我是靠谱客的博主 缓慢酸奶,最近开发中收集的这篇文章主要介绍STM32在使用CJSON库时程序不运行的问题描述及CJSON库代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

之前做STM32项目,需要用到json串处理数据,用常用的字符串拆分,容错率和扩展率太低了,所以采用Cjson库。

之前采用的时小容量的STM32芯片,由于库文件中存在大容量的内存申请,写好的程序死活运行不起来,是因为栈内存使用超出,

之后换了中容量的芯片,程序完全能跑起来,但作为一个大一些的项目,程序里面变量的增多,还是会导致程序死机,这个时候可以考虑更改malloc.h文件的内存申请大小或是更换大容量的芯片。

当然,在stm32里跑jcson确实是个吃力的问题,太耗费内存资源了,除了必须使用Cjson,还是字节流方式传输数据好一些。

另外再插一嘴,再使用cjson的时候,一定对相应的内存进行free释放,不然前期程序可能不会出问题,但是项目程序多跑一阵可能就是停止,这是由于没有释放内存的缘故。比如在将json格式转为字符串的时候,用于接收的指针在使用完之后一定要释放。

 

下面附上CJSON库的代码:

cJSON.c


/*
  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"

#include "malloc.h"

static const char *ep;

const char *cJSON_GetErrorPtr(void) {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 *(*cJSON_malloc)(size_t sz) = mymalloc;
static void (*cJSON_free)(void *ptr) = myfree;

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(void)
{
    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;

    if (*num=='-') sign=-1,num++;    /* Has sign? */
    if (*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 && fabs(d)<1.0e60)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;
}

static unsigned parse_hex4(const char *str)
{
    unsigned h=0;
    if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
    h=h<<4;str++;
    if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
    h=h<<4;str++;
    if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
    h=h<<4;str++;
    if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
    return h;
}

/* 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. */
                    uc=parse_hex4(ptr+1);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.    */
                        uc2=parse_hex4(ptr+3);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(""\bfnrt",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_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
{
    const char *end=0;
    cJSON *c=cJSON_New_Item();
    ep=0;
    if (!c) return 0;       /* memory fail */

    end=parse_value(c,skip(value));
    if (!end)    {cJSON_Delete(c);return 0;}    /* parse failure. ep is set. */

    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
    if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
    if (return_parse_end) *return_parse_end=end;
    return c;
}
/* Default options for cJSON_Parse */
cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}

/* 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;
    /* Explicitly handle numentries==0 */
    if (!numentries)
    {
        out=(char*)cJSON_malloc(3);
        if (out) strcpy(out,"[]");
        return out;
    }
    /* 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;
    /* Explicitly handle empty object case */
    if (!numentries)
    {
        out=(char*)cJSON_malloc(fmt?depth+4:3);
        if (!out)    return 0;
        ptr=out;*ptr++='{';
        //if (fmt) {*ptr++='n';for (i=0;i<depth-1;i++) *ptr++='t';}		  
        *ptr++='}';*ptr++=0;
        return out;
    }
    /* 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';	//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;mymemcpy(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(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse(void)                    {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(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}

/* Create Arrays: */
cJSON *cJSON_CreateIntArray(const 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(const 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(const 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;}

/* Duplication */
cJSON *cJSON_Duplicate(cJSON *item,int recurse)
{
    cJSON *newitem,*cptr,*nptr=0,*newchild;
    /* Bail on bad ptr */
    if (!item) return 0;
    /* Create new item */
    newitem=cJSON_New_Item();
    if (!newitem) return 0;
    /* Copy over all vars */
    newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
    if (item->valuestring)    {newitem->valuestring=cJSON_strdup(item->valuestring);    if (!newitem->valuestring)    {cJSON_Delete(newitem);return 0;}}
    if (item->string)        {newitem->string=cJSON_strdup(item->string);            if (!newitem->string)        {cJSON_Delete(newitem);return 0;}}
    /* If non-recursive, then we're done! */
    if (!recurse) return newitem;
    /* Walk the ->next chain for the child. */
    cptr=item->child;
    while (cptr)
    {
        newchild=cJSON_Duplicate(cptr,1);        /* Duplicate (with recurse) each item in the ->next chain */
        if (!newchild) {cJSON_Delete(newitem);return 0;}
        if (nptr)    {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}    /* If newitem->child already set, then crosswire ->prev and ->next and move on */
        else        {newitem->child=newchild;nptr=newchild;}                    /* Set newitem->child and move to it */
        cptr=cptr->next;
    }
    return newitem;
}

void cJSON_Minify(char *json)
{
    char *into=json;
    while (*json)
    {
        if (*json==' ') json++;
        else if (*json=='t') json++;    // Whitespace characters.
        else if (*json=='r') json++;
        else if (*json=='n') json++;
        else if (*json=='/' && json[1]=='/')  while (*json && *json!='n') json++;    // double-slash comments, to end of line.
        else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}    // multiline comments.
        else if (*json=='"'){*into++=*json++;while (*json && *json!='"'){if (*json=='\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are " sensitive.
        else *into++=*json++;            // All other characters.
    }
    *into=0;    // and null-terminate.
}

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

#include <stddef.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(void);
    
/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);

/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(const 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);

/* Duplicate a cJSON item */
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */

/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);

extern void cJSON_Minify(char *json);

/* Macros for creating things quickly. */
#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, cJSON_CreateBool(b))
#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))

/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object,val)            ((object)?(object)->valueint=(object)->valuedouble=(val):(val))

#ifdef __cplusplus
}
#endif

#endif

之后为json的内存申请和释放文件,在硬件端使用,一般和cjson一起,在大型的系统中(win,linux等)可以不用,直接修改Cjson.c的代码让其只想C语言库中的malloc和free即可。

static void *(*cJSON_malloc)(size_t sz) = mymalloc;
static void (*cJSON_free)(void *ptr) = myfree;

malloc.c


#include "malloc.h"

//内存池(4字节对齐)
__align(4) u8 membase[MEM_MAX_SIZE];                                                    //内部SRAM内存池
//内存管理表
u16 memmapbase[MEM_ALLOC_TABLE_SIZE];                                                    //内部SRAM内存池MAP
//内存管理参数       
const u32 memtblsize = MEM_ALLOC_TABLE_SIZE;        //内存表大小
const u32 memblksize = MEM_BLOCK_SIZE;                    //内存分块大小
const u32 memsize    = MEM_MAX_SIZE;                            //内存总大小


//内存管理控制器
struct _m_mallco_dev mallco_dev=
{
    mem_init,                //内存初始化
    mem_perused,      //内存使用率
    membase,            //内存池
    memmapbase,     //内存管理状态表
    0,                        //内存管理未就绪
};

//复制内存
//*des:目的地址
//*src:源地址
//n:需要复制的内存长度(字节为单位)
void mymemcpy(void *des,void *src,u32 n)  
{  
  u8 *xdes=des;
    u8 *xsrc=src; 
  while(n--)*xdes++=*xsrc++;  
}  

//设置内存
//*s:内存首地址
//c :要设置的值
//count:需要设置的内存大小(字节为单位)
void mymemset(void *s,u8 c,u32 count)  
{  
    u8 *xs = s;  
    while(count--)*xs++=c;  
}    

//内存管理初始化  
//memx:所属内存块
void mem_init(void)  
{  
  mymemset(mallco_dev.memmap, 0,memtblsize*2);//内存状态表数据清零  
    mymemset(mallco_dev.membase, 0,memsize);    //内存池所有数据清零  
    mallco_dev.memrdy=1;                                //内存管理初始化OK  
} 
 
//获取内存使用率
//memx:所属内存块
//返回值:使用率(0~100)
u8 mem_perused(void)  
{  
    u32 used=0;  
    u32 i;  
    for(i=0;i<memtblsize;i++)  
    {  
        if(mallco_dev.memmap[i])used++; 
    } 
    return (used*100)/(memtblsize);  
}  

//内存分配(内部调用)
//memx:所属内存块
//size:要分配的内存大小(字节)
//返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址 
u32 mem_malloc(u32 size)  
{  
    signed long offset=0;  
    u16 nmemb;    //需要的内存块数  
    u16 cmemb=0;//连续空内存块数
    u32 i;  
    if(!mallco_dev.memrdy)mallco_dev.init();//未初始化,先执行初始化 
    if(size==0)return 0XFFFFFFFF;//不需要分配

    nmemb=size/memblksize;      //获取需要分配的连续内存块数
    if(size%memblksize)nmemb++;  
    for(offset=memtblsize-1;offset>=0;offset--)//搜索整个内存控制区  
    {     
        if(!mallco_dev.memmap[offset])cmemb++;//连续空内存块数增加
        else cmemb=0;                                //连续内存块清零
        if(cmemb==nmemb)                            //找到了连续nmemb个空内存块
        {
            for(i=0;i<nmemb;i++)                      //标注内存块非空 
            {  
                mallco_dev.memmap[offset+i]=nmemb;  
            }  
            return (offset*memblksize);//返回偏移地址  
        }
    }  
    return 0XFFFFFFFF;//未找到符合分配条件的内存块  
}  

//释放内存(内部调用) 
//memx:所属内存块
//offset:内存地址偏移
//返回值:0,释放成功;1,释放失败;  
u8 mem_free(u32 offset)  
{  
    int i;  
    if(!mallco_dev.memrdy)//未初始化,先执行初始化
    {
        mallco_dev.init();    
        return 1;//未初始化  
    }  
    if(offset<memsize)//偏移在内存池内. 
    {  
        int index=offset/memblksize;            //偏移所在内存块号码  
        int nmemb=mallco_dev.memmap[index];    //内存块数量
        for(i=0;i<nmemb;i++)                          //内存块清零
        {  
            mallco_dev.memmap[index+i]=0;  
        }  
        return 0;  
    }else return 2;//偏移超区了.  
}  

//释放内存(外部调用) 
//memx:所属内存块
//ptr:内存首地址 
void myfree(void *ptr)  
{  
    u32 offset;  
    if(ptr==NULL)return;//地址为0.  
     offset=(u32)ptr-(u32)mallco_dev.membase;  
    mem_free(offset);//释放内存     
}

//分配内存(外部调用)
//memx:所属内存块
//size:内存大小(字节)
//返回值:分配到的内存首地址.
void *mymalloc(u32 size)  
{  
    u32 offset;                                            
    offset=mem_malloc(size);                            
    if(offset==0XFFFFFFFF)return NULL;  
    else return (void*)((u32)mallco_dev.membase+offset);  
}  

//重新分配内存(外部调用)
//memx:所属内存块
//*ptr:旧内存首地址
//size:要分配的内存大小(字节)
//返回值:新分配到的内存首地址.
void *myrealloc(void *ptr,u32 size)  
{  
    u32 offset;  
    offset=mem_malloc(size);  
    if(offset==0XFFFFFFFF)return NULL;     
    else  
    {                                         
        mymemcpy((void*)((u32)mallco_dev.membase+offset),ptr,size);    //拷贝旧内存内容到新内存   
        myfree(ptr);                                                        //释放旧内存
        return (void*)((u32)mallco_dev.membase+offset);                  //返回新内存首地址
    }  
}

malloc.h


#ifndef __MALLOC_H
#define __MALLOC_H
#include "stm32f10x.h"
  
#ifndef NULL
#define NULL 0
#endif

#define MEM_BLOCK_SIZE              32                                      //内存块大小为32字节
#define MEM_MAX_SIZE                16*1024                                  //最大管理内存 2K
#define MEM_ALLOC_TABLE_SIZE    MEM_MAX_SIZE/MEM_BLOCK_SIZE //内存表大小
         
//内存管理控制器
struct _m_mallco_dev
{
    void (*init)(void);                    //初始化
    u8   (*perused)(void);                      //内存使用率
    u8       *membase;                    //内存池
    u16   *memmap;                     //内存管理状态表
    u8     memrdy;                         //内存管理是否就绪
};

extern struct _m_mallco_dev mallco_dev;     //在mallco.c里面定义

void mymemset(void *s,u8 c,u32 count);     //设置内存
void mymemcpy(void *des,void *src,u32 n);//复制内存 

void mem_init(void);                     //内存管理初始化函数
u32 mem_malloc(u32 size);         //内存分配
u8 mem_free(u32 offset);         //内存释放
u8 mem_perused(void);                 //获得内存使用率 

//用户调用函数
void myfree(void *ptr);              //内存释放
void *mymalloc(u32 size);            //内存分配
void *myrealloc(void *ptr,u32 size);//重新分配内存
#endif

 

最后

以上就是缓慢酸奶为你收集整理的STM32在使用CJSON库时程序不运行的问题描述及CJSON库代码的全部内容,希望文章能够帮你解决STM32在使用CJSON库时程序不运行的问题描述及CJSON库代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部