C++和服务器交互的几个文件代码

cjson.h文件

/*
  Copyright (c) 2009 Dave Gamble
 
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
 
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
 
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

#ifndef cJSON__h
#define cJSON__h

#ifdef __cplusplus
extern "C"
{
#endif

/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
	
#define cJSON_IsReference 256

/* The cJSON structure: */
typedef struct cJSON {
	struct cJSON *next,*prev;	/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
	struct cJSON *child;		/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */

	int type;					/* The type of the item, as above. */

	char *valuestring;			/* The item's string, if type==cJSON_String */
	int valueint;				/* The item's number, if type==cJSON_Number */
	double valuedouble;			/* The item's number, if type==cJSON_Number */

	char *string;				/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;

typedef struct cJSON_Hooks {
      void *(*malloc_fn)(size_t sz);
      void (*free_fn)(void *ptr);
} cJSON_Hooks;

/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);


/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char  *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char  *cJSON_PrintUnformatted(cJSON *item);
/* Delete a cJSON entity and all subentities. */
extern void   cJSON_Delete(cJSON *c);

/* Returns the number of items in an array (or object). */
extern int	  cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);

/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
extern const char *cJSON_GetErrorPtr();
	
/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull();
extern cJSON *cJSON_CreateTrue();
extern cJSON *cJSON_CreateFalse();
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray();
extern cJSON *cJSON_CreateObject();

/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);

/* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void	cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void	cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);

/* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);
	
/* Update array items. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);

#define cJSON_AddNullToObject(object,name)	cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name)	cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name)		cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b)		cJSON_AddItemToObject(object, name, b ? cJSON_CreateTrue() : cJSON_CreateFalse())
#define cJSON_AddNumberToObject(object,name,n)	cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s)	cJSON_AddItemToObject(object, name, cJSON_CreateString(s))

#define cJSON_AddNullToArray(array) cJSON_AddItemToArray(array, cJSON_CreateNull());
#define cJSON_AddTrueToArray(array) cJSON_AddItemToArray(array, cJSON_CreateTrue());
#define cJSON_AddFalseToArray(array) cJSON_AddItemToArray(array, cJSON_CreateFalse());
#define cJSON_AddBoolToArray(array, b)		cJSON_AddItemToArray(array, b ? cJSON_CreateTrue() : cJSON_CreateFalse())
#define cJSON_AddNumberToArray(array, n) cJSON_AddItemToArray(array, cJSON_CreateNumber(n));
#define cJSON_AddStringToArray(array, s) cJSON_AddItemToArray(array, cJSON_CreateString(s));

extern int cJSON_GetObjectValueInt(cJSON *object, const char *string);
extern const char *cJSON_GetObjectValueString(cJSON *object, const char *string);
extern double cJSON_GetObjectValueDouble(cJSON *object, const char *string);
extern int cJSON_GetObjectValueBool(cJSON *object, const char *string);

#ifdef __cplusplus
}
#endif

#endif

cjson.cpp文件

/*
  Copyright (c) 2009 Dave Gamble

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

/* cJSON */
/* JSON parser in C. */

#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "cJSON.h"

static const char *ep;

const char *cJSON_GetErrorPtr() {return ep;}

static int cJSON_strcasecmp(const char *s1,const char *s2)
{
	if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
	for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)	if(*s1 == 0)	return 0;
	return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}

static void *_malloc(size_t size)
{
	//malloc in some system, malloc(0) will return NULL. But, cJSON need a valid pointer
	if (size == 0)
		size++;
	return malloc(size);
}

static void *(*cJSON_malloc)(size_t sz) = _malloc;
static void (*cJSON_free)(void *ptr) = free;

static char* cJSON_strdup(const char* str)
{
      size_t len;
      char* copy;

      len = strlen(str) + 1;
      if (!(copy = (char*)cJSON_malloc(len))) return 0;
      memcpy(copy,str,len);
      return copy;
}

void cJSON_InitHooks(cJSON_Hooks* hooks)
{
    if (!hooks) { /* Reset hooks */
        cJSON_malloc = _malloc;
        cJSON_free = free;
        return;
    }

	cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:_malloc;
	cJSON_free	 = (hooks->free_fn)?hooks->free_fn:free;
}

/* Internal constructor. */
static cJSON *cJSON_New_Item()
{
	cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
	if (node) memset(node,0,sizeof(cJSON));
	return node;
}

/* Delete a cJSON structure. */
void cJSON_Delete(cJSON *c)
{
	cJSON *next;
	while (c)
	{
		next=c->next;
		if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
		if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
		if (c->string) cJSON_free(c->string);
		cJSON_free(c);
		c=next;
	}
}

/* Parse the input text to generate a number, and populate the result into item. */
static const char *parse_number(cJSON *item,const char *num)
{
	double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;

	/* Could use sscanf for this? */
	if (*num=='-') sign=-1,num++;	/* Has sign? */
	while (*num && *num=='0') num++;			/* is zero */
	if (*num>='1' && *num<='9')	do	n=(n*10.0)+(*num++ -'0');	while (*num>='0' && *num<='9');	/* Number? */
	if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;		do	n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}	/* Fractional part? */
	if (*num=='e' || *num=='E')		/* Exponent? */
	{	num++;if (*num=='+') num++;	else if (*num=='-') signsubscale=-1,num++;		/* With sign? */
		while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');	/* Number? */
	}

	n=sign*n*pow(10.0,(scale+subscale*signsubscale));	/* number = +/- number.fraction * 10^+/- exponent */
	
	item->valuedouble=n;
	item->valueint=(int)n;
	item->type=cJSON_Number;
	return num;
}

/* Render the number nicely from the given item into a string. */
static char *print_number(cJSON *item)
{
	char *str;
	double d=item->valuedouble;
	if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
	{
		str=(char*)cJSON_malloc(21);	/* 2^64+1 can be represented in 21 chars. */
		if (str) sprintf(str,"%d",item->valueint);
	}
	else
	{
		str=(char*)cJSON_malloc(64);	/* This is a nice tradeoff. */
		if (str)
		{
			if (fabs(floor(d)-d)<=DBL_EPSILON)			sprintf(str,"%.0f",d);
			else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)	sprintf(str,"%e",d);
			else										sprintf(str,"%f",d);
		}
	}
	return str;
}

/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(cJSON *item,const char *str)
{
	const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
	if (*str!='\"') {ep=str;return 0;}	/* not a string! */
	
	while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++;	/* Skip escaped quotes. */
	
	out=(char*)cJSON_malloc(len+1);	/* This is how long we need for the string, roughly. */
	if (!out) return 0;
	
	ptr=str+1;ptr2=out;
	while (*ptr!='\"' && *ptr)
	{
		if (*ptr!='\\') *ptr2++=*ptr++;
		else
		{
			ptr++;
			switch (*ptr)
			{
				case 'b': *ptr2++='\b';	break;
				case 'f': *ptr2++='\f';	break;
				case 'n': *ptr2++='\n';	break;
				case 'r': *ptr2++='\r';	break;
				case 't': *ptr2++='\t';	break;
				case 'u':	 /* transcode utf16 to utf8. */
					sscanf(ptr+1,"%4x",&uc);ptr+=4;	/* get the unicode char. */

					if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)	break;	// check for invalid.

					if (uc>=0xD800 && uc<=0xDBFF)	// UTF16 surrogate pairs.
					{
						if (ptr[1]!='\\' || ptr[2]!='u')	break;	// missing second-half of surrogate.
						sscanf(ptr+3,"%4x",&uc2);ptr+=6;
						if (uc2<0xDC00 || uc2>0xDFFF)		break;	// invalid second-half of surrogate.
						uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF);
					}

					len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
					
					switch (len) {
						case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
						case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
						case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
						case 1: *--ptr2 =(uc | firstByteMark[len]);
					}
					ptr2+=len;
					break;
				default:  *ptr2++=*ptr; break;
			}
			ptr++;
		}
	}
	*ptr2=0;
	if (*ptr=='\"') ptr++;
	item->valuestring=out;
	item->type=cJSON_String;
	return ptr;
}

/* Render the cstring provided to an escaped version that can be printed. */
static char *print_string_ptr(const char *str)
{
	const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
	
	if (!str) return cJSON_strdup("");
	ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
	
	out=(char*)cJSON_malloc(len+3);
	if (!out) return 0;

	ptr2=out;ptr=str;
	*ptr2++='\"';
	while (*ptr)
	{
		if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
		else
		{
			*ptr2++='\\';
			switch (token=*ptr++)
			{
				case '\\':	*ptr2++='\\';	break;
				case '\"':	*ptr2++='\"';	break;
				case '\b':	*ptr2++='b';	break;
				case '\f':	*ptr2++='f';	break;
				case '\n':	*ptr2++='n';	break;
				case '\r':	*ptr2++='r';	break;
				case '\t':	*ptr2++='t';	break;
				default: sprintf(ptr2,"u%04x",token);ptr2+=5;	break;	/* escape and print */
			}
		}
	}
	*ptr2++='\"';*ptr2++=0;
	return out;
}
/* Invote print_string_ptr (which is useful) on an item. */
static char *print_string(cJSON *item)	{return print_string_ptr(item->valuestring);}

/* Predeclare these prototypes. */
static const char *parse_value(cJSON *item,const char *value);
static char *print_value(cJSON *item,int depth,int fmt);
static const char *parse_array(cJSON *item,const char *value);
static char *print_array(cJSON *item,int depth,int fmt);
static const char *parse_object(cJSON *item,const char *value);
static char *print_object(cJSON *item,int depth,int fmt);

/* Utility to jump whitespace and cr/lf */
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}

/* Parse an object - create a new root, and populate. */
cJSON *cJSON_Parse(const char *value)
{
	cJSON *c=cJSON_New_Item();
	ep=0;
	if (!c) return 0;       /* memory fail */

	if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
	return c;
}

/* Render a cJSON item/entity/structure to text. */
char *cJSON_Print(cJSON *item)				{return print_value(item,0,1);}
char *cJSON_PrintUnformatted(cJSON *item)	{return print_value(item,0,0);}

/* Parser core - when encountering text, process appropriately. */
static const char *parse_value(cJSON *item,const char *value)
{
	if (!value)						return 0;	/* Fail on null. */
	if (!strncmp(value,"null",4))	{ item->type=cJSON_NULL;  return value+4; }
	if (!strncmp(value,"false",5))	{ item->type=cJSON_False; return value+5; }
	if (!strncmp(value,"true",4))	{ item->type=cJSON_True; item->valueint=1;	return value+4; }
	if (*value=='\"')				{ return parse_string(item,value); }
	if (*value=='-' || (*value>='0' && *value<='9'))	{ return parse_number(item,value); }
	if (*value=='[')				{ return parse_array(item,value); }
	if (*value=='{')				{ return parse_object(item,value); }

	ep=value;return 0;	/* failure. */
}

/* Render a value to text. */
static char *print_value(cJSON *item,int depth,int fmt)
{
	char *out=0;
	if (!item) return 0;
	switch ((item->type)&255)
	{
		case cJSON_NULL:	out=cJSON_strdup("null");	break;
		case cJSON_False:	out=cJSON_strdup("false");break;
		case cJSON_True:	out=cJSON_strdup("true"); break;
		case cJSON_Number:	out=print_number(item);break;
		case cJSON_String:	out=print_string(item);break;
		case cJSON_Array:	out=print_array(item,depth,fmt);break;
		case cJSON_Object:	out=print_object(item,depth,fmt);break;
	}
	return out;
}

/* Build an array from input text. */
static const char *parse_array(cJSON *item,const char *value)
{
	cJSON *child;
	if (*value!='[')	{ep=value;return 0;}	/* not an array! */

	item->type=cJSON_Array;
	value=skip(value+1);
	if (*value==']') return value+1;	/* empty array. */

	item->child=child=cJSON_New_Item();
	if (!item->child) return 0;		 /* memory fail */
	value=skip(parse_value(child,skip(value)));	/* skip any spacing, get the value. */
	if (!value) return 0;

	while (*value==',')
	{
		cJSON *new_item;
		if (!(new_item=cJSON_New_Item())) return 0; 	/* memory fail */
		child->next=new_item;new_item->prev=child;child=new_item;
		value=skip(parse_value(child,skip(value+1)));
		if (!value) return 0;	/* memory fail */
	}

	if (*value==']') return value+1;	/* end of array */
	ep=value;return 0;	/* malformed. */
}

/* Render an array to text */
static char *print_array(cJSON *item,int depth,int fmt)
{
	char **entries;
	char *out=0,*ptr,*ret;int len=5;
	cJSON *child=item->child;
	int numentries=0,i=0,fail=0;
	
	/* How many entries in the array? */
	while (child) numentries++,child=child->next;
	/* Allocate an array to hold the values for each */
	entries=(char**)cJSON_malloc(numentries*sizeof(char*));
	if (!entries) return 0;
	memset(entries,0,numentries*sizeof(char*));
	/* Retrieve all the results: */
	child=item->child;
	while (child && !fail)
	{
		ret=print_value(child,depth+1,fmt);
		entries[i++]=ret;
		if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
		child=child->next;
	}
	
	/* If we didn't fail, try to malloc the output string */
	if (!fail) out=(char*)cJSON_malloc(len);
	/* If that fails, we fail. */
	if (!out) fail=1;

	/* Handle failure. */
	if (fail)
	{
		for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
		cJSON_free(entries);
		return 0;
	}
	
	/* Compose the output array. */
	*out='[';
	ptr=out+1;*ptr=0;
	for (i=0;i<numentries;i++)
	{
		strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
		if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
		cJSON_free(entries[i]);
	}
	cJSON_free(entries);
	*ptr++=']';*ptr++=0;
	return out;	
}

/* Build an object from the text. */
static const char *parse_object(cJSON *item,const char *value)
{
	cJSON *child;
	if (*value!='{')	{ep=value;return 0;}	/* not an object! */
	
	item->type=cJSON_Object;
	value=skip(value+1);
	if (*value=='}') return value+1;	/* empty array. */
	
	item->child=child=cJSON_New_Item();
	if (!item->child) return 0;
	value=skip(parse_string(child,skip(value)));
	if (!value) return 0;
	child->string=child->valuestring;child->valuestring=0;
	if (*value!=':') {ep=value;return 0;}	/* fail! */
	value=skip(parse_value(child,skip(value+1)));	/* skip any spacing, get the value. */
	if (!value) return 0;
	
	while (*value==',')
	{
		cJSON *new_item;
		if (!(new_item=cJSON_New_Item()))	return 0; /* memory fail */
		child->next=new_item;new_item->prev=child;child=new_item;
		value=skip(parse_string(child,skip(value+1)));
		if (!value) return 0;
		child->string=child->valuestring;child->valuestring=0;
		if (*value!=':') {ep=value;return 0;}	/* fail! */
		value=skip(parse_value(child,skip(value+1)));	/* skip any spacing, get the value. */
		if (!value) return 0;
	}
	
	if (*value=='}') return value+1;	/* end of array */
	ep=value;return 0;	/* malformed. */
}

/* Render an object to text. */
static char *print_object(cJSON *item,int depth,int fmt)
{
	char **entries=0,**names=0;
	char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
	cJSON *child=item->child;
	int numentries=0,fail=0;
	/* Count the number of entries. */
	while (child) numentries++,child=child->next;
	/* Allocate space for the names and the objects */
	entries=(char**)cJSON_malloc(numentries*sizeof(char*));
	if (!entries) return 0;
	names=(char**)cJSON_malloc(numentries*sizeof(char*));
	if (!names) {cJSON_free(entries);return 0;}
	memset(entries,0,sizeof(char*)*numentries);
	memset(names,0,sizeof(char*)*numentries);

	/* Collect all the results into our arrays: */
	child=item->child;depth++;if (fmt) len+=depth;
	while (child)
	{
		names[i]=str=print_string_ptr(child->string);
		entries[i++]=ret=print_value(child,depth,fmt);
		if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
		child=child->next;
	}
	
	/* Try to allocate the output string */
	if (!fail) out=(char*)cJSON_malloc(len);
	if (!out) fail=1;

	/* Handle failure */
	if (fail)
	{
		for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
		cJSON_free(names);cJSON_free(entries);
		return 0;
	}
	
	/* Compose the output: */
	*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
	for (i=0;i<numentries;i++)
	{
		if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
		strcpy(ptr,names[i]);ptr+=strlen(names[i]);
		*ptr++=':';if (fmt) *ptr++='\t';
		strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
		if (i!=numentries-1) *ptr++=',';
		if (fmt) *ptr++='\n';*ptr=0;
		cJSON_free(names[i]);cJSON_free(entries[i]);
	}
	
	cJSON_free(names);cJSON_free(entries);
	if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
	*ptr++='}';*ptr++=0;
	return out;	
}

/* Get Array size/item / object item. */
int    cJSON_GetArraySize(cJSON *array)							{cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
cJSON *cJSON_GetArrayItem(cJSON *array,int item)				{cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)	{cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}

/* Utility for array list handling. */
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
/* Utility for handling references. */
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}

/* Add item to array/object. */
void   cJSON_AddItemToArray(cJSON *array, cJSON *item)						{cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
void   cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item)	{if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
void	cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)						{cJSON_AddItemToArray(array,create_reference(item));}
void	cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)	{cJSON_AddItemToObject(object,string,create_reference(item));}

cJSON *cJSON_DetachItemFromArray(cJSON *array,int which)			{cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
	if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
void   cJSON_DeleteItemFromArray(cJSON *array,int which)			{cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}

/* Replace array/object items with new ones. */
void   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)		{cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
	newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
	if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
void   cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}

/* Create basic types: */
cJSON *cJSON_CreateNull()						{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue()						{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse()						{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
cJSON *cJSON_CreateBool(int b)					{cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
cJSON *cJSON_CreateNumber(double num)			{cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
cJSON *cJSON_CreateString(const char *string)	{cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
cJSON *cJSON_CreateArray()						{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject()						{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}

/* Create Arrays: */
cJSON *cJSON_CreateIntArray(int *numbers,int count)				{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateFloatArray(float *numbers,int count)			{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateDoubleArray(double *numbers,int count)		{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateStringArray(const char **strings,int count)	{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}

/* Get Object value Directly */
int cJSON_GetObjectValueInt(cJSON *object, const char *string)
{
	cJSON *item = cJSON_GetObjectItem(object, string);
	if (item && item->type == cJSON_Number)
	{
		return item->valueint;
	}

	return -1;
}

const char *cJSON_GetObjectValueString(cJSON *object, const char *string)
{
	cJSON *item = cJSON_GetObjectItem(object, string);
	if (item && item->type == cJSON_String)
	{
		return item->valuestring;
	}

	return NULL;
}

double cJSON_GetObjectValueDouble(cJSON *object, const char *string)
{
	cJSON *item = cJSON_GetObjectItem(object, string);
	if (item && item->type == cJSON_Number)
	{
		return item->valuedouble;
	}

	return 0.0;
}

int cJSON_GetObjectValueBool(cJSON *object, const char *string)
{
	cJSON *item = cJSON_GetObjectItem(object, string);
	if (item && item->type == cJSON_True)
	{
		return item->type;
	}

	return cJSON_False;
}

cjson_derect.h


#ifndef _CJSON_DIRECT_H_
#define _CJSON_DIRECT_H_

#ifdef __cplusplus
extern "C"
{
#endif

typedef enum {
	KEY_TYPE_NULL,
	KEY_TYPE_U8,
	KEY_TYPE_U16,
	KEY_TYPE_U32,
	KEY_TYPE_FLOAT,
	KEY_TYPE_DOUBLE,
	KEY_TYPE_STRING,	//数组存储的字符串

	/**
	 * 外部存储的字符串。
	 * 对于cjson_string2object形成的结构体,
	 * 需要调用cjson_string2object_array_free 释放资源
	 *
	 */
	KEY_TYPE_STRING_PTR,	//

	KEY_TYPE_OBJECT,

	/**
		 注意,如果是字符串数组,只支持二维数组,而且不支持外部字符串
		 char stringArray[2][3];// 这种是支持的
		 char *stringArray[2];//这种是不支持的。因为它有外部字符串
	*/
	KEY_TYPE_ARRAY,
	KEY_TYPE_MAX
}key_type_e;


typedef struct key_info_s{
	int csize;					///< 本结构体大小
	key_type_e type;				///< 成员类型
	char *key;					///< 成员名称
	int offset;					///< 成员偏移地址
	int ksize;						///< 成员大小
	struct key_info_s *sub_key;	///< 对于#KEY_TYPE_OBJECT类型,其具体类型定义
	int arraycnt;					///< 对于#KEY_TYPE_ARRAY类型,其个数
	key_type_e arraytype;		///< 对于#KEY_TYPE_ARRAY类型,其成员的类型
}json_kinfo_t;


/*成员在结构体中的偏移地址*/
#define NAME_OFFSET(type,name) ((int)(&(((type *)0)->name)))
#define NAME_SIZE(type,name) (sizeof((((type *)0)->name)))


/**
 *@brief 形成结构体
 *@param ctype 结构体类型
 *@param ktype 成员类型
 *@param kname 成员名
 *@param subkey 如果keytype为#KEY_TYPE_OBJECT,则为其对应结构体的#json_kinfo_t 指针
 *@param arraycnt 对于#KEY_TYPE_ARRAY类型,其个数
 *@param arraytype 对于#KEY_TYPE_ARRAY类型,其成员的类型
 *
 */
#define MAKE_ARRAY_INFO(ctype, ktype, kname, subkey, arraycnt, arraytype) {sizeof(ctype), ktype, #kname, NAME_OFFSET(ctype,kname), NAME_SIZE(ctype,kname), subkey, arraycnt, arraytype}

#define MAKE_KEY_INFO(ctype, ktype, kname, subkey) MAKE_ARRAY_INFO(ctype, ktype, kname, subkey, 0, KEY_TYPE_NULL)
#define MAKE_END_INFO()	{0, KEY_TYPE_NULL, NULL, 0, 0, NULL}


/**
 *@brief 将JSON格式的字符串转化为结构体
 *@param kinfo 输入 结构体信息,用于识别结构体各成员
 *@param string 输入 要转化的字符串
 *@param obj 输出 结构体指针。如果为NULL,会自动分配内存,需要释放
 *
 *@return obj。失败时返回NULL
 *
 */
void *cjson_string2object(json_kinfo_t *kinfo, char *string, void *obj);

/**
 *@brief 将JSON格式的字符串转化为结构体数组
 *@param kinfo 输入 结构体信息,用于识别结构体各成员
 *@param string 输入 要转化的字符串
 *@param obj_array 输出 结构体数组的指针。如果为NULL,会自动分配内存,需要释放
 *@param maxCnt 输入 最多能装载的obj的个数
 *@param cnt 输出 实际得到的obj的个数
 *
 *@return obj。失败时返回NULL
 *
 */
void *cjson_string2object_array(json_kinfo_t *kinfo, char *string, void *obj_array, int maxCnt, int *cnt);

/**
 *@brief 将#cjson_string2object 或 #cjson_string2object_array 转化后的结构体,做必要的释放操作。
 *@param kinfo 输入 结构体信息,用于识别结构体各成员
 *@param obj_array 需要释放的资源
 *@param cnt 输入 实际得到的obj的个数。对于 #cjson_string2object ,cnt为1
 *
 */
void cjson_string2object_array_free(json_kinfo_t *kinfo, void *obj_array, int cnt);

/**
 *@brief 将结构体转化为字符串
 *@param kinfo 输入 结构体信息,用于识别结构体各成员
 *@param obj 输入 要转化的结构体地址
 *
 *@return json格式的字符串。NULL if failed
 *
 *@note 其返回的字符串,需要用free释放
 *
 */
char *cjson_object2string(json_kinfo_t *kinfo, void *obj);

/**
 *@brief 将结构体数组转化为JSON字符串
 *@param kinfo 输入 结构体信息,用于识别结构体各成员
 *@param obj_array 输入 要转化的结构体数组的指针
 *@param cnt 数组个数
 *
 *@return json格式的字符串。NULL if failed
 *
 *@note 其返回的字符串,需要用free释放
 *
 */
char *cjson_object_array2string(json_kinfo_t *kinfo, void *obj_array, int cnt);


#ifdef __cplusplus
}
#endif

#endif


cjson_derect.cpp

在这里插入代码片

#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "cJSON.h"

#include "cJSON_Direct.h"

#define KEY_ADDR(obj, offset)  (((unsigned char *)obj) + offset)

#define KEY_ADDR_U8(obj, offset) ((unsigned char *)KEY_ADDR(obj, offset))
#define KEY_ADDR_U16(obj, offset) ((unsigned short *)KEY_ADDR(obj, offset))
#define KEY_ADDR_U32(obj, offset) ((unsigned int *)KEY_ADDR(obj, offset))
#define KEY_ADDR_FLOAT(obj, offset) ((float *)KEY_ADDR(obj, offset))
#define KEY_ADDR_DOUBLE(obj, offset) ((double *)KEY_ADDR(obj, offset))

#define json_assert(x,express) do{\
		if (!(x))\
		{\
			printf("[%s] json_assert failed\n", __FUNCTION__);\
			express;\
		}\
	}while(0)


static void _cjson2obj(json_kinfo_t *kinfo, cJSON *json, void *obj)
{
	int i,j,cnt;
	cJSON *sub, *item;

	for (i=0;kinfo[i].key != NULL;i++)
	{
		sub = cJSON_GetObjectItem(json,kinfo[i].key);
		if (!sub)
			continue;
		switch(kinfo[i].type)
		{
		default:
			break;
		case KEY_TYPE_U8:
			*KEY_ADDR_U8(obj, kinfo[i].offset) = sub->valueint;
			break;
		case KEY_TYPE_U16:
			*KEY_ADDR_U16(obj, kinfo[i].offset) = sub->valueint;
			break;
		case KEY_TYPE_U32:
			*KEY_ADDR_U32(obj, kinfo[i].offset) = sub->valueint;
			break;
		case KEY_TYPE_FLOAT:
			*KEY_ADDR_FLOAT(obj, kinfo[i].offset) = sub->valuedouble;
			break;
		case KEY_TYPE_DOUBLE:
			*KEY_ADDR_DOUBLE(obj, kinfo[i].offset) = sub->valuedouble;
			break;
		case KEY_TYPE_STRING:
			memcpy(KEY_ADDR_U8(obj, kinfo[i].offset), sub->valuestring, kinfo[i].ksize);
			//set the last byte be '\0', to avoid no string end.
			KEY_ADDR_U8(obj, kinfo[i].offset) [kinfo[i].ksize-1] = '\0';
			break;
		case KEY_TYPE_STRING_PTR:
		{
			char *temp = strdup(sub->valuestring);
			*KEY_ADDR_U32(obj, kinfo[i].offset) = (unsigned int)temp;
		}
			break;
		case KEY_TYPE_ARRAY:
			cnt = cJSON_GetArraySize(sub);
			switch(kinfo[i].arraytype)
			{
			default:
				printf(" %d Not Support\n", kinfo[i].arraytype);
				break;
			case KEY_TYPE_STRING:
				for (j=0;j<cnt && j<kinfo[i].arraycnt;j++)
				{
					int strMaxLen = (kinfo[i].ksize / kinfo[i].arraycnt);
					item = cJSON_GetArrayItem(sub, j);
					memcpy(KEY_ADDR_U8(obj, kinfo[i].offset) + j * strMaxLen, item->valuestring, strMaxLen);
					//set the last byte be '\0', to avoid no string end.
					(KEY_ADDR_U8(obj, kinfo[i].offset) + j * strMaxLen)[strMaxLen-1] = '\0';
				}
				break;
			case KEY_TYPE_STRING_PTR:
				for (j=0;j<cnt && j<kinfo[i].arraycnt;j++)
				{
					int strMaxLen = (kinfo[i].ksize / kinfo[i].arraycnt);
					item = cJSON_GetArrayItem(sub, j);
					{
						char *temp = strdup(item->valuestring);
						*(KEY_ADDR_U32(obj, kinfo[i].offset) + j) = (unsigned int)temp;
					}
				}
				break;
			case KEY_TYPE_U8:
				for (j=0;j<cnt && j<kinfo[i].arraycnt;j++)
				{
					item = cJSON_GetArrayItem(sub, j);
					if (item)
						KEY_ADDR_U8(obj, kinfo[i].offset)[j] = item->valueint;
				}
				break;
			case KEY_TYPE_U16:
				for (j=0;j<cnt && j<kinfo[i].arraycnt;j++)
				{
					item = cJSON_GetArrayItem(sub, j);
					if (item)
						KEY_ADDR_U16(obj, kinfo[i].offset)[j] = item->valueint;
				}
				break;
			case KEY_TYPE_U32:
				for (j=0;j<cnt && j<kinfo[i].arraycnt;j++)
				{
					item = cJSON_GetArrayItem(sub, j);
					if (item)
						KEY_ADDR_U32(obj, kinfo[i].offset)[j] = item->valueint;
				}
				break;
			case KEY_TYPE_FLOAT:
				for (j=0;j<cnt && j<kinfo[i].arraycnt;j++)
				{
					item = cJSON_GetArrayItem(sub, j);
					if (item)
						KEY_ADDR_FLOAT(obj, kinfo[i].offset)[j] = item->valuedouble;
				}
				break;
			case KEY_TYPE_DOUBLE:
				for (j=0;j<cnt && j<kinfo[i].arraycnt;j++)
				{
					item = cJSON_GetArrayItem(sub, j);
					if (item)
						KEY_ADDR_DOUBLE(obj, kinfo[i].offset)[j] = item->valuedouble;
				}
				break;
			case KEY_TYPE_OBJECT:
				for (j=0;j<cnt && j<kinfo[i].arraycnt;j++)
				{
					item = cJSON_GetArrayItem(sub, j);
					if (item)
						_cjson2obj(kinfo[i].sub_key, item, KEY_ADDR_U8(obj, kinfo[i].offset) + (kinfo[i].sub_key->csize * j));
				}
				break;
			}
			break;
		case KEY_TYPE_OBJECT:
			_cjson2obj(kinfo[i].sub_key, sub, KEY_ADDR_U8(obj, kinfo[i].offset));
			break;
		}
	}
}

void *cjson_string2object(json_kinfo_t *kinfo, char *string, void *obj)
{
	cJSON *json = cJSON_Parse(string);

	if (obj == NULL)
		obj = malloc(kinfo[0].csize);				//注意防止内存泄露
//	json_assert(json, return NULL);
	_cjson2obj(kinfo, json, obj);
	cJSON_Delete(json);
	return obj;
}

/**
 *@brief 
 *@param kinfo 输入 结构体信息,用于识别结构体各成员
 *@param string 输入 要转化的字符串
 *@param obj_array 输出 结构体数组的指针。如果为NULL,会自动分配内存,需要释放
 *@param maxCnt 输入 最多能装载的obj的个数
 *@param cnt 输出 实际得到的obj的个数
 *
 *@return obj。失败时返回NULL
 *
 */
void *cjson_string2object_array(json_kinfo_t *kinfo, char *string, void *obj_array, int maxCnt, int *cnt)
{
	cJSON *json = cJSON_Parse(string);
	cJSON *sub;
	int i;

//	json_assert(json, return NULL);
	*cnt = cJSON_GetArraySize(json);

	if (obj_array == NULL)
	{
		obj_array = malloc(kinfo[0].csize * (*cnt));
//		json_assert(obj_array, return NULL);
	}
	else if (*cnt > maxCnt)
		*cnt = maxCnt;

	for (i=0;i<*cnt;i++)
	{
		sub = cJSON_GetArrayItem(json,i);
		_cjson2obj(kinfo, sub, (char *)obj_array + (kinfo->csize * i));
	}
	return obj_array;
}

static cJSON *_obj2cjson(json_kinfo_t *kinfo, cJSON *json, void *obj)
{
	int i,j;
	cJSON *sub;
	unsigned char *addr;

	for (i=0;kinfo[i].key != NULL;i++)
	{
		switch(kinfo[i].type)
		{
		default:
			printf(" %d Not Support\n", kinfo[i].arraytype);
			break;
		case KEY_TYPE_U8:
			cJSON_AddNumberToObject(json,kinfo[i].key, *KEY_ADDR_U8(obj, kinfo[i].offset));
			break;
		case KEY_TYPE_U16:
			cJSON_AddNumberToObject(json,kinfo[i].key, *KEY_ADDR_U16(obj, kinfo[i].offset));
			break;
		case KEY_TYPE_U32:
			cJSON_AddNumberToObject(json,kinfo[i].key, *KEY_ADDR_U32(obj, kinfo[i].offset));
			break;
		case KEY_TYPE_FLOAT:
			cJSON_AddNumberToObject(json,kinfo[i].key, *KEY_ADDR_FLOAT(obj, kinfo[i].offset));
			break;
		case KEY_TYPE_DOUBLE:
			cJSON_AddNumberToObject(json,kinfo[i].key, *KEY_ADDR_DOUBLE(obj, kinfo[i].offset));
			break;
		case KEY_TYPE_STRING:
			cJSON_AddStringToObject(json, kinfo[i].key, (char *)KEY_ADDR_U8(obj, kinfo[i].offset));
			break;
		case KEY_TYPE_STRING_PTR:
			cJSON_AddStringToObject(json, kinfo[i].key, (char *)(*KEY_ADDR_U32(obj, kinfo[i].offset)));
			break;
		case KEY_TYPE_ARRAY:
			switch(kinfo[i].arraytype)
			{
			default:
				printf(" %d Not Support\n", kinfo[i].arraytype);
				sub = NULL;
				break;
			case KEY_TYPE_STRING:
				//printf(" %d Not Support\n", kinfo[i].arraytype);
				/*注意,这里只支持二维数组方式保存的字符串数组*/
				sub = cJSON_CreateArray();
				for (j=0;j<kinfo[i].arraycnt;j++)
				{
					cJSON_AddItemToArray(sub,
						cJSON_CreateString((char *)KEY_ADDR_U8(obj, kinfo[i].offset) + j * (kinfo[i].ksize / kinfo[i].arraycnt)));
				}
				break;
			case KEY_TYPE_STRING_PTR:
				sub = cJSON_CreateArray();
				for (j=0;j<kinfo[i].arraycnt;j++)
				{
					cJSON_AddItemToArray(sub,
						cJSON_CreateString((char *)(*(KEY_ADDR_U32(obj, kinfo[i].offset) + j)))
						);
				}
				break;
			case KEY_TYPE_U8:
				sub = cJSON_CreateArray();
				for (j=0;j<kinfo[i].arraycnt;j++)
				{
					cJSON_AddItemToArray(sub,cJSON_CreateNumber(KEY_ADDR_U8(obj, kinfo[i].offset)[j]));
				}
				break;
			case KEY_TYPE_U16:
				sub = cJSON_CreateArray();
				for (j=0;j<kinfo[i].arraycnt;j++)
				{
					cJSON_AddItemToArray(sub,cJSON_CreateNumber(KEY_ADDR_U16(obj, kinfo[i].offset)[j]));
				}
				break;
			case KEY_TYPE_U32:
				sub = cJSON_CreateIntArray((int*)KEY_ADDR_U32(obj, kinfo[i].offset), kinfo[i].arraycnt);
				break;
			case KEY_TYPE_FLOAT:
				sub = cJSON_CreateFloatArray(KEY_ADDR_FLOAT(obj, kinfo[i].offset), kinfo[i].arraycnt);
				break;
			case KEY_TYPE_DOUBLE:
				sub = cJSON_CreateDoubleArray(KEY_ADDR_DOUBLE(obj, kinfo[i].offset), kinfo[i].arraycnt);
				break;
			case KEY_TYPE_OBJECT:
				if (kinfo[i].sub_key == NULL)
				{
					printf("ERROR: kinfo[i].sub_key should not be NULL\n");
					break;
				}
				sub = cJSON_CreateArray();
				addr = KEY_ADDR_U8(obj, kinfo[i].offset);
				for (j=0;j<kinfo[i].arraycnt;j++)
				{
					cJSON_AddItemToArray(sub, _obj2cjson(kinfo[i].sub_key, cJSON_CreateObject(), addr + (kinfo[i].sub_key->csize * j)));
				}
				break;
			}
			cJSON_AddItemToObject(json, kinfo[i].key, sub);
			break;
		case KEY_TYPE_OBJECT:
			cJSON_AddItemToObject(json, kinfo[i].key, _obj2cjson(kinfo[i].sub_key, cJSON_CreateObject(), KEY_ADDR(obj, kinfo[i].offset)));
			break;
		}
	}
	return json;
}

void cjson_string2object_free(json_kinfo_t *kinfo, void *obj)
{
	int i,j;
	cJSON *sub;
	unsigned char *addr;

	for (i=0;kinfo[i].key != NULL;i++)
	{
		switch(kinfo[i].type)
		{
		default:
			break;
		case KEY_TYPE_STRING_PTR:
		{
			char *temp = (char *)(*KEY_ADDR_U32(obj, kinfo[i].offset));
//			printf("test free: %d : %x\n", __LINE__, temp);
			if (temp)
				free(temp);
		}
			break;
		case KEY_TYPE_ARRAY:
			switch(kinfo[i].arraytype)
			{
			default:
				break;
			case KEY_TYPE_STRING_PTR:
				for (j=0;j<kinfo[i].arraycnt;j++)
				{
					char *temp = (char *)(*(KEY_ADDR_U32(obj, kinfo[i].offset) + j));
//					printf("test free: %d : %x\n", __LINE__, temp);
					if (temp)
						free(temp);
				}
				break;
			}
			break;
		}
	}
	return ;
}

/**
 *@brief 将#cjson_string2object 或 #cjson_string2object_array 转化后的结构体,做必要的释放操作。
 *@param kinfo 输入 结构体信息,用于识别结构体各成员
 *@param obj_array 需要释放的资源
 *@param cnt 输入 实际得到的obj的个数。对于 #cjson_string2object ,cnt为1
 *
 */
void cjson_string2object_array_free(json_kinfo_t *kinfo, void *obj_array, int cnt)
{
	int i;
	for (i=0;i<cnt;i++)
	{
		cjson_string2object_free(kinfo, (char *)obj_array + (kinfo->csize * i));
	}
}

char *cjson_object2string(json_kinfo_t *kinfo, void *obj)
{
	cJSON *json = cJSON_CreateObject();
	char *out;

	_obj2cjson(kinfo, json, obj);
	out = cJSON_Print(json);
	cJSON_Delete(json);

	return out;
}

/**
 *@brief 
 *@param kinfo 输入 结构体信息,用于识别结构体各成员
 *@param obj_array 输入 要转化的结构体数组的指针
 *@param cnt 数组个数
 *
 *@return json格式的字符串。NULL if failed
 *
 *@note 其返回的字符串,需要用free释放
 *
 */
char *cjson_object_array2string(json_kinfo_t *kinfo, void *obj_array, int cnt)
{
	cJSON *json = cJSON_CreateArray();
	cJSON *item;
	char *out;
	int i;

	for (i=0;i<cnt;i++)
	{
		item = cJSON_CreateObject();
		_obj2cjson(kinfo, item, (char *)obj_array + (kinfo->csize * i));
		cJSON_AddItemToArray(json,item);
	}

	out = cJSON_Print(json);
	cJSON_Delete(json);
	return out;
}







typedef struct tagRECT
{
	unsigned int		x;
	unsigned int		y;
	unsigned int		w;
	unsigned int		h;
}RECT, *PRECT;


static json_kinfo_t rect_key[] = {
	MAKE_KEY_INFO(RECT, KEY_TYPE_U32, x, NULL),
	MAKE_KEY_INFO(RECT, KEY_TYPE_U32, y, NULL),
	MAKE_KEY_INFO(RECT, KEY_TYPE_U32, w, NULL),
	MAKE_KEY_INFO(RECT, KEY_TYPE_U32, h, NULL),
	MAKE_END_INFO()
};


typedef struct tagMD
{
	int			bEnable;			//是否开启移动检测
	unsigned int	nSensitivity;		//灵敏度
	unsigned int	nThreshold;			//移动检测阈值
	unsigned int	nRectNum;			//移动检测区域个数,最大为4,0表示全画面检测
	RECT		stRect[4];

	unsigned int	nDelay;
	unsigned int	nStart;
	unsigned int	bOutClient;
	unsigned int	bOutEMail;
	unsigned char testlist[5];
	RECT		testObj;
	char name[20];
	char nameList[2][20];
	char *nameptr;
	char *nameptrList[2];
	float flt;
	double db;
	float flta[3];
	double dba[3];
}MD, *PMD;

static json_kinfo_t md_key[] = {
	MAKE_KEY_INFO(MD, KEY_TYPE_U32, bEnable, NULL),
	MAKE_KEY_INFO(MD, KEY_TYPE_U32, nSensitivity, NULL),
	MAKE_KEY_INFO(MD, KEY_TYPE_U32, nThreshold, NULL),
	MAKE_KEY_INFO(MD, KEY_TYPE_U32, nRectNum, NULL),
	MAKE_ARRAY_INFO(MD, KEY_TYPE_ARRAY, stRect, rect_key, 4, KEY_TYPE_OBJECT),
	MAKE_KEY_INFO(MD, KEY_TYPE_U32, nStart, NULL),
	MAKE_KEY_INFO(MD, KEY_TYPE_U32, bOutClient, NULL),
	MAKE_KEY_INFO(MD, KEY_TYPE_U32, bOutEMail, NULL),
	MAKE_ARRAY_INFO(MD, KEY_TYPE_ARRAY, testlist, NULL, 5, KEY_TYPE_U8),
	MAKE_KEY_INFO(MD, KEY_TYPE_OBJECT, testObj, rect_key),
	MAKE_KEY_INFO(MD, KEY_TYPE_STRING, name, NULL),
	MAKE_ARRAY_INFO(MD, KEY_TYPE_ARRAY, nameList, NULL, 2, KEY_TYPE_STRING),
	MAKE_KEY_INFO(MD, KEY_TYPE_STRING_PTR, nameptr, NULL),
	MAKE_ARRAY_INFO(MD, KEY_TYPE_ARRAY, nameptrList, NULL, 2, KEY_TYPE_STRING_PTR),
	MAKE_KEY_INFO(MD, KEY_TYPE_FLOAT, flt, NULL),
	MAKE_KEY_INFO(MD, KEY_TYPE_DOUBLE, db, NULL),
	MAKE_ARRAY_INFO(MD, KEY_TYPE_ARRAY, flta, NULL, 3, KEY_TYPE_FLOAT),
	MAKE_ARRAY_INFO(MD, KEY_TYPE_ARRAY, dba, NULL, 3, KEY_TYPE_DOUBLE),
	MAKE_END_INFO()
};

void cjson_direct_test(void)
{
	char *out;
	MD md = 
	{
		1,	//bEnable;	
		30,	//nSensitivity;
		40,	//nThreshold;
		4,	//nRectNum;	
		{
			{1,2,3,4},
			{2,3,4,5},
			{3,4,5,6},
			{4,5,6,7},
		},
		10,	//nDelay;
		10,	//nStart;
		1,	//bOutClient
		1,	//bOutEMail
		{1,2,3,4,5},
		{1,2,3,4},
		"I have a dream",
		{"nameList1", "nameList2"},
		"I have a dream",
		{"nameList1", "nameList2"},
		0.1,
		0.2,
		{2.1,3,2},
		{3.1,4,3}
	};
	MD m2;
	MD m3[3];
	MD m4[3];
	int cnt;

	out = cjson_object2string(md_key,(void *)&md);
	printf("%d: out: \n%s\n", __LINE__, out);
	cjson_string2object(md_key, out, (void *)&m2);
	cjson_string2object_array_free(md_key, &m2, 1);
	printf("%s: %d\n",__FILE__, __LINE__);
	free(out);
	printf("%s: %d\n",__FILE__, __LINE__);
	out = cjson_object2string(md_key,(void *)&m2);
	printf("%d: out: \n%s\n", __LINE__, out);
	free(out);

	m3[0] = md;
	m3[1] = md;
	m3[2] = md;
	out = cjson_object_array2string(md_key,m3,3);
	printf("array out: \n%s\n", out);

	cjson_string2object_array(md_key,out,m4,3,&cnt);
	free(out);
	out = cjson_object_array2string(md_key,m4,3);
	printf("array out: \n%s\n", out);
	cjson_string2object_array_free(md_key, m4, cnt);
	free(out);
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

物联网小镇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值