cJSON代码分析(一)
前言
cJSON采用双向链表来存储数据。双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
cJSON操作JSON对象实质就是操作链表的过程。本次分析cJSON添加对象和删除对象的操作。
cJSON返回结果的宏定义
在小端系统中,最高有效位存储在高地址内存中,最低有效位存储在低地址中。
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0) 1最低有效位往最高有效位的方向移动0位。
#define cJSON_True (1 << 1) 1最低有效位往最高有效位的方向移动1位。
#define cJSON_NULL (1 << 2) 1最低有效位往最高有效位的方向移动2位。
#define cJSON_Number (1 << 3) 1最低有效位往最高有效位的方向移动3位。
#define cJSON_String (1 << 4) 1最低有效位往最高有效位的方向移动4位。
#define cJSON_Array (1 << 5) 1最低有效位往最高有效位的方向移动5位。
#define cJSON_Object (1 << 6) 1最低有效位往最高有效位的方向移动6位。
#define cJSON_Raw (1 << 7) /* raw json */ 1最低有效位往最高有效位的方向移动7位。
cJSON_Invalid 0
cJSON_False1
cJSON_True2
cJSON_NULL4
cJSON_Number 8
cJSON_String 16
cJSON_Array32
cJSON_Object 64
cJSON_Raw128
c JSON中最重要的结构体
struct cJSON
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively,useGetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chainof the items in the array/object. */
struct cJSON *child;
/* The type of the item,as above. */
int type;
/* The item's string,if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED,use cJSON_SetNumberValue instead*/
int valueint;
/* The item's number,if type==cJSON_Number */
double valuedouble;
/* The item's name string,if this item is the child of,or is in thelist of subitems of an object. */
char *string;
} cJSON;
parse_buffer
typedef struct
{
const unsigned char *content;
size_t length;
size_t offset;
size_t depth; /* How deeply nested (in arrays/objects) is the input atthe current offset. */
internal_hooks hooks;
} parse_buffer;
error
typedef struct {
const unsigned char *json;
size_t position;
} error;
internal_hooks
typedef struct internal_hooks
{
void *(*allocate)(size_t size);
void (*deallocate)(void *pointer);
void *(*reallocate)(void *pointer,size_t size);
} internal_hooks;
创建JSON对象
CJSON_PUBLIC(cJSON *) cJSON_CreateObject创建JSON对象
CJSON_PUBLIC(cJSON*) cJSON_CreateObject(void)
{
cJSON *item =cJSON_New_Item(&global_hooks);
if (item)
{
item->type = cJSON_Object;//指定item的类型为cJSON_OBJECT
}
return item;
}
/* Internal constructor. */
static cJSON *cJSON_New_Item初始化
static cJSON*cJSON_New_Item(const internal_hooks * const hooks)
{
cJSON* node =(cJSON*)hooks->allocate(sizeof(cJSON));// 调用malloc函数分配内存
if (node)
{
memset(node,'\0',sizeof(cJSON));//初始化
}
return node;
}
typedef struct internal_hooks
typedef structinternal_hooks
{
void *(*allocate)(size_t size);
void (*deallocate)(void *pointer);
void *(*reallocate)(void *pointer,size_tsize);
} internal_hooks;
static void*internal_malloc(size_t size)
{
return malloc(size);
}
static voidinternal_free(void *pointer)
{
free(pointer);
}
static void*internal_realloc(void *pointer,size_t size)
{
return realloc(pointer,size);
}
#defineinternal_malloc malloc
#defineinternal_free free
#defineinternal_realloc realloc
staticinternal_hooks global_hooks = { internal_malloc,internal_free,internal_realloc };
CJSON_PUBLIC(void) cJSON_AddItemToObject JSON对象添加成员
CJSON_PUBLIC(void) cJSON_AddItemToArray 把成员添加到数组或对象中
/* Add item to array/object. */
CJSON_PUBLIC(void)cJSON_AddItemToArray(cJSON *array,cJSON *item)
{
cJSON *child = NULL;
if ((item == NULL) || (array == NULL))
{
return;
}
child = array->child;
if (child == NULL)
{
/* list is empty,start new one */
array->child = item; //如果当前JSON的child为空,把item挂载到当 //前child节点。
}
else
{
/* append to the end */
while (child->next) //循环到JSON的最后一个节点
{
child = child->next;
}
suffix_object(child,item); //把item放到双向链表的后面
//child节点next 指向item.
//item节点的prev 指向prev
}
}
//child节点next 指向item.
//item 节点的prev 指向prev
static voidsuffix_object(cJSON *prev,cJSON *item)
{
prev->next = item;
item->prev = prev;
}
删除JSON对象
CJSON_PUBLIC(void) cJSON_Delete删除对象
/* Delete a cJSONstructure. */
//递归删除节点
CJSON_PUBLIC(void)cJSON_Delete(cJSON *item)
{
cJSON *next = NULL;
while (item != NULL)
{
next = item->next;
if (!(item->type &cJSON_IsReference) && (item->child != NULL))
{
cJSON_Delete(item->child);
}
if (!(item->type &cJSON_IsReference) && (item->valuestring != NULL))
{
global_hooks.deallocate(item->valuestring);
}
if (!(item->type &cJSON_StringIsConst) && (item->string != NULL))
{
global_hooks.deallocate(item->string);
}
global_hooks.deallocate(item);
item = next;
}
}
基础宏
can_read
/* check if the given size is left to readin a given parse buffer (starting with 1) */
#define can_read(buffer,size) ((buffer !=NULL) && (((buffer)->offset + size) <= (buffer)->length))
can_access_at_index
/* check if the buffer can be accessed atthe given index (starting with 0) */
#define can_access_at_index(buffer,index)((buffer != NULL) && (((buffer)->offset + index) <(buffer)->length))
cannot_access_at_index
#define cannot_access_at_index(buffer,index) (!can_access_at_index(buffer,index))
buffer_at_offset
/* get a pointer to the buffer at theposition */
#define buffer_at_offset(buffer)((buffer)->content + (buffer)->offset)
附录
1)指针
指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。
如上图所示,左边的小房子是一个变量,变量内容为1个小人。
右边的小房子是一个指针。指针内容是左边小房子的房号(房子的地址)。