… | |
… | |
40 | // structure used for decoding JSON |
40 | // structure used for decoding JSON |
41 | typedef struct |
41 | typedef struct |
42 | { |
42 | { |
43 | char *cur; |
43 | char *cur; |
44 | char *end; |
44 | char *end; |
45 | char *err; |
45 | const char *err; |
46 | UV flags; |
46 | UV flags; |
47 | } dec_t; |
47 | } dec_t; |
48 | |
48 | |
49 | static UV * |
49 | static UV * |
50 | SvJSON (SV *sv) |
50 | SvJSON (SV *sv) |
… | |
… | |
63 | if (enc->cur + len >= enc->end) |
63 | if (enc->cur + len >= enc->end) |
64 | { |
64 | { |
65 | STRLEN cur = enc->cur - SvPVX (enc->sv); |
65 | STRLEN cur = enc->cur - SvPVX (enc->sv); |
66 | SvGROW (enc->sv, cur + len + 1); |
66 | SvGROW (enc->sv, cur + len + 1); |
67 | enc->cur = SvPVX (enc->sv) + cur; |
67 | enc->cur = SvPVX (enc->sv) + cur; |
68 | enc->end = SvEND (enc->sv); |
68 | enc->end = SvPVX (enc->sv) + SvLEN (enc->sv); |
69 | } |
69 | } |
70 | } |
70 | } |
71 | |
71 | |
72 | static void |
72 | static void |
73 | encode_ch (enc_t *enc, char ch) |
73 | encode_ch (enc_t *enc, char ch) |
… | |
… | |
79 | static void |
79 | static void |
80 | encode_str (enc_t *enc, char *str, STRLEN len, int is_utf8) |
80 | encode_str (enc_t *enc, char *str, STRLEN len, int is_utf8) |
81 | { |
81 | { |
82 | char *end = str + len; |
82 | char *end = str + len; |
83 | |
83 | |
|
|
84 | need (enc, len); |
|
|
85 | |
84 | while (str < end) |
86 | while (str < end) |
85 | { |
87 | { |
86 | unsigned char ch = *(unsigned char *)str; |
88 | unsigned char ch = *(unsigned char *)str; |
|
|
89 | |
|
|
90 | if (ch == '"') |
|
|
91 | { |
|
|
92 | need (enc, len += 1); |
|
|
93 | *enc->cur++ = '\\'; |
|
|
94 | *enc->cur++ = '"'; |
|
|
95 | ++str; |
|
|
96 | } |
|
|
97 | else if (ch == '\\') |
|
|
98 | { |
|
|
99 | need (enc, len += 1); |
|
|
100 | *enc->cur++ = '\\'; |
|
|
101 | *enc->cur++ = '\\'; |
|
|
102 | ++str; |
|
|
103 | } |
87 | if (ch >= 0x20 && ch < 0x80) // most common case |
104 | else if (ch >= 0x20 && ch < 0x80) // most common case |
88 | { |
105 | { |
89 | *enc->cur++ = ch; |
106 | *enc->cur++ = ch; |
90 | str++; |
107 | ++str; |
|
|
108 | } |
|
|
109 | else if (ch == '\015') |
|
|
110 | { |
|
|
111 | need (enc, len += 1); |
|
|
112 | *enc->cur++ = '\\'; |
|
|
113 | *enc->cur++ = 'r'; |
|
|
114 | ++str; |
|
|
115 | } |
|
|
116 | else if (ch == '\012') |
|
|
117 | { |
|
|
118 | need (enc, len += 1); |
|
|
119 | *enc->cur++ = '\\'; |
|
|
120 | *enc->cur++ = 'n'; |
|
|
121 | ++str; |
91 | } |
122 | } |
92 | else |
123 | else |
93 | { |
124 | { |
94 | STRLEN clen; |
125 | STRLEN clen; |
95 | UV uch; |
126 | UV uch; |
… | |
… | |
104 | { |
135 | { |
105 | uch = ch; |
136 | uch = ch; |
106 | clen = 1; |
137 | clen = 1; |
107 | } |
138 | } |
108 | |
139 | |
109 | need (enc, len += 6); |
|
|
110 | |
|
|
111 | if (uch < 0xa0 || enc->flags & F_ASCII) |
140 | if (uch < 0x80 || enc->flags & F_ASCII) |
112 | { |
141 | { |
113 | if (uch > 0xFFFFUL) |
142 | if (uch > 0xFFFFUL) |
114 | { |
143 | { |
115 | len += 6; |
|
|
116 | need (enc, len += 6); |
144 | need (enc, len += 11); |
117 | sprintf (enc->cur, "\\u%04x\\u%04x", |
145 | sprintf (enc->cur, "\\u%04x\\u%04x", |
118 | (uch - 0x10000) / 0x400 + 0xD800, |
146 | (uch - 0x10000) / 0x400 + 0xD800, |
119 | (uch - 0x10000) % 0x400 + 0xDC00); |
147 | (uch - 0x10000) % 0x400 + 0xDC00); |
120 | enc->cur += 12; |
148 | enc->cur += 12; |
121 | } |
149 | } |
122 | else |
150 | else |
123 | { |
151 | { |
124 | sprintf (enc->cur, "\\u%04x", uch); |
152 | static char hexdigit [16] = "0123456789abcdef"; |
|
|
153 | need (enc, len += 5); |
|
|
154 | *enc->cur++ = '\\'; |
125 | enc->cur += 6; |
155 | *enc->cur++ = 'u'; |
|
|
156 | *enc->cur++ = hexdigit [ uch >> 12 ]; |
|
|
157 | *enc->cur++ = hexdigit [(uch >> 8) & 15]; |
|
|
158 | *enc->cur++ = hexdigit [(uch >> 4) & 15]; |
|
|
159 | *enc->cur++ = hexdigit [(uch >> 0) & 15]; |
126 | } |
160 | } |
|
|
161 | |
|
|
162 | str += clen; |
127 | } |
163 | } |
128 | else if (is_utf8) |
164 | else if (is_utf8) |
129 | { |
165 | { |
130 | memcpy (enc->cur, str, clen); |
166 | need (enc, len += clen); |
|
|
167 | while (clen--) |
131 | enc->cur += clen; |
168 | *enc->cur++ = *str++; |
132 | } |
169 | } |
133 | else |
170 | else |
|
|
171 | { |
|
|
172 | need (enc, 10); // never more than 11 bytes needed |
134 | enc->cur = uvuni_to_utf8_flags (enc->cur, uch, 0); |
173 | enc->cur = uvuni_to_utf8_flags (enc->cur, uch, 0); |
135 | |
174 | ++str; |
136 | str += clen; |
175 | } |
137 | } |
176 | } |
138 | |
177 | |
139 | --len; |
178 | --len; |
140 | } |
179 | } |
141 | } |
180 | } |
… | |
… | |
192 | |
231 | |
193 | if (HeKLEN (he) == HEf_SVKEY) |
232 | if (HeKLEN (he) == HEf_SVKEY) |
194 | { |
233 | { |
195 | SV *sv = HeSVKEY (he); |
234 | SV *sv = HeSVKEY (he); |
196 | STRLEN len; |
235 | STRLEN len; |
|
|
236 | char *str; |
|
|
237 | |
|
|
238 | SvGETMAGIC (sv); |
197 | char *str = SvPV (sv, len); |
239 | str = SvPV (sv, len); |
198 | |
240 | |
199 | encode_str (enc, str, len, SvUTF8 (sv)); |
241 | encode_str (enc, str, len, SvUTF8 (sv)); |
200 | } |
242 | } |
201 | else |
243 | else |
202 | encode_str (enc, HeKEY (he), HeKLEN (he), HeKUTF8 (he)); |
244 | encode_str (enc, HeKEY (he), HeKLEN (he), HeKUTF8 (he)); |
… | |
… | |
313 | } |
355 | } |
314 | |
356 | |
315 | static void |
357 | static void |
316 | encode_sv (enc_t *enc, SV *sv) |
358 | encode_sv (enc_t *enc, SV *sv) |
317 | { |
359 | { |
|
|
360 | SvGETMAGIC (sv); |
|
|
361 | |
318 | if (SvPOKp (sv)) |
362 | if (SvPOKp (sv)) |
319 | { |
363 | { |
320 | STRLEN len; |
364 | STRLEN len; |
321 | char *str = SvPV (sv, len); |
365 | char *str = SvPV (sv, len); |
322 | encode_ch (enc, '"'); |
366 | encode_ch (enc, '"'); |
… | |
… | |
402 | ++dec->cur; \ |
446 | ++dec->cur; \ |
403 | SE |
447 | SE |
404 | |
448 | |
405 | static SV *decode_sv (dec_t *dec); |
449 | static SV *decode_sv (dec_t *dec); |
406 | |
450 | |
407 | #define APPEND_CH(ch) SB \ |
|
|
408 | SvGROW (sv, cur + 1 + 1); \ |
|
|
409 | SvPVX (sv)[cur++] = (ch); \ |
|
|
410 | SE |
|
|
411 | |
|
|
412 | static signed char decode_hexdigit[256]; |
451 | static signed char decode_hexdigit[256]; |
413 | |
452 | |
414 | static UV |
453 | static UV |
415 | decode_4hex (dec_t *dec) |
454 | decode_4hex (dec_t *dec) |
416 | { |
455 | { |
… | |
… | |
434 | |
473 | |
435 | fail: |
474 | fail: |
436 | return (UV)-1; |
475 | return (UV)-1; |
437 | } |
476 | } |
438 | |
477 | |
|
|
478 | #define APPEND_GROW(n) SB \ |
|
|
479 | if (cur + (n) >= end) \ |
|
|
480 | { \ |
|
|
481 | STRLEN ofs = cur - SvPVX (sv); \ |
|
|
482 | SvGROW (sv, ofs + (n) + 1); \ |
|
|
483 | cur = SvPVX (sv) + ofs; \ |
|
|
484 | end = SvEND (sv); \ |
|
|
485 | } \ |
|
|
486 | SE |
|
|
487 | |
|
|
488 | #define APPEND_CH(ch) SB \ |
|
|
489 | APPEND_GROW (1); \ |
|
|
490 | *cur++ = (ch); \ |
|
|
491 | SE |
|
|
492 | |
439 | static SV * |
493 | static SV * |
440 | decode_str (dec_t *dec) |
494 | decode_str (dec_t *dec) |
441 | { |
495 | { |
442 | SV *sv = NEWSV (0,2); |
496 | SV *sv = NEWSV (0,2); |
443 | STRLEN cur = 0; |
|
|
444 | int utf8 = 0; |
497 | int utf8 = 0; |
|
|
498 | char *cur = SvPVX (sv); |
|
|
499 | char *end = SvEND (sv); |
445 | |
500 | |
446 | for (;;) |
501 | for (;;) |
447 | { |
502 | { |
448 | unsigned char ch = *(unsigned char *)dec->cur; |
503 | unsigned char ch = *(unsigned char *)dec->cur; |
449 | |
504 | |
… | |
… | |
494 | |
549 | |
495 | if (hi >= 0x80) |
550 | if (hi >= 0x80) |
496 | { |
551 | { |
497 | utf8 = 1; |
552 | utf8 = 1; |
498 | |
553 | |
499 | SvGROW (sv, cur + 4 + 1); // at most 4 bytes for 21 bits |
554 | APPEND_GROW (4); // at most 4 bytes for 21 bits |
500 | cur = (char *)uvuni_to_utf8_flags (SvPVX (sv) + cur, hi, 0) - SvPVX (sv); |
555 | cur = (char *)uvuni_to_utf8_flags (cur, hi, 0); |
501 | } |
556 | } |
502 | else |
557 | else |
503 | APPEND_CH (hi); |
558 | APPEND_CH (hi); |
504 | } |
559 | } |
505 | break; |
560 | break; |
… | |
… | |
512 | STRLEN clen; |
567 | STRLEN clen; |
513 | UV uch = utf8n_to_uvuni (dec->cur, dec->end - dec->cur, &clen, UTF8_CHECK_ONLY); |
568 | UV uch = utf8n_to_uvuni (dec->cur, dec->end - dec->cur, &clen, UTF8_CHECK_ONLY); |
514 | if (clen < 0) |
569 | if (clen < 0) |
515 | ERR ("malformed UTF-8 character in string, cannot convert to JSON"); |
570 | ERR ("malformed UTF-8 character in string, cannot convert to JSON"); |
516 | |
571 | |
517 | SvGROW (sv, cur + clen + 1); // at most 4 bytes for 21 bits |
572 | APPEND_GROW (clen); |
518 | memcpy (SvPVX (sv) + cur, dec->cur, clen); |
573 | memcpy (cur, dec->cur, clen); |
|
|
574 | cur += clen; |
519 | dec->cur += clen; |
575 | dec->cur += clen; |
520 | } |
576 | } |
521 | else |
577 | else |
522 | ERR ("invalid character encountered"); |
578 | ERR ("invalid character encountered"); |
523 | } |
579 | } |
524 | |
580 | |
525 | ++dec->cur; |
581 | ++dec->cur; |
526 | |
582 | |
|
|
583 | SvCUR_set (sv, cur - SvPVX (sv)); |
|
|
584 | |
527 | SvPOK_only (sv); |
585 | SvPOK_only (sv); |
528 | |
|
|
529 | SvCUR_set (sv, cur); |
|
|
530 | *SvEND (sv) = 0; |
586 | *SvEND (sv) = 0; |
531 | |
587 | |
532 | if (utf8) |
588 | if (utf8) |
533 | SvUTF8_on (sv); |
589 | SvUTF8_on (sv); |
534 | |
590 | |
… | |
… | |
794 | |
850 | |
795 | memset (decode_hexdigit, 0xff, 256); |
851 | memset (decode_hexdigit, 0xff, 256); |
796 | for (i = 10; i--; ) |
852 | for (i = 10; i--; ) |
797 | decode_hexdigit ['0' + i] = i; |
853 | decode_hexdigit ['0' + i] = i; |
798 | |
854 | |
799 | for (i = 6; --i; ) |
855 | for (i = 7; i--; ) |
800 | { |
856 | { |
801 | decode_hexdigit ['a' + i] = 10 + i; |
857 | decode_hexdigit ['a' + i] = 10 + i; |
802 | decode_hexdigit ['A' + i] = 10 + i; |
858 | decode_hexdigit ['A' + i] = 10 + i; |
803 | } |
859 | } |
804 | |
860 | |
805 | json_stash = gv_stashpv ("JSON::XS", 1); |
861 | json_stash = gv_stashpv ("JSON::XS", 1); |
806 | } |
862 | } |
|
|
863 | |
|
|
864 | PROTOTYPES: DISABLE |
807 | |
865 | |
808 | SV *new (char *dummy) |
866 | SV *new (char *dummy) |
809 | CODE: |
867 | CODE: |
810 | RETVAL = sv_bless (newRV_noinc (newSVuv (F_DEFAULT)), json_stash); |
868 | RETVAL = sv_bless (newRV_noinc (newSVuv (F_DEFAULT)), json_stash); |
811 | OUTPUT: |
869 | OUTPUT: |
… | |
… | |
841 | |
899 | |
842 | void decode (SV *self, SV *jsonstr) |
900 | void decode (SV *self, SV *jsonstr) |
843 | PPCODE: |
901 | PPCODE: |
844 | XPUSHs (decode_json (jsonstr, *SvJSON (self))); |
902 | XPUSHs (decode_json (jsonstr, *SvJSON (self))); |
845 | |
903 | |
|
|
904 | PROTOTYPES: ENABLE |
|
|
905 | |
846 | void to_json (SV *scalar) |
906 | void to_json (SV *scalar) |
847 | PPCODE: |
907 | PPCODE: |
848 | XPUSHs (encode_json (scalar, F_UTF8)); |
908 | XPUSHs (encode_json (scalar, F_UTF8)); |
849 | |
909 | |
850 | void from_json (SV *jsonstr) |
910 | void from_json (SV *jsonstr) |