cJson学习(二)

已剪辑自: https://blog.csdn.net/ZRXSLYG/article/details/122541036?spm=1001.2101.3001.6650.17&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-17-122541036-blog-123806149.235^v35^pc_relevant_default_base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-17-122541036-blog-123806149.235^v35^pc_relevant_default_base&utm_relevant_index=18

安装

https://github.com/DaveGamble/cJSON

组包

#include <stdio.h>
#include "cJSON.h"

int main(){
    // 创建dict结点
    cJSON *root = cJSON_CreateObject();

    // 添加string子节点
    cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));

    // 添加number子节点
    cJSON_AddItemToObject(root, "age", cJSON_CreateNumber(20));

    // 添加bool子节点
    cJSON_AddItemToObject(root, "best", cJSON_CreateBool(cJSON_True));

    // 添加bool子节点
    cJSON_AddItemToObject(root, "worse", cJSON_CreateFalse());

    // 添加NULL子节点
    cJSON_AddItemToObject(root, "address", cJSON_CreateNull());

    // 添加array
    cJSON *string_array = cJSON_CreateArray();
    cJSON_AddItemToObject(string_array,"hello",cJSON_CreateString("hello"));
    cJSON_AddItemToObject(string_array,"world",cJSON_CreateString("world"));
    cJSON_AddItemToObject(root,"string",string_array);

    // 添加array
    int nums[] = {1,2,3,4,5,6};
    cJSON *nums_array = cJSON_CreateIntArray(nums,sizeof(nums)/sizeof(int));
    cJSON_AddItemToObject(root,"nums",nums_array);

    // 格式化输出, 调用malloc
    printf("%s\n",cJSON_Print(root));

    // 非格式化输出, 调用malloc
    printf("%s\n",cJSON_PrintUnformatted(root));

    // 不调用malloc
    char buffer[4096] = {0};
    cJSON_PrintPreallocated(root,buffer,sizeof(buffer),0);//0 非格式化, 1格式化
    printf("%s\n",buffer);

    // 删除节点, 如果直接调用cJSON_Delete删除某个节点, print的时候会出错的
    cJSON_DeleteItemFromObjectCaseSensitive(root,"age");// 大小写敏感
    // cJSON_DeleteItemFromObject// 大小写不敏感

    // 更新节点
    cJSON_ReplaceItemInObjectCaseSensitive(root,"name",cJSON_CreateString("小明"));// 大小写敏感
    // cJSON_ReplaceItemInObject// 大小写不敏感

    // 格式化输出, 调用malloc
    printf("%s\n",cJSON_Print(root));

    // 删除根节点
    cJSON_Delete(root);
}

解包

#include <stdio.h>
#include "cJSON.h"

int main(){
    char s[] = "{\"name\":\"Jack (\\\"Bee\\\") Nimble\",\"age\":20,\"best\":true,\"worse\":false,\"address\":null,\"string\":[\"hello\",\"world\"],\"nums\":[1,2,3,4,5,6]}";

    cJSON *root, *object, *sub_object;
    
    // 解析
    root = cJSON_Parse(s);

    // 字符串
    object = cJSON_GetObjectItemCaseSensitive(root,"name");
    printf("%d %s\n",cJSON_IsString(object), cJSON_GetStringValue(object));
    object = cJSON_GetObjectItem(root,"NAME");
    printf("%d %s\n",cJSON_IsString(object), cJSON_GetStringValue(object));
    

    // 数字
    object = cJSON_GetObjectItemCaseSensitive(root,"age");
    printf("%d %lf\n",cJSON_IsNumber(object), cJSON_GetNumberValue(object));

    // 数组
    object = cJSON_GetObjectItemCaseSensitive(root,"string");
    printf("%d %d\n",cJSON_IsArray(object), cJSON_GetArraySize(object));
    int i,n = cJSON_GetArraySize(object);
    for(i=0;i<n;i++){
        sub_object = cJSON_GetArrayItem(object,i);
        printf("%d %s\n",cJSON_IsString(sub_object), cJSON_GetStringValue(sub_object));
    }

    // 删除根节点
    cJSON_Delete(root);
}

解包与可变参数

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "cJSON.h"

#define get_cjson_string(args...) _get_cjson_string(args,"")
int _get_cjson_string(cJSON * root, char * value, int value_size, ...)
{
    va_list ap;
    char *key;
    cJSON *object;

    va_start(ap, value_size);
    for(key=va_arg(ap, char*),object=root;key[0]!='\0';key=va_arg(ap, char*)){
        object = cJSON_GetObjectItemCaseSensitive(object,key);
        if(object == NULL){
            printf("no find %s\n",key);
            break;
        }
    }
    
    va_end(ap);

    if(object==NULL || !cJSON_IsString(object)){
        return -1;
    }

    int len = strlen(cJSON_GetStringValue(object));
    if(len > value_size){
        return -1;
    }

    strcpy(value,cJSON_GetStringValue(object));
    return len;
}

#define get_cjson_number(args...) _get_cjson_number(args,"")
int _get_cjson_number(cJSON * root, double * value, ...){
    va_list ap;
    char *key;
    cJSON *object;

    va_start(ap, value);
    for(key=va_arg(ap, char*),object=root;key[0]!='\0';key=va_arg(ap, char*)){
        object = cJSON_GetObjectItemCaseSensitive(object,key);
        if(object == NULL){
            printf("no find %s\n",key);
            break;
        }
    }
    
    va_end(ap);

    if(object==NULL || !cJSON_IsNumber(object)){
        return -1;
    }

    *value = cJSON_GetNumberValue(object);
    return 0;
}

#define get_cjson_object(args...) _get_cjson_object(args,"")
cJSON * _get_cjson_object(cJSON * root, ...){
    va_list ap;
    char *key;
    cJSON *object;

    va_start(ap, root);
    for(key=va_arg(ap, char*),object=root;key[0]!='\0';key=va_arg(ap, char*)){
        object = cJSON_GetObjectItemCaseSensitive(object,key);
        if(object == NULL){
            printf("no find %s\n",key);
            break;
        }
    }
    
    va_end(ap);

    return object;
}

int main(){
    char s[] = "{\"name\":\"Jack (\\\"Bee\\\") Nimble\",\"age\":20,\"best\":true,\"worse\":false,\"address\":null,\"string\":[\"hello\",\"world\"],\"nums\":[1,2,3,4,5,6]}";

    cJSON *root, *object, *sub_object;
    
    // 解析
    root = cJSON_Parse(s);

    // 字符串
    char tmp[1024] = {0};
    get_cjson_string(root,tmp,sizeof(tmp)-1,"name");
    printf("%s\n",tmp);
    

    // 数字
    double f = 0.0;
    get_cjson_number(root,&f,"age");
    printf("%lf\n",f);

    // 删除根节点
    cJSON_Delete(root);
}

优化

重定义malloc和free, 可以优化组包解包速度
因为绝大部分场景,基本都是调用malloc生成新节点,然后在最后delete根节点的时候一起free释放所有节点。所以可以预先在堆中定义一个大buffer, malloc则从buffer中申请

#include <stdio.h>
#include "cJSON.h"

int main(int argc,char** argv){
   unsigned char buff[8192],*p = buff;
   void *my_malloc(size_t sz){
       if(sizeof(buff) - (p-buff) < sz){
           return NULL;
       }
       unsigned char *p_tmp = p;
       p += sz;
       return p_tmp;
   }
   void my_free(void* ptr){
       return;
   }

   cJSON_Hooks hooks = {my_malloc,my_free};
   cJSON_InitHooks(&hooks);// 替换原有的malloc和free

   cJSON *root,*fmt;
   root = cJSON_CreateObject();
   cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
   cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
   cJSON_AddStringToObject(fmt, "type", "rect");
   cJSON_AddNumberToObject(fmt, "width", 1920);
   cJSON_AddNumberToObject(fmt, "height", 1080);
   cJSON_AddFalseToObject (fmt, "interlace");
   cJSON_AddNumberToObject(fmt, "frame rate", 24);
   printf("%s\n",cJSON_PrintUnformatted(root));
   cJSON_Delete(root);

   cJSON_InitHooks(NULL);// 还原为原有的malloc和free
}

测试程序
测试环境:树莓派4B
test_stack.c
#include <stdio.h>
#include "cJSON.h"

int main(int argc,char** argv){
   int n = 10000,i;
   if(argc > 1){
       n = atoi(argv[1]);
   }

   for(i=0;i<n;i++){
       unsigned char buff[8192],*p = buff;
       void *my_malloc(size_t sz){
           if(sizeof(buff) - (p-buff) < sz){
               return NULL;
           }
           unsigned char *p_tmp = p;
           p += sz;
           return p_tmp;
       }
       void my_free(void* ptr){
           return;
       }

       cJSON_Hooks hooks = {my_malloc,my_free};
       cJSON_InitHooks(&hooks);

       cJSON *root,*fmt;
       root = cJSON_CreateObject();
       cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
       cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
       cJSON_AddStringToObject(fmt, "type", "rect");
       cJSON_AddNumberToObject(fmt, "width", 1920);
       cJSON_AddNumberToObject(fmt, "height", 1080);
       cJSON_AddFalseToObject (fmt, "interlace");
       cJSON_AddNumberToObject(fmt, "frame rate", 24);
       // printf("%s\n",cJSON_PrintUnformatted(root));
       cJSON_Delete(root);
       cJSON_InitHooks(NULL);
   }
}

test_heap.c
#include <stdio.h>
#include "cJSON.h"

int main(int argc,char** argv){
   int n = 10000,i;
   if(argc > 1){
       n = atoi(argv[1]);
   }

   for(i=0;i<n;i++){
       cJSON *root,*fmt;
       root = cJSON_CreateObject();
       cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
       cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
       cJSON_AddStringToObject(fmt, "type", "rect");
       cJSON_AddNumberToObject(fmt, "width", 1920);
       cJSON_AddNumberToObject(fmt, "height", 1080);
       cJSON_AddFalseToObject (fmt, "interlace");
       cJSON_AddNumberToObject(fmt, "frame rate", 24);
       // printf("%s\n",cJSON_PrintUnformatted(root));
       cJSON_Delete(root);
   }
   
   
}

Makefile

SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))

all : test_stack test_heap

test_stack:test_stack.o cJSON.o
    gcc -o $@ $^

test_heap:test_heap.o cJSON.o
    gcc -o $@ $^

$(OBJ):%.o:%.c
    gcc -c -o $@ $< -O3

clean:
    -rm $(OBJ) $(all)

.PHONY:all clean

1000000次循环测试结果

> time ./test_stack 1000000

real    0m0.868s
user    0m0.867s
sys     0m0.000s

> time ./test_heap 1000000

real    0m3.093s
user    0m3.093s
sys     0m0.000s

参考:

https://blog.csdn.net/Mark_md/article/details/108548524
https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap
https://stackoverflow.com/questions/24057331/is-accessing-data-in-the-heap-faster-than-from-the-stack
https://stackoverflow.com/questions/161053/which-is-faster-stack-allocation-or-heap-allocation
https://stackoverflow.com/questions/2264969/why-is-memory-allocation-on-heap-much-slower-than-on-stack

posted @ 2023-05-11 16:05  sgggr  阅读(169)  评论(0)    收藏  举报