Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat https://www.fefe.de/libowfat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

55 lines
1.4 KiB

  1. #include "fmt.h"
  2. #include "textcode.h"
  3. #include "scan.h"
  4. size_t scan_jsonescape(const char *src,char *dest,size_t *destlen) {
  5. register const unsigned char* s=(const unsigned char*) src;
  6. size_t written=0,i;
  7. char c;
  8. unsigned int prev,cur,todo;
  9. prev=cur=(unsigned int)-1;
  10. for (i=0; s[i]; ++i) {
  11. if ((c=s[i])=='\\') {
  12. switch (s[i+1]) {
  13. case '\\':
  14. if (prev!=(unsigned int)-1) return 0; // lead surrogate not followed by tail surrogate
  15. // c='\\'; // c already is backslash
  16. break;
  17. case 'u':
  18. {
  19. size_t j;
  20. for (cur=j=0; j<4; ++j) {
  21. char x=scan_fromhex(s[i+2+j]);
  22. if (x<0) return 0; // not hex -> invalid input
  23. cur=(cur<<4) | x;
  24. }
  25. if (cur>=0xd800 && cur<=0xdbff) {
  26. // utf-16 surrogate pair; needs to be followed by another
  27. // surrogate. We need to read both and convert to UTF-8
  28. if (prev!=(unsigned int)-1) return 0; // two lead surrogates
  29. prev=cur;
  30. i+=5; // we want i to go up by 6, 1 is done by the for loop
  31. continue; // write nothing!
  32. } else if (cur>=0xdc00 && cur<=0xdfff) {
  33. todo=(cur&0x3ff) | ((prev&0x3ff) << 10) + 0x100000;
  34. } else
  35. todo=cur;
  36. written+=fmt_utf8(dest?dest+written:dest,todo);
  37. i+=5;
  38. prev=-1;
  39. continue;
  40. }
  41. default:
  42. if (prev!=(unsigned int)-1) return 0; // lead surrogate not followed by tail surrogate
  43. c=s[i+1];
  44. break;
  45. }
  46. ++i;
  47. }
  48. if (dest) dest[written]=c;
  49. ++written;
  50. }
  51. *destlen=written;
  52. return i;
  53. }