| 384 result.ptr[result.length] = 0; |
384 result.ptr[result.length] = 0; |
| 385 |
385 |
| 386 return result; |
386 return result; |
| 387 } |
387 } |
| 388 |
388 |
| 389 static cxmutstr escape_string(cxmutstr str) { |
389 static cxmutstr escape_string(cxmutstr str, bool escape_slash) { |
| 390 // note: this function produces the string without enclosing quotes |
390 // note: this function produces the string without enclosing quotes |
| 391 // the reason is that we don't want to allocate memory just for that |
391 // the reason is that we don't want to allocate memory just for that |
| 392 CxBuffer buf = {0}; |
392 CxBuffer buf = {0}; |
| 393 |
393 |
| 394 bool all_printable = true; |
394 bool all_printable = true; |
| 395 for (size_t i = 0; i < str.length; i++) { |
395 for (size_t i = 0; i < str.length; i++) { |
| 396 bool escape = !isprint(str.ptr[i]) |
396 bool escape = !isprint(str.ptr[i]) |
| 397 || str.ptr[i] == '\\' |
397 || str.ptr[i] == '\\' |
| 398 || str.ptr[i] == '"' |
398 || str.ptr[i] == '"' |
| 399 // TODO: make escaping slash optional |
399 || (escape_slash && str.ptr[i] == '/'); |
| 400 || str.ptr[i] == '/'; |
|
| 401 |
400 |
| 402 if (all_printable && escape) { |
401 if (all_printable && escape) { |
| 403 size_t capa = str.length + 32; |
402 size_t capa = str.length + 32; |
| 404 char *space = malloc(capa); |
403 char *space = malloc(capa); |
| 405 if (space == NULL) return cx_mutstrn(NULL, 0); |
404 if (space == NULL) return cx_mutstrn(NULL, 0); |
| 1147 } |
1148 } |
| 1148 } |
1149 } |
| 1149 |
1150 |
| 1150 // the name |
1151 // the name |
| 1151 actual += wfunc("\"", 1, 1, target); |
1152 actual += wfunc("\"", 1, 1, target); |
| 1152 cxmutstr name = escape_string(member->name); |
1153 cxmutstr name = escape_string(member->name, settings->escape_slash); |
| 1153 actual += wfunc(name.ptr, 1, name.length, target); |
1154 actual += wfunc(name.ptr, 1, name.length, target); |
| 1154 if (name.ptr != member->name.ptr) { |
1155 if (name.ptr != member->name.ptr) { |
| 1155 cx_strfree(&name); |
1156 cx_strfree(&name); |
| 1156 } |
1157 } |
| 1157 actual += wfunc("\"", 1, 1, target); |
1158 actual += wfunc("\"", 1, 1, target); |
| 1217 expected++; |
1218 expected++; |
| 1218 break; |
1219 break; |
| 1219 } |
1220 } |
| 1220 case CX_JSON_STRING: { |
1221 case CX_JSON_STRING: { |
| 1221 actual += wfunc("\"", 1, 1, target); |
1222 actual += wfunc("\"", 1, 1, target); |
| 1222 cxmutstr str = escape_string(value->value.string); |
1223 cxmutstr str = escape_string(value->value.string, settings->escape_slash); |
| 1223 actual += wfunc(str.ptr, 1, str.length, target); |
1224 actual += wfunc(str.ptr, 1, str.length, target); |
| 1224 if (str.ptr != value->value.string.ptr) { |
1225 if (str.ptr != value->value.string.ptr) { |
| 1225 cx_strfree(&str); |
1226 cx_strfree(&str); |
| 1226 } |
1227 } |
| 1227 actual += wfunc("\"", 1, 1, target); |
1228 actual += wfunc("\"", 1, 1, target); |