|    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); |