| 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 unsigned char c = str.ptr[i]; |
| 397 || str.ptr[i] == '\\' |
397 bool escape = c < 0x20 || c == '\\' || c == '"' |
| 398 || str.ptr[i] == '"' |
398 || (escape_slash && c == '/'); |
| 399 || (escape_slash && str.ptr[i] == '/'); |
|
| 400 |
399 |
| 401 if (all_printable && escape) { |
400 if (all_printable && escape) { |
| 402 size_t capa = str.length + 32; |
401 size_t capa = str.length + 32; |
| 403 char *space = malloc(capa); |
402 char *space = malloc(capa); |
| 404 if (space == NULL) return cx_mutstrn(NULL, 0); |
403 if (space == NULL) return cx_mutstrn(NULL, 0); |
| 406 cxBufferWrite(str.ptr, 1, i, &buf); |
405 cxBufferWrite(str.ptr, 1, i, &buf); |
| 407 all_printable = false; |
406 all_printable = false; |
| 408 } |
407 } |
| 409 if (escape) { |
408 if (escape) { |
| 410 cxBufferPut(&buf, '\\'); |
409 cxBufferPut(&buf, '\\'); |
| 411 if (str.ptr[i] == '\"') { |
410 if (c == '\"') { |
| 412 cxBufferPut(&buf, '\"'); |
411 cxBufferPut(&buf, '\"'); |
| 413 } else if (str.ptr[i] == '\n') { |
412 } else if (c == '\n') { |
| 414 cxBufferPut(&buf, 'n'); |
413 cxBufferPut(&buf, 'n'); |
| 415 } else if (str.ptr[i] == '\t') { |
414 } else if (c == '\t') { |
| 416 cxBufferPut(&buf, 't'); |
415 cxBufferPut(&buf, 't'); |
| 417 } else if (str.ptr[i] == '\r') { |
416 } else if (c == '\r') { |
| 418 cxBufferPut(&buf, 'r'); |
417 cxBufferPut(&buf, 'r'); |
| 419 } else if (str.ptr[i] == '\\') { |
418 } else if (c == '\\') { |
| 420 cxBufferPut(&buf, '\\'); |
419 cxBufferPut(&buf, '\\'); |
| 421 } else if (str.ptr[i] == '/') { |
420 } else if (c == '/') { |
| 422 cxBufferPut(&buf, '/'); |
421 cxBufferPut(&buf, '/'); |
| 423 } else if (str.ptr[i] == '\f') { |
422 } else if (c == '\f') { |
| 424 cxBufferPut(&buf, 'f'); |
423 cxBufferPut(&buf, 'f'); |
| 425 } else if (str.ptr[i] == '\b') { |
424 } else if (c == '\b') { |
| 426 cxBufferPut(&buf, 'b'); |
425 cxBufferPut(&buf, 'b'); |
| 427 } else { |
426 } else { |
| 428 char code[6]; |
427 char code[6]; |
| 429 snprintf(code, sizeof(code), "u%04x", |
428 snprintf(code, sizeof(code), "u%04x", (unsigned int) c); |
| 430 (unsigned int)(0xff & str.ptr[i])); |
|
| 431 cxBufferPutString(&buf, code); |
429 cxBufferPutString(&buf, code); |
| 432 } |
430 } |
| 433 } else if (!all_printable) { |
431 } else if (!all_printable) { |
| 434 cxBufferPut(&buf, str.ptr[i]); |
432 cxBufferPut(&buf, c); |
| 435 } |
433 } |
| 436 } |
434 } |
| 437 if (!all_printable) { |
435 if (!all_printable) { |
| 438 str = cx_mutstrn(buf.space, buf.size); |
436 str = cx_mutstrn(buf.space, buf.size); |
| 439 } |
437 } |