1. Parsing numbers
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++;/* have sign? */if (*num== ' 0 ') num++;/* is zero */if (*num>= ' 1 ' && *num<= ' 9 ') don= (n*10.0) + (*num++-' 0 '), while (*num>= ' 0 ' && *num<= ' 9 '); */* number? */if (*num== '. && num[1]>= ' 0 ' && num[1]<= ' 9 ') {num++;d on= (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 ' && *n um<= ' 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;}
Item is a Cjson object that is passed in, and Num is the starting number.
1. Resolve the positive and negative, sign mark, 1 is negative
2. Judging is not 0
3. Determine the number before the decimal point, that is-3.2 e 5, the preceding 3.2, this is divided into two parts, before and after the decimal point
4. E or E, which is the second half of the scientific count, is the time to deal with the question of whether the scientific count is positive or negative and is recorded with Signsubscale.
5. And then directly parse, here the author used a small technique, the author directly in the analysis of the front base of the part, parsing out is an integer, with scale record, finally with science and technology get back on OK, very ingenious.
6. Then return the number and parse out an object.
2. Parsing strings
static const char *parse_string (Cjson *item,const char *str) {const char *ptr=str+1;char *ptr2;char *out;int Len=0;unsigne D uc,uc2;if (*str!= ' "') {Ep=str;return 0;} /* Not a string! */while (*ptr!= ' \ ' && *ptr && ++len) if (*ptr++ = = ' \ \ ') ptr++;/* Skip escaped quotes. *///Jump to the last of the string to out= (char*) Cjson_malloc (len+1); */* This is what long we need for the string, roughly. *///Pre-Request a space size of a string if (!out) return 0; If the application is unsuccessful, exit ptr=str+1;ptr2=out; Start again, PTR2 set to the point where the out begins while (*ptr!= ' \ ' && *ptr) {if (*ptr!= ' \ \ ') *ptr2++=*ptr++; Under normal circumstances, run straight down the line Else{ptr++;switch (*ptr) {case ' B ': *ptr2++= ' \b '; In special cases, the case ' F ': *ptr2++= ' \f '; Break;case ' n ': *ptr2++= ' \ n '; Break;case ' R ': *ptr2++= ' \ r '; Break;case ' t ': *ptr2++ = ' \ t '; break;case ' u ':/* transcodeUtf16 to UTF8. *///unicode to handle the uc=parse_hex4 (ptr+1);p tr+=4;/* get the Unicode char. *///parse hex in the back, just put the last four bits out, if ((uc>=0xdc00 && uc<=0xdfff) | | uc==0) break;/* Check for invalid.*/if (uc>=0xd800 && uc<=0x DBFF)/* UTF16 surrogate pairs.*/{if (ptr[1]!= ' \ \ ' | | ptr[2]!= ' u ') break;/* missing second-half of Surrogate.*/uc2=parse_ Hex4 (ptr+3);p tr+=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;}
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;}
In addition to transcoding, the rest is relatively simple, is to apply a string, and then copy the past.
3. Parsing an array
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. */}
If the content is not empty, then parse it down. It's OK.
4. Parse the object with {} to indicate
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. */}
is a value, a value is rolled down, and its values are recorded in the child record, the previous position. There is no big difference with the array.
These are the four main one.
Cjson Source code Interpretation (c) parsing strings, numbers, arrays, objects