| 163 | /* Parse the input text into an unescaped cstring, and populate item. */ |
| 164 | static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; |
| 165 | static const char *parse_string(cJSON *item,const char *str) |
| 166 | { |
| 167 | const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; |
| 168 | if (*str!='\"') {ep=str;return 0;} /* not a string! */ |
| 169 | |
| 170 | while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ |
| 171 | |
| 172 | out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ |
| 173 | if (!out) return 0; |
| 174 | |
| 175 | ptr=str+1;ptr2=out; |
| 176 | while (*ptr!='\"' && *ptr) |
| 177 | { |
| 178 | if (*ptr!='\\') *ptr2++=*ptr++; |
| 179 | else |
| 180 | { |
| 181 | ptr++; |
| 182 | switch (*ptr) |
| 183 | { |
| 184 | case 'b': *ptr2++='\b'; break; |
| 185 | case 'f': *ptr2++='\f'; break; |
| 186 | case 'n': *ptr2++='\n'; break; |
| 187 | case 'r': *ptr2++='\r'; break; |
| 188 | case 't': *ptr2++='\t'; break; |
| 189 | case 'u': /* transcode utf16 to utf8. */ |
| 190 | if (scan_unicode(ptr+1, &uc) < 1) break; |
| 191 | ptr+=4; /* get the unicode char. */ |
| 192 | |
| 193 | if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; // check for invalid. |
| 194 | |
| 195 | if (uc>=0xD800 && uc<=0xDBFF) // UTF16 surrogate pairs. |
| 196 | { |
| 197 | if (ptr[1]!='\\' || ptr[2]!='u') break; // missing second-half of surrogate. |
| 198 | if (scan_unicode(ptr+3,&uc2) < 1) break; |
| 199 | ptr+=6; |
| 200 | if (uc2<0xDC00 || uc2>0xDFFF) break; // invalid second-half of surrogate. |
| 201 | uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF); |
| 202 | } |
| 203 | |
| 204 | len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; |
| 205 | |
| 206 | switch (len) { |
| 207 | case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; |
| 208 | case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; |
| 209 | case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; |
| 210 | case 1: *--ptr2 =(char)(uc | firstByteMark[len]); |
| 211 | } |
| 212 | ptr2+=len; |
| 213 | break; |
| 214 | default: *ptr2++=*ptr; break; |
| 215 | } |
| 216 | if (*ptr) ptr++; |
| 217 | } |
| 218 | } |
| 219 | *ptr2=0; |
| 220 | if (*ptr=='\"') ptr++; |
| 221 | item->valuestring=out; |
| 222 | item->type=cJSON_String; |
no test coverage detected