| 237 | static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, |
| 238 | 0xF8, 0xFC }; |
| 239 | static const char *parse_string(cJSON *item, const char *str, const char **ep) |
| 240 | { |
| 241 | const char *ptr = str + 1; |
| 242 | char *ptr2; |
| 243 | char *out; |
| 244 | int len = 0; |
| 245 | unsigned uc, uc2; |
| 246 | if (*str != '\"') |
| 247 | { |
| 248 | *ep = str; |
| 249 | return 0; |
| 250 | } /* not a string! */ |
| 251 | |
| 252 | while (*ptr != '\"' && *ptr && ++len) |
| 253 | if (*ptr++ == '\\') |
| 254 | ptr++; /* Skip escaped quotes. */ |
| 255 | |
| 256 | out = (char*) cJSON_malloc(len + 1); /* This is how long we need for the string, roughly. */ |
| 257 | if (!out) |
| 258 | return 0; |
| 259 | |
| 260 | ptr = str + 1; |
| 261 | ptr2 = out; |
| 262 | while (*ptr != '\"' && *ptr) |
| 263 | { |
| 264 | if (*ptr != '\\') |
| 265 | *ptr2++ = *ptr++; |
| 266 | else |
| 267 | { |
| 268 | ptr++; |
| 269 | switch (*ptr) |
| 270 | { |
| 271 | case 'b': |
| 272 | *ptr2++ = '\b'; |
| 273 | break; |
| 274 | case 'f': |
| 275 | *ptr2++ = '\f'; |
| 276 | break; |
| 277 | case 'n': |
| 278 | *ptr2++ = '\n'; |
| 279 | break; |
| 280 | case 'r': |
| 281 | *ptr2++ = '\r'; |
| 282 | break; |
| 283 | case 't': |
| 284 | *ptr2++ = '\t'; |
| 285 | break; |
| 286 | case 'u': /* transcode utf16 to utf8. */ |
| 287 | sscanf(ptr + 1, "%4x", &uc); |
| 288 | ptr += 4; /* get the unicode char. */ |
| 289 | |
| 290 | if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) |
| 291 | break; // check for invalid. |
| 292 | |
| 293 | if (uc >= 0xD800 && uc <= 0xDBFF) // UTF16 surrogate pairs. |
| 294 | { |
| 295 | if (ptr[1] != '\\' || ptr[2] != 'u') |
| 296 | break; // missing second-half of surrogate. |
no outgoing calls
no test coverage detected