… | |
… | |
11 | #define F_INDENT 0x00000004 |
11 | #define F_INDENT 0x00000004 |
12 | #define F_CANONICAL 0x00000008 |
12 | #define F_CANONICAL 0x00000008 |
13 | #define F_SPACE_BEFORE 0x00000010 |
13 | #define F_SPACE_BEFORE 0x00000010 |
14 | #define F_SPACE_AFTER 0x00000020 |
14 | #define F_SPACE_AFTER 0x00000020 |
15 | #define F_JSON_RPC 0x00000040 |
15 | #define F_JSON_RPC 0x00000040 |
|
|
16 | #define F_ALLOW_NONREF 0x00000080 |
16 | |
17 | |
|
|
18 | #define F_PRETTY F_INDENT | F_SPACE_BEFORE | F_SPACE_AFTER |
17 | #define F_DEFAULT 0 |
19 | #define F_DEFAULT 0 |
18 | |
20 | |
19 | #define INIT_SIZE 32 // initial scalar size to be allocated |
21 | #define INIT_SIZE 32 // initial scalar size to be allocated |
20 | |
22 | |
21 | #define SB do { |
23 | #define SB do { |
… | |
… | |
38 | // structure used for decoding JSON |
40 | // structure used for decoding JSON |
39 | typedef struct |
41 | typedef struct |
40 | { |
42 | { |
41 | char *cur; |
43 | char *cur; |
42 | char *end; |
44 | char *end; |
43 | char *err; |
45 | const char *err; |
44 | UV flags; |
46 | UV flags; |
45 | } dec_t; |
47 | } dec_t; |
46 | |
48 | |
47 | static UV * |
49 | static UV * |
48 | SvJSON (SV *sv) |
50 | SvJSON (SV *sv) |
… | |
… | |
61 | if (enc->cur + len >= enc->end) |
63 | if (enc->cur + len >= enc->end) |
62 | { |
64 | { |
63 | STRLEN cur = enc->cur - SvPVX (enc->sv); |
65 | STRLEN cur = enc->cur - SvPVX (enc->sv); |
64 | SvGROW (enc->sv, cur + len + 1); |
66 | SvGROW (enc->sv, cur + len + 1); |
65 | enc->cur = SvPVX (enc->sv) + cur; |
67 | enc->cur = SvPVX (enc->sv) + cur; |
66 | enc->end = SvEND (enc->sv); |
68 | enc->end = SvPVX (enc->sv) + SvLEN (enc->sv); |
67 | } |
69 | } |
68 | } |
70 | } |
69 | |
71 | |
70 | static void |
72 | static void |
71 | encode_ch (enc_t *enc, char ch) |
73 | encode_ch (enc_t *enc, char ch) |
… | |
… | |
77 | static void |
79 | static void |
78 | 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) |
79 | { |
81 | { |
80 | char *end = str + len; |
82 | char *end = str + len; |
81 | |
83 | |
|
|
84 | need (enc, len); |
|
|
85 | |
82 | while (str < end) |
86 | while (str < end) |
83 | { |
87 | { |
84 | 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 | } |
85 | if (ch >= 0x20 && ch < 0x80) // most common case |
104 | else if (ch >= 0x20 && ch < 0x80) // most common case |
86 | { |
105 | { |
87 | *enc->cur++ = ch; |
106 | *enc->cur++ = ch; |
88 | 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; |
89 | } |
122 | } |
90 | else |
123 | else |
91 | { |
124 | { |
92 | STRLEN clen; |
125 | STRLEN clen; |
93 | UV uch; |
126 | UV uch; |
… | |
… | |
102 | { |
135 | { |
103 | uch = ch; |
136 | uch = ch; |
104 | clen = 1; |
137 | clen = 1; |
105 | } |
138 | } |
106 | |
139 | |
107 | need (enc, len += 6); |
|
|
108 | |
|
|
109 | if (uch < 0xa0 || enc->flags & F_ASCII) |
140 | if (uch < 0x80 || enc->flags & F_ASCII) |
110 | { |
141 | { |
111 | if (uch > 0xFFFFUL) |
142 | if (uch > 0xFFFFUL) |
112 | { |
143 | { |
113 | len += 6; |
|
|
114 | need (enc, len += 6); |
144 | need (enc, len += 11); |
115 | sprintf (enc->cur, "\\u%04x\\u%04x", |
145 | sprintf (enc->cur, "\\u%04x\\u%04x", |
116 | (uch - 0x10000) / 0x400 + 0xD800, |
146 | (uch - 0x10000) / 0x400 + 0xD800, |
117 | (uch - 0x10000) % 0x400 + 0xDC00); |
147 | (uch - 0x10000) % 0x400 + 0xDC00); |
118 | enc->cur += 12; |
148 | enc->cur += 12; |
119 | } |
149 | } |
120 | else |
150 | else |
121 | { |
151 | { |
122 | sprintf (enc->cur, "\\u%04x", uch); |
152 | static char hexdigit [16] = "0123456789abcdef"; |
|
|
153 | need (enc, len += 5); |
|
|
154 | *enc->cur++ = '\\'; |
123 | 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]; |
124 | } |
160 | } |
|
|
161 | |
|
|
162 | str += clen; |
125 | } |
163 | } |
126 | else if (is_utf8) |
164 | else if (is_utf8) |
127 | { |
165 | { |
128 | memcpy (enc->cur, str, clen); |
166 | need (enc, len += clen); |
|
|
167 | while (clen--) |
129 | enc->cur += clen; |
168 | *enc->cur++ = *str++; |
130 | } |
169 | } |
131 | else |
170 | else |
|
|
171 | { |
|
|
172 | need (enc, 10); // never more than 11 bytes needed |
132 | enc->cur = uvuni_to_utf8_flags (enc->cur, uch, 0); |
173 | enc->cur = uvuni_to_utf8_flags (enc->cur, uch, 0); |
133 | |
174 | ++str; |
134 | str += clen; |
175 | } |
135 | } |
176 | } |
136 | |
177 | |
137 | --len; |
178 | --len; |
138 | } |
179 | } |
139 | } |
180 | } |
… | |
… | |
146 | for (i_ = enc->indent * 3; i_--; )\ |
187 | for (i_ = enc->indent * 3; i_--; )\ |
147 | encode_ch (enc, ' '); \ |
188 | encode_ch (enc, ' '); \ |
148 | } \ |
189 | } \ |
149 | SE |
190 | SE |
150 | |
191 | |
151 | #define SPACE SB if (enc->flags & F_INDENT) { need (enc, 1); encode_ch (enc, ' '); } SE |
192 | #define SPACE SB need (enc, 1); encode_ch (enc, ' '); SE |
152 | #define NL SB if (enc->flags & F_INDENT) { need (enc, 1); encode_ch (enc, '\n'); } SE |
193 | #define NL SB if (enc->flags & F_INDENT) { need (enc, 1); encode_ch (enc, '\n'); } SE |
153 | #define COMMA SB \ |
194 | #define COMMA SB \ |
154 | encode_ch (enc, ','); \ |
195 | encode_ch (enc, ','); \ |
155 | if (enc->flags & F_INDENT) \ |
196 | if (enc->flags & F_INDENT) \ |
156 | NL; \ |
197 | NL; \ |
… | |
… | |
190 | |
231 | |
191 | if (HeKLEN (he) == HEf_SVKEY) |
232 | if (HeKLEN (he) == HEf_SVKEY) |
192 | { |
233 | { |
193 | SV *sv = HeSVKEY (he); |
234 | SV *sv = HeSVKEY (he); |
194 | STRLEN len; |
235 | STRLEN len; |
|
|
236 | char *str; |
|
|
237 | |
|
|
238 | SvGETMAGIC (sv); |
195 | char *str = SvPV (sv, len); |
239 | str = SvPV (sv, len); |
196 | |
240 | |
197 | encode_str (enc, str, len, SvUTF8 (sv)); |
241 | encode_str (enc, str, len, SvUTF8 (sv)); |
198 | } |
242 | } |
199 | else |
243 | else |
200 | encode_str (enc, HeKEY (he), HeKLEN (he), HeKUTF8 (he)); |
244 | encode_str (enc, HeKEY (he), HeKLEN (he), HeKUTF8 (he)); |
… | |
… | |
311 | } |
355 | } |
312 | |
356 | |
313 | static void |
357 | static void |
314 | encode_sv (enc_t *enc, SV *sv) |
358 | encode_sv (enc_t *enc, SV *sv) |
315 | { |
359 | { |
|
|
360 | SvGETMAGIC (sv); |
|
|
361 | |
316 | if (SvPOKp (sv)) |
362 | if (SvPOKp (sv)) |
317 | { |
363 | { |
318 | STRLEN len; |
364 | STRLEN len; |
319 | char *str = SvPV (sv, len); |
365 | char *str = SvPV (sv, len); |
320 | encode_ch (enc, '"'); |
366 | encode_ch (enc, '"'); |
… | |
… | |
358 | } |
404 | } |
359 | |
405 | |
360 | static SV * |
406 | static SV * |
361 | encode_json (SV *scalar, UV flags) |
407 | encode_json (SV *scalar, UV flags) |
362 | { |
408 | { |
|
|
409 | if (!(flags & F_ALLOW_NONREF) && !SvROK (scalar)) |
|
|
410 | croak ("hash- or arraref required (not a simple scalar, use allow_nonref to allow this)"); |
|
|
411 | |
363 | enc_t enc; |
412 | enc_t enc; |
364 | enc.flags = flags; |
413 | enc.flags = flags; |
365 | enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); |
414 | enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); |
366 | enc.cur = SvPVX (enc.sv); |
415 | enc.cur = SvPVX (enc.sv); |
367 | enc.end = SvEND (enc.sv); |
416 | enc.end = SvEND (enc.sv); |
… | |
… | |
397 | ++dec->cur; \ |
446 | ++dec->cur; \ |
398 | SE |
447 | SE |
399 | |
448 | |
400 | static SV *decode_sv (dec_t *dec); |
449 | static SV *decode_sv (dec_t *dec); |
401 | |
450 | |
402 | #define APPEND_CH(ch) SB \ |
|
|
403 | SvGROW (sv, cur + 1 + 1); \ |
|
|
404 | SvPVX (sv)[cur++] = (ch); \ |
|
|
405 | SE |
|
|
406 | |
|
|
407 | static signed char decode_hexdigit[256]; |
451 | static signed char decode_hexdigit[256]; |
408 | |
452 | |
409 | static UV |
453 | static UV |
410 | decode_4hex (dec_t *dec) |
454 | decode_4hex (dec_t *dec) |
411 | { |
455 | { |
… | |
… | |
429 | |
473 | |
430 | fail: |
474 | fail: |
431 | return (UV)-1; |
475 | return (UV)-1; |
432 | } |
476 | } |
433 | |
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 | |
434 | static SV * |
493 | static SV * |
435 | decode_str (dec_t *dec) |
494 | decode_str (dec_t *dec) |
436 | { |
495 | { |
437 | SV *sv = NEWSV (0,2); |
496 | SV *sv = NEWSV (0,2); |
438 | STRLEN cur = 0; |
|
|
439 | int utf8 = 0; |
497 | int utf8 = 0; |
|
|
498 | char *cur = SvPVX (sv); |
|
|
499 | char *end = SvEND (sv); |
440 | |
500 | |
441 | for (;;) |
501 | for (;;) |
442 | { |
502 | { |
443 | unsigned char ch = *(unsigned char *)dec->cur; |
503 | unsigned char ch = *(unsigned char *)dec->cur; |
444 | |
504 | |
… | |
… | |
489 | |
549 | |
490 | if (hi >= 0x80) |
550 | if (hi >= 0x80) |
491 | { |
551 | { |
492 | utf8 = 1; |
552 | utf8 = 1; |
493 | |
553 | |
494 | SvGROW (sv, cur + 4 + 1); // at most 4 bytes for 21 bits |
554 | APPEND_GROW (4); // at most 4 bytes for 21 bits |
495 | cur = (char *)uvuni_to_utf8_flags (SvPVX (sv) + cur, hi, 0) - SvPVX (sv); |
555 | cur = (char *)uvuni_to_utf8_flags (cur, hi, 0); |
496 | } |
556 | } |
497 | else |
557 | else |
498 | APPEND_CH (hi); |
558 | APPEND_CH (hi); |
499 | } |
559 | } |
500 | break; |
560 | break; |
… | |
… | |
507 | STRLEN clen; |
567 | STRLEN clen; |
508 | 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); |
509 | if (clen < 0) |
569 | if (clen < 0) |
510 | ERR ("malformed UTF-8 character in string, cannot convert to JSON"); |
570 | ERR ("malformed UTF-8 character in string, cannot convert to JSON"); |
511 | |
571 | |
512 | SvGROW (sv, cur + clen + 1); // at most 4 bytes for 21 bits |
572 | APPEND_GROW (clen); |
513 | memcpy (SvPVX (sv) + cur, dec->cur, clen); |
573 | memcpy (cur, dec->cur, clen); |
|
|
574 | cur += clen; |
514 | dec->cur += clen; |
575 | dec->cur += clen; |
515 | } |
576 | } |
516 | else |
577 | else |
517 | ERR ("invalid character encountered"); |
578 | ERR ("invalid character encountered"); |
518 | } |
579 | } |
519 | |
580 | |
520 | ++dec->cur; |
581 | ++dec->cur; |
521 | |
582 | |
|
|
583 | SvCUR_set (sv, cur - SvPVX (sv)); |
|
|
584 | |
522 | SvPOK_only (sv); |
585 | SvPOK_only (sv); |
523 | |
|
|
524 | SvCUR_set (sv, cur); |
|
|
525 | *SvEND (sv) = 0; |
586 | *SvEND (sv) = 0; |
526 | |
587 | |
527 | if (utf8) |
588 | if (utf8) |
528 | SvUTF8_on (sv); |
589 | SvUTF8_on (sv); |
529 | |
590 | |
… | |
… | |
771 | dec.err, |
832 | dec.err, |
772 | (int)offset, |
833 | (int)offset, |
773 | dec.cur != dec.end ? SvPV_nolen (uni) : "(end of string)"); |
834 | dec.cur != dec.end ? SvPV_nolen (uni) : "(end of string)"); |
774 | } |
835 | } |
775 | |
836 | |
776 | sv_dump (sv);//D |
|
|
777 | return sv_2mortal (sv); |
837 | sv = sv_2mortal (sv); |
|
|
838 | |
|
|
839 | if (!(dec.flags & F_ALLOW_NONREF) && !SvROK (sv)) |
|
|
840 | croak ("JSON object or array expected (but number, string, true, false or null found, use allow_nonref to allow this)"); |
|
|
841 | |
|
|
842 | return sv; |
778 | } |
843 | } |
779 | |
844 | |
780 | MODULE = JSON::XS PACKAGE = JSON::XS |
845 | MODULE = JSON::XS PACKAGE = JSON::XS |
781 | |
846 | |
782 | BOOT: |
847 | BOOT: |
… | |
… | |
785 | |
850 | |
786 | memset (decode_hexdigit, 0xff, 256); |
851 | memset (decode_hexdigit, 0xff, 256); |
787 | for (i = 10; i--; ) |
852 | for (i = 10; i--; ) |
788 | decode_hexdigit ['0' + i] = i; |
853 | decode_hexdigit ['0' + i] = i; |
789 | |
854 | |
790 | for (i = 6; --i; ) |
855 | for (i = 7; i--; ) |
791 | { |
856 | { |
792 | decode_hexdigit ['a' + i] = 10 + i; |
857 | decode_hexdigit ['a' + i] = 10 + i; |
793 | decode_hexdigit ['A' + i] = 10 + i; |
858 | decode_hexdigit ['A' + i] = 10 + i; |
794 | } |
859 | } |
795 | |
860 | |
796 | json_stash = gv_stashpv ("JSON::XS", 1); |
861 | json_stash = gv_stashpv ("JSON::XS", 1); |
797 | } |
862 | } |
|
|
863 | |
|
|
864 | PROTOTYPES: DISABLE |
798 | |
865 | |
799 | SV *new (char *dummy) |
866 | SV *new (char *dummy) |
800 | CODE: |
867 | CODE: |
801 | RETVAL = sv_bless (newRV_noinc (newSVuv (F_DEFAULT)), json_stash); |
868 | RETVAL = sv_bless (newRV_noinc (newSVuv (F_DEFAULT)), json_stash); |
802 | OUTPUT: |
869 | OUTPUT: |
… | |
… | |
809 | indent = F_INDENT |
876 | indent = F_INDENT |
810 | canonical = F_CANONICAL |
877 | canonical = F_CANONICAL |
811 | space_before = F_SPACE_BEFORE |
878 | space_before = F_SPACE_BEFORE |
812 | space_after = F_SPACE_AFTER |
879 | space_after = F_SPACE_AFTER |
813 | json_rpc = F_JSON_RPC |
880 | json_rpc = F_JSON_RPC |
|
|
881 | pretty = F_PRETTY |
|
|
882 | allow_nonref = F_ALLOW_NONREF |
814 | CODE: |
883 | CODE: |
815 | { |
884 | { |
816 | UV *uv = SvJSON (self); |
885 | UV *uv = SvJSON (self); |
817 | if (enable) |
886 | if (enable) |
818 | *uv |= ix; |
887 | *uv |= ix; |
… | |
… | |
826 | |
895 | |
827 | void encode (SV *self, SV *scalar) |
896 | void encode (SV *self, SV *scalar) |
828 | PPCODE: |
897 | PPCODE: |
829 | XPUSHs (encode_json (scalar, *SvJSON (self))); |
898 | XPUSHs (encode_json (scalar, *SvJSON (self))); |
830 | |
899 | |
831 | void decode (SV *self, SV *jsondata) |
900 | void decode (SV *self, SV *jsonstr) |
832 | PPCODE: |
901 | PPCODE: |
833 | XPUSHs (decode_json (jsondata, *SvJSON (self))); |
902 | XPUSHs (decode_json (jsonstr, *SvJSON (self))); |
834 | |
903 | |
|
|
904 | PROTOTYPES: ENABLE |
|
|
905 | |
|
|
906 | void to_json (SV *scalar) |
|
|
907 | PPCODE: |
|
|
908 | XPUSHs (encode_json (scalar, F_UTF8)); |
|
|
909 | |
|
|
910 | void from_json (SV *jsonstr) |
|
|
911 | PPCODE: |
|
|
912 | XPUSHs (decode_json (jsonstr, F_UTF8)); |
|
|
913 | |