cson beta

#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

//#define MEM_LEAK_TEST
#ifdef MEM_LEAK_TEST
#define BUFFER_SIZE 500
typedef char buffer_size_type[1024 * 1024];
buffer_size_type s_test_buffer[BUFFER_SIZE] = {0};
int s_test_list[BUFFER_SIZE] = {0};
#define  calloc(size,counts) calloc_p(size,counts)
#define  free(p) free_p(p)

static void* calloc_p(int size, int counts) {
    for (int i = 0; i < sizeof (s_test_buffer) / sizeof (s_test_buffer[0]); ++i) {
        if (s_test_list[i]) continue;
        s_test_list[i] = 1;
        return (void*) &s_test_buffer[i];
    }
}

static void free_p(void* p) {
    int index = (int) ((buffer_size_type*) p - s_test_buffer);
    if (index < 0) {
        return;
    }
    memset(&s_test_buffer[index], 0, sizeof (s_test_buffer[index]));
    s_test_list[index] = 0;
}

static void check() {
    for (int i = 0; i < sizeof (s_test_list) / sizeof (s_test_list[0]); ++i) {
        if (s_test_list[i]) {
            printf("%d leak...%s\n", i, (char*) &s_test_buffer[i]);
        }
    }
}
#endif


#if !defined(_GNU_SOURCE) && !defined(_USE_GNU)
#ifdef WIN32
#define snprintf _snprintf
#endif

int asprintf(char** dst, const char* fmt, ...) {
    static FILE* tmp_file = NULL;
    int size = 0;
    va_list ap, rp;
    va_start(ap, fmt);
    va_start(rp, fmt);
    if (NULL == tmp_file) {
        tmp_file = tmpfile();
    }
    size = vfprintf(tmp_file, fmt, ap);
    if (size < 0) {
        goto out;
    }
    *dst = (char*) calloc(sizeof (char), size + 1);
    size = vsnprintf(*dst, size + 1, fmt, rp);
out:
    va_end(ap);
    va_end(rp);
    return size;
}

char* strndup(const char*src, int len) {
    char* dst = (char*) calloc(sizeof (char), len + 1);
    strncpy(dst, src, len);
    return dst;
}
#endif



#ifndef BUCKET_SIZE
#define BUCKET_SIZE 1024
#endif

//#define LEVEL 1
#if defined(LEVEL)
#define DEBUG(fmt,...) printf("[%d,%s]:"fmt,__LINE__,__FUNCTION__,##__VA_ARGS__)
#define TRACE(fmt,...) printf("[%d,%s]:"fmt,__LINE__,__FUNCTION__,##__VA_ARGS__)
#else
#define DEBUG(fmt,...) 
#define TRACE(fmt,...) 
#endif

#define JSON_OBJ_BEGIN(x) const char* x[] = {
#define VALUE_ITEM(name,value) ("\"" #name "\":" #value )
#define ARRAY_ITEM(name,...) ("\""   #name "\":["#__VA_ARGS__"]")
#define STR_ITEM(name,value) ("\""   #name"\":"#value)
#define JSON_OBJ_END(x) }

typedef struct json_item_tag {
    char* key;
    char* value;
    unsigned flag;
} json_item_t, *json_item_handle;
enum{
    em_del = 0x1,
    em_sri = 0x2
};
typedef struct hash_bucket_tag {
    struct hash_bucket_tag* next;
    int position;
} hash_bucket_t, *hash_bucket_handle;

typedef struct json_obj_tag {
    int size, used;
    hash_bucket_t bucket[BUCKET_SIZE];
    json_item_t items[];
} json_obj_t, *json_obj_handle;

json_obj_handle create_json_obj(int size);
void  destroy_json_obj(json_obj_handle h);


#define name_id(name) ((strlen(name) + *(int*)name) % BUCKET_SIZE)


static void clear_bucket(hash_bucket_handle h) {
    if (NULL == h) {
        return;
    }
    clear_bucket(h->next);
    free(h);
}


#define free_and_nil(x) do{free(x);x=NULL;}while(0)        

static json_item_handle get_json_item(json_obj_handle h, const char* name) {
    int index = name_id(name);
    hash_bucket_handle hh = &h->bucket[index];
    if (0 == hh->position && NULL == hh->next) {
        hh->position = h->used++;
        DEBUG("new position at %d\n", hh->position);
        return &h->items[hh->position];
    }
    for (; 0 != strcmp(h->items[hh->position].key, name);) {
        if(h->items[hh->position].flag & em_del){
            json_item_handle it = &h->items[hh->position];
            free_and_nil(it->key);
            free_and_nil(it->value);
            it->flag = 0;
            DEBUG("reused deleted posion at %d\n",hh->position);
            break;
        }
        if (NULL == hh->next) {
            hh->next = (hash_bucket_handle) calloc(sizeof (hash_bucket_t), 1);
            hh->next->position = h->used++;
            hh = hh->next;
            DEBUG("%s crashed new pos at %d\n", name, hh->position);
            break;
        }
        hh = hh->next;
    }
    return &h->items[hh->position];
}

#ifdef insert_json_item
#undef insert_json_item
#endif
#define insert_json_item(fmt,h,name,v) do{\
	json_item_handle __ih__ = get_json_item(h,name);\
	if(NULL == __ih__->key) asprintf(&__ih__->key,"%s",name);\
	if(NULL != __ih__->value) free(__ih__->value);\
	asprintf(&__ih__->value,fmt,v);\
}while(0)

int insert_json_obj_handle_value(json_obj_handle h, const char* name, json_obj_handle son) {
    int i = 0;
    for (; i < son->used; ++i) {
        char* name_str = NULL;
        asprintf(&name_str, "%s.%s", name, son->items[i].key);
        insert_json_item("%s", h, name_str, son->items[i].value);
        free(name_str);
    }
    return i;
}
#define insert_float_value(h,name,value) insert_json_item("%lf",h,name,value)
#define insert_int_value(h,name,value) insert_json_item("%d",h,name,value)
#define insert_double_value(h,name,value) insert_json_item("%lf",h,name,value)
#define insert_string_value(h,name,value) insert_json_item("\"%s\"",h,name,value)
#define insert_bool_value(h,name,value) insert_json_item((value ? "true" : "false"),h,name,value)
#define insert_NULL_value(h,name,value) insert_json_item("null",h,name,value)
#define insert_value(h, name,type,value) insert_##type##_value(h,name,value)



const char* get_json_value(json_obj_handle h, const char* name,const char* fmt,void* value) {
    int index = name_id(name);
    hash_bucket_handle hh = &h->bucket[index];
    for (; NULL != hh; hh = hh->next) {
        json_item_handle it = &h->items[hh->position];
        if (0 != strcmp(it->key, name) || (it->flag & em_del)) {
            continue;
        }
        if (NULL != value && NULL != fmt) {
            TRACE("convert %s : %s by %s fmt\n", name, it->value, fmt);
            sscanf(it->value, fmt, value);
        }
        return it->value;
    }
    DEBUG("%s not found the value\n",name);
    return NULL;
}
#define get_float_value(h,name,value) (NULL != get_json_value(h,name,"%f",value))
#define get_double_value(h,name,value) get_float_value
#define get_int_value(h,name,value) (NULL != get_json_value(h,name,"%d",value))
#define get_bool_value(h,name,value) get_int_value

int get_string_value(json_obj_handle h, const char* name, char** value) {
    const char* ret = get_json_value(h, name, "", NULL);
    if (NULL == ret) {
        *value = NULL;
        DEBUG("%s not found the value\n",name);
        return 0;
    }
    TRACE("get %s = %s \n",name,ret);
    asprintf(value, "%s", ret);
    return 1;
}

int get_json_obj_handle_value(json_obj_handle h,const char* name,json_obj_handle* son){
    int i = 0,len = strlen(name);
    *son = create_json_obj(100);
    for (; i < h->used; ++i) {
        if (0 != strncmp(h->items[i].key, name, len) || (h->items[i].flag & em_del)) {
            continue;
        } else {
            const char* sub_key = &h->items[i].key[len + 1];
            const char* sub_val = h->items[i].value;
            json_item_handle it = get_json_item(*son, sub_key);
            /*
             * using "%s" copy string avoid src string had % act..
             */
            TRACE("%s.%s = %s\n", name, sub_key, sub_val);
            asprintf(&it->key, "%s", sub_key);
            asprintf(&it->value, "%s", sub_val);
        }
    }    
    if(0 != (*son)->used){
        DEBUG("new object %s had %d items created\n",name,(*son)->used);
        return 1;
    }
    destroy_json_obj(*son);
    *son = NULL;
    return 0;
}
#define get_value(h,name,type,value) get_##type##_value(h,name,&(value))

#ifdef create_array_insert
#undef create_array_insert
#endif
#ifdef insert_array_item
#undef  insert_array_item
#endif 
#define insert_array_item(h,name,type,index,val) do{\
        char* __name_str__ = NULL;\
        asprintf(&__name_str__,"%s[%d]",name,index);\
        insert_value(h,__name_str__,type,val);\
        free(__name_str__);\
}while(0)
#define create_array_insert(f_name,type) int insert_##f_name##_array(json_obj_handle h, const char* name, ...) {\
    union{\
        int  last;\
        type val;\
    }dst_val;\
    int i = 0,lbreak = 0;\
    va_list al;\
    va_start(al, name);\
    lbreak = va_arg(al,int);\
    for (dst_val.val = va_arg(al, type); dst_val.last != ']'; dst_val.val = va_arg(al, type)) {\
        insert_array_item(h,name,f_name,i++,dst_val.val);\
    }\
    return i;\
}
create_array_insert(int, int)
create_array_insert(double, double)
create_array_insert(string, char*)
create_array_insert(json_obj_handle, json_obj_handle)
#ifdef create_array_insert
#undef create_array_insert
#endif
#ifdef insert_array_item
#undef  insert_array_item
#endif 

#ifdef insert_array
#undef insert_array
#endif
#define insert_array(h,name,type,...) insert_##type##_array(h,name,'[',__VA_ARGS__,']')

#define get_array_item(h,name,type,index,value) do{\
        char* __name_str__ = NULL;\
        asprintf(&__name_str__,"%s[%d]",name,index);\
        get_value(h,__name_str__,type,value);\
        free(__name_str__);\
}while(0)

#define get_array(h,name,type,dst,size) do{\
    int __i__ = 0,__k__ = 0;\
    for (; (__i__ < h->used) && (__k__ < size); ++__i__) {\
        char* __name_str__ = NULL;\
        asprintf(&__name_str__, "%s[%d]", name, __i__);\
        if(get_value(h, __name_str__, type, dst[__k__])){\
            TRACE("%s[%d] gotted the value at %d\n",__name_str__,__i__,__k__);\
            ++__k__;\
        };\
        free(__name_str__);\
    }\
    size = __k__;\
    DEBUG("%s got %d items\n",name,size);\
}while(0)

static void rebuild_josn_bucket(json_obj_handle h) {
    int i = 0;
    for (; i < BUCKET_SIZE; ++i) {
        clear_bucket(h->bucket[i].next);
    }
    memset(h->bucket, 0, sizeof (h->bucket));
    for (int i = 0; i < h->used; ++i) {
        int index = name_id(h->items[i].key);
        hash_bucket_handle hh = &h->bucket[index];
        for (; NULL != hh; hh = hh->next) {
            if (NULL == hh->next && 0 == hh->position) {
                h->bucket[index].position = i;
                break;
            }else if(NULL == hh->next){
                hh->next = (hash_bucket_t*)calloc(sizeof(hash_bucket_t),1);
                hh->next->position = i;
                break;
            }else{
                ;
            }
        }
    }
}


void pack_json_item(json_obj_handle h) {
    int i = 0;
    DEBUG("json had %d items\n",h->used);
    for (i = 0; i < h->used; ++i) {        
        json_item_handle it = &h->items[i];
        if(!(it->flag & em_del)){
            TRACE("%d(%s) not deleleted \n",i,it->key);
            continue;
        }
        DEBUG("removed %d(%s) item\n",i,it->key);
        free_and_nil(it->key);
        free_and_nil(it->value);
        memmove(&h->items[i], &h->items[i + 1], (h->used -i) * sizeof(json_item_t));
        memset(&h->items[h->used--], 0, sizeof (json_item_t));
        --i;
    }
    TRACE("left %d item in %p handle\n",h->used,h);
    rebuild_josn_bucket(h);
}

void remove_json_simple_item(json_obj_handle h, const char* name) {
    int index = name_id(name);
    hash_bucket_handle hh = &h->bucket[index];
    for (; NULL != hh; hh = hh->next) {
        json_item_handle it = &h->items[hh->position];
        if ((it->flag & em_del)||(0 != strcmp(it->key, name))) {
            continue;
        }        
        /*
         * logic delete item avoid rehash 
         */
        TRACE("will be remove %s at %d\n", it->key, hh->position);
        it->flag |= em_del;
    }
}

void remove_json_complex_item(json_obj_handle h, const char* name, const char* fix) {
    int i = 0;
    char* name_str = NULL;
    int len = asprintf(&name_str, "%s%s", name, fix);
    TRACE("try to remove %s(%d)\n",name_str,len);
    for (; i < h->used; ++i) {
        if ((h->items[i].flag & em_del) || (0 != strncmp(h->items[i].key, name_str, len))) {
            continue;
        }
        /*
         * logic delete item avoid rehash 
         */
        TRACE("will be remove %s at %d,name = %s(%d)\n", h->items[i].key, i,name_str,len);
        h->items[i].flag |= em_del;
    }
    free(name_str);
}

#define remove_int_value(h,name) remove_json_simple_item(h,name)
#define remove_string_value(h,name) remove_json_simple_item(h,name)
#define remove_double_value(h,name) remove_json_simple_item(h,name)
#define remove_float_value(h,name) remove_json_simple_item(h,name)
#define remove_bool_value(h,name) remove_json_simple_item(h,name)
#define remove_NULL_value(h,name) remove_json_simple_item(h,name)
#define remove_json_obj_handle_value(h,name) remove_json_complex_item(h,name,".")
#define remove_array_value(h,name) remove_json_complex_item(h,name,"[")
#define remove_value(h,name,type) remove_##type##_value(h,name)

#define remove_array_item(h,name,index,type) do{\
        char* __fix__ = NULL;\
        asprintf(&__fix__,"%s[%d]",name,index);\
        remove_value(h,__fix__,type);\
        free(__fix__);\
}while(0)




json_obj_handle create_json_obj(int size) {
    json_obj_t* ret = (json_obj_handle) calloc(size * sizeof (json_item_t) + sizeof (json_obj_t), 1);
    ret->size = size;
    return ret;
}

char** sort_json_key(json_obj_handle h) {
    int i = 0, j = 0;
    char** results = (char**) calloc(sizeof (char*), h->used + 1);
    results[0] = h->items[0].key;
    for (; i < h->used; ++i) {
        for (j = 0; j < i; ++j) {
            if (strcmp(h->items[i].key, results[j]) < 0) {
                break;
            }
        }
        memmove(&results[j + 1], &results[j], h->used - j - 1);
        results[j] = h->items[i].key;
    }
    return results;
}

static int object_to_string(json_obj_handle h, const char*const skip_name, char buffer[], int size) {
    int i = 0, len = 0;
    char *sub_str = NULL, *array = NULL, *objec = NULL;
    DEBUG("skip = %s(%d), len = %d\n", skip_name, strlen(skip_name), size);
    for (; i < h->used; ++i) {
        DEBUG("buffer[%d,%s] = %s\n", i, h->items[i].key, buffer);
        if ((h->items[i].flag & em_sri) || (h->items[i].flag & em_del)) {
            DEBUG("processed %s pass...\n", h->items[i].key);
            continue;
        }
        if (0 != strncmp(h->items[i].key, skip_name, strlen(skip_name))) {
            DEBUG("no match %s pass...\n", h->items[i].key);
            continue;
        }
        sub_str = h->items[i].key + strlen(skip_name);
        array = strstr(sub_str, "[");
        objec = strstr(sub_str, ".");
        DEBUG("sub_str = %s(%p),array = %p,objec = %p\n", sub_str, sub_str, array, objec);
        /*
         * normal key:value pair
         */
        if (NULL == array && NULL == objec) {
            char* str = NULL;
            asprintf(&str, "\"%s\":%s", sub_str, h->items[i].value);
            h->items[i].flag |= em_sri;
            len += snprintf(&buffer[len], size - len, "%s,", str);
            free(str);
            continue;
        }
        DEBUG("item name = %s\n", h->items[i].key);
        /*
         * array list key : []
         */
        if (NULL != array && (NULL == objec || array < objec)) {
            char* name = strndup(sub_str, (int) (array - sub_str));
            int index = 0, j = 0;
            DEBUG("array sub_str = %s,name = %s\n", sub_str, name);
            len += snprintf(&buffer[len], size - len, "\"%s\":[", name);
            for (j = 0; j < h->used; ++j) {
                char* skip = NULL;
                if ((h->items[j].flag & em_sri) || (h->items[j].flag & em_del)) {
                    continue;
                }
                asprintf(&skip, "%s[%d]", name, index++);
                if (0 != strncmp(h->items[j].key, skip, strlen(skip))) {
                    free(skip);
                    continue;
                }
                DEBUG("will be process array : %s\n", skip);
                if (h->items[j].key[strlen(skip)] == '.') {
                    len += object_to_string(h, skip, &buffer[len], size - len);
                } else {
                    len += snprintf(&buffer[len], size - len, "%s,", h->items[j].value);
                    h->items[j].flag |= em_sri;
                }
                free(skip);
            }
            free(name);
            --len;
            len += snprintf(&buffer[len], size - len, "],");
            TRACE("array buffer = %s\n", buffer);
        } else {
            /*
             * object key : {}
             */
            char* name = strndup(sub_str, (int) (objec - sub_str));
            char* skip = strndup(h->items[i].key, (int) (objec - h->items[i].key) + 1);
            DEBUG("object sub_str = %s, name = %s,skip_str = %s\n", sub_str, name, skip);
            if (0 != strlen(name)) {
                len += snprintf(&buffer[len], size - len, "\"%s\":{", name);
            } else {
                len += snprintf(&buffer[len], size - len, "{");
            }
            len += object_to_string(h, skip, &buffer[len], size - len) - 1;
            len += snprintf(&buffer[len], size - len, "},");
            TRACE("object buffer = %s\n", buffer);
            free(skip);
            free(name);
        }

    }
    TRACE("%s %s %d\n", skip_name, buffer, len);
    return len;
}

const char* to_string(json_obj_handle h, char buffer[], int size) {
    int len = snprintf(buffer, size, "{");
    len += object_to_string(h, "", &buffer[len], size - len) - 1;
    len = (len > 0) ? len : 1;
    snprintf(&buffer[len], size - len, "}");
    for (len = 0; len < h->used; ++len) {
        h->items[len].flag &= ~(em_sri);
    }
    return buffer;
}

void destroy_json_obj(json_obj_handle h) {
    int i = 0;
    for (; i < h->used; ++i) {
        free(h->items[i].key);
        free(h->items[i].value);
    }
    for (i = 0; i < BUCKET_SIZE; ++i) {
        clear_bucket(h->bucket[i].next);
    }
    free(h);
}

test

JSON_OBJ_BEGIN(obj)
VALUE_ITEM(age, 18),
ARRAY_ITEM(arrays, 1, 2, 3, 4, 5.6),
STR_ITEM(name, "zhang san"),
JSON_OBJ_END(obj);


char buffer[10240] = {0};

static void param_test() {
    json_obj_handle h = create_json_obj(10240);

    /*
            insert value
     */
    insert_value(h, "age", int, 18);
    {
        int age = 0;
        get_value(h,"age",int,age);
        assert(age == 18);
    }
    /*
            insert string
     */
    insert_value(h, "name", string, "zhangsan");
    {
        char* name_str = NULL;
        get_value(h,"name",string,name_str);
        assert(0 == strcmp(name_str,"\"zhangsan\""));
        free(name_str);
    }
    /*
            insert object
     */
    {
        json_obj_handle local = create_json_obj(10);
        insert_value(local, "city", string, "sh");
        insert_value(local, "mailNo", string, "200240");
        insert_value(h, "local", json_obj_handle, local);
        destroy_json_obj(local);
    }
    {
        json_obj_handle jh = NULL;
        get_value(h,"local",json_obj_handle,jh);
        assert(NULL != jh);
        destroy_json_obj(jh);
    }
    /*
            insert array
     */
    {
        json_obj_handle f1 = create_json_obj(10);
        json_obj_handle f2 = create_json_obj(10);

        insert_value(f1, "city", string, "sh");
        insert_value(f1, "mailNo", string, "200240");
        insert_value(f1, "mailNo",int,200241);
        insert_value(f2, "city", string, "sh");
        insert_value(f2, "mailNo", string, "200240");
        
        insert_array(h, "friends", json_obj_handle, f1, f2);
        
        destroy_json_obj(f1);
        destroy_json_obj(f2);
    }
    insert_array(h, "number", int, 1, 2, 3, 4, 5, 6, 7, 8);
    insert_array(h, "string", string, "a", "b", "c", "d", "e");
    {
        json_obj_handle jh[10] = {NULL,NULL};
        char* s[10] = {NULL};
        int   i[10] = {0};
        int len = 10,k = 1;

        get_array(h,"friends",json_obj_handle,jh,len);
        assert(2 == len);
        assert(NULL != jh[0]);
        assert(NULL != jh[1]);
        assert(NULL == jh[2]);
        for(k = 0; k < 2; ++k){
            destroy_json_obj(jh[k]);
        }
        len = 10;
        get_array(h,"number",int,i,len);
        assert(8 == len);
        for(k = 0; k < 8; ++k){
            assert( (k+1) == i[k]);
        }        
        assert(0 == i[9]);
        len = 10;
        get_array(h,"string",string,s,len);
        assert(5 == len);
        assert(0 == strcmp(s[0],"\"a\""));
        assert(NULL == s[9]);
        get_array_item(h,"number",int,3,len);
        assert(4 == len);
        get_array_item(h,"string",string,0,s[9]);
        assert(0 == strcmp(s[0],s[9]));
        for(k = 0; k < 5 ; ++k){
            free(s[k]);
        }                      
        free(s[9]);
    }
    /*
            insert bool
     */
    insert_value(h, "boolean1", bool, 1);
    insert_value(h, "boolean2", bool, 0);
    /*
            insert null
     */
    insert_value(h, "null", NULL, NULL);
    
    to_string(h, buffer, sizeof (buffer));
    //printf("%s\n", buffer);
    /*
     * remove test
     */
    {
        int age = 0;
        remove_value(h,"age",int);
        assert(0 == get_value(h,"age",int,age));
    }
    {
        char* name = NULL;
        remove_value(h,"name",string);
        assert(0 == get_value(h,"name",string,name));
        assert(NULL == name);
    }
    {
        json_obj_handle jh = NULL;
        remove_value(h,"local",json_obj_handle);        
        assert(0 == get_value(h,"local",json_obj_handle,jh));
        assert(NULL == jh);
    }
    {
        json_obj_handle ja[10] = {0},jh = NULL;
        int size = 10;
        remove_array_item(h,"friends",0,json_obj_handle);
        get_array_item(h,"friends",json_obj_handle,0,jh);
        assert(0 == jh);
        get_array(h,"friends",json_obj_handle,ja,size);
        assert(1 == size);
        assert(NULL != ja[0]);
        assert(NULL == ja[1]);
        destroy_json_obj(ja[0]);
        remove_value(h,"friends",array);
        size = 10;
        get_array(h,"friends",json_obj_handle,ja,size);
        assert(0 == size);
        assert(NULL == ja[0]);
    }
    {
        int ai[10] = {0},len = 10;
        remove_array_item(h,"number",3,int);
        get_array(h,"number",int,ai,len);
        assert(7 == len);
        assert(5 == ai[3]);
        assert(0 == ai[9]);
        remove_value(h,"number",array);
        len = 10;
        get_array(h,"number",int,ai,len);
        assert(0 == len);
    }
    {
        char* ai[10] = {NULL};
        int len = 10;
        remove_array_item(h,"string",3,string);
        get_array(h,"string",string,ai,len);
        assert(4 == len);
        assert(0 == strcmp("\"e\"",ai[3]));
        assert(NULL == ai[9]);
        remove_value(h,"string",array);
        for(len = 0; len < 10; ++len){
            free(ai[len]);
            ai[len] = NULL;
        }
        len = 10;
        get_array(h,"string",string,ai,len);
        assert(0 == len);
    }    
    {
        remove_value(h,"boolean1",bool);
        remove_value(h,"boolean2",bool);
        remove_value(h,"null",NULL);
    }
    memset(buffer, 0, sizeof (buffer));
    to_string(h, buffer, sizeof (buffer));
    assert(0 == strcmp("{}",buffer));
    {
        assert(24 == h->used);
        insert_value(h,"test",string,"this is a test");
        pack_json_item(h);    
        assert(1 == h->used);
    }  
    {
        char* test_str = NULL;
        get_value(h,"test",string,test_str);
        assert(NULL != test_str);
        assert(0 == strcmp("\"this is a test\"",test_str));   
        free(test_str);
    }
    
    destroy_json_obj(h);
}

int main(int argn, const char* argv[]) {
    for(;;)param_test();
#ifdef MEM_LEAK_TEST
    check();
#endif
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值