ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/JSON-XS/XS.xs
Revision: 1.3
Committed: Thu Mar 22 18:10:29 2007 UTC (17 years, 2 months ago) by root
Branch: MAIN
Changes since 1.2: +11 -2 lines
Log Message:
rant

File Contents

# User Rev Content
1 root 1.1 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5     #include "assert.h"
6     #include "string.h"
7     #include "stdlib.h"
8    
9     #define F_ASCII 0x00000001
10     #define F_UTF8 0x00000002
11     #define F_INDENT 0x00000004
12     #define F_CANONICAL 0x00000008
13     #define F_SPACE_BEFORE 0x00000010
14     #define F_SPACE_AFTER 0x00000020
15     #define F_JSON_RPC 0x00000040
16 root 1.3 #define F_ALLOW_NONREF 0x00000080
17 root 1.1
18 root 1.2 #define F_PRETTY F_INDENT | F_SPACE_BEFORE | F_SPACE_AFTER
19 root 1.1 #define F_DEFAULT 0
20    
21     #define INIT_SIZE 32 // initial scalar size to be allocated
22    
23     #define SB do {
24     #define SE } while (0)
25    
26     static HV *json_stash;
27    
28     // structure used for encoding JSON
29     typedef struct
30     {
31     char *cur;
32     STRLEN len; // SvLEN (sv)
33     char *end; // SvEND (sv)
34     SV *sv;
35     UV flags;
36     int max_recurse;
37     int indent;
38     } enc_t;
39    
40     // structure used for decoding JSON
41     typedef struct
42     {
43     char *cur;
44     char *end;
45     char *err;
46     UV flags;
47     } dec_t;
48    
49     static UV *
50     SvJSON (SV *sv)
51     {
52     if (!(SvROK (sv) && SvOBJECT (SvRV (sv)) && SvSTASH (SvRV (sv)) == json_stash))
53     croak ("object is not of type JSON::XS");
54    
55     return &SvUVX (SvRV (sv));
56     }
57    
58     /////////////////////////////////////////////////////////////////////////////
59    
60     static void
61     need (enc_t *enc, STRLEN len)
62     {
63     if (enc->cur + len >= enc->end)
64     {
65     STRLEN cur = enc->cur - SvPVX (enc->sv);
66     SvGROW (enc->sv, cur + len + 1);
67     enc->cur = SvPVX (enc->sv) + cur;
68     enc->end = SvEND (enc->sv);
69     }
70     }
71    
72     static void
73     encode_ch (enc_t *enc, char ch)
74     {
75     need (enc, 1);
76     *enc->cur++ = ch;
77     }
78    
79     static void
80     encode_str (enc_t *enc, char *str, STRLEN len, int is_utf8)
81     {
82     char *end = str + len;
83    
84     while (str < end)
85     {
86     unsigned char ch = *(unsigned char *)str;
87     if (ch >= 0x20 && ch < 0x80) // most common case
88     {
89     *enc->cur++ = ch;
90     str++;
91     }
92     else
93     {
94     STRLEN clen;
95     UV uch;
96    
97     if (is_utf8)
98     {
99     uch = utf8n_to_uvuni (str, end - str, &clen, UTF8_CHECK_ONLY);
100     if (clen < 0)
101     croak ("malformed UTF-8 character in string, cannot convert to JSON");
102     }
103     else
104     {
105     uch = ch;
106     clen = 1;
107     }
108    
109     need (enc, len += 6);
110    
111     if (uch < 0xa0 || enc->flags & F_ASCII)
112     {
113     if (uch > 0xFFFFUL)
114     {
115     len += 6;
116     need (enc, len += 6);
117     sprintf (enc->cur, "\\u%04x\\u%04x",
118     (uch - 0x10000) / 0x400 + 0xD800,
119     (uch - 0x10000) % 0x400 + 0xDC00);
120     enc->cur += 12;
121     }
122     else
123     {
124     sprintf (enc->cur, "\\u%04x", uch);
125     enc->cur += 6;
126     }
127     }
128     else if (is_utf8)
129     {
130     memcpy (enc->cur, str, clen);
131     enc->cur += clen;
132     }
133     else
134     enc->cur = uvuni_to_utf8_flags (enc->cur, uch, 0);
135    
136     str += clen;
137     }
138    
139     --len;
140     }
141     }
142    
143     #define INDENT SB \
144     if (enc->flags & F_INDENT) \
145     { \
146     int i_; \
147     need (enc, enc->indent); \
148     for (i_ = enc->indent * 3; i_--; )\
149     encode_ch (enc, ' '); \
150     } \
151     SE
152    
153 root 1.2 #define SPACE SB need (enc, 1); encode_ch (enc, ' '); SE
154 root 1.1 #define NL SB if (enc->flags & F_INDENT) { need (enc, 1); encode_ch (enc, '\n'); } SE
155     #define COMMA SB \
156     encode_ch (enc, ','); \
157     if (enc->flags & F_INDENT) \
158     NL; \
159     else if (enc->flags & F_SPACE_AFTER) \
160     SPACE; \
161     SE
162    
163     static void encode_sv (enc_t *enc, SV *sv);
164    
165     static void
166     encode_av (enc_t *enc, AV *av)
167     {
168     int i, len = av_len (av);
169    
170     encode_ch (enc, '['); NL;
171     ++enc->indent;
172    
173     for (i = 0; i <= len; ++i)
174     {
175     INDENT;
176     encode_sv (enc, *av_fetch (av, i, 0));
177    
178     if (i < len)
179     COMMA;
180     }
181    
182     NL;
183    
184     --enc->indent;
185     INDENT; encode_ch (enc, ']');
186     }
187    
188     static void
189     encode_he (enc_t *enc, HE *he)
190     {
191     encode_ch (enc, '"');
192    
193     if (HeKLEN (he) == HEf_SVKEY)
194     {
195     SV *sv = HeSVKEY (he);
196     STRLEN len;
197     char *str = SvPV (sv, len);
198    
199     encode_str (enc, str, len, SvUTF8 (sv));
200     }
201     else
202     encode_str (enc, HeKEY (he), HeKLEN (he), HeKUTF8 (he));
203    
204     encode_ch (enc, '"');
205    
206     if (enc->flags & F_SPACE_BEFORE) SPACE;
207     encode_ch (enc, ':');
208     if (enc->flags & F_SPACE_AFTER ) SPACE;
209     encode_sv (enc, HeVAL (he));
210     }
211    
212     // compare hash entries, used when all keys are bytestrings
213     static int
214     he_cmp_fast (const void *a_, const void *b_)
215     {
216     int cmp;
217    
218     HE *a = *(HE **)a_;
219     HE *b = *(HE **)b_;
220    
221     STRLEN la = HeKLEN (a);
222     STRLEN lb = HeKLEN (b);
223    
224     if (!(cmp == memcmp (HeKEY (a), HeKEY (b), la < lb ? la : lb)))
225     cmp = la < lb ? -1 : la == lb ? 0 : 1;
226    
227     return cmp;
228     }
229    
230     // compare hash entries, used when some keys are sv's or utf-x
231     static int
232     he_cmp_slow (const void *a, const void *b)
233     {
234     return sv_cmp (HeSVKEY_force (*(HE **)a), HeSVKEY_force (*(HE **)b));
235     }
236    
237     static void
238     encode_hv (enc_t *enc, HV *hv)
239     {
240     int count, i;
241    
242     encode_ch (enc, '{'); NL; ++enc->indent;
243    
244     if ((count = hv_iterinit (hv)))
245     {
246     // for canonical output we have to sort by keys first
247     // actually, this is mostly due to the stupid so-called
248     // security workaround added somewhere in 5.8.x.
249     // that randomises hash orderings
250     if (enc->flags & F_CANONICAL)
251     {
252     HE *he, *hes [count];
253     int fast = 1;
254    
255     i = 0;
256     while ((he = hv_iternext (hv)))
257     {
258     hes [i++] = he;
259     if (HeKLEN (he) < 0 || HeKUTF8 (he))
260     fast = 0;
261     }
262    
263     assert (i == count);
264    
265     if (fast)
266     qsort (hes, count, sizeof (HE *), he_cmp_fast);
267     else
268     {
269     // hack to disable "use bytes"
270     COP *oldcop = PL_curcop, cop;
271     cop.op_private = 0;
272     PL_curcop = &cop;
273    
274     SAVETMPS;
275     qsort (hes, count, sizeof (HE *), he_cmp_slow);
276     FREETMPS;
277    
278     PL_curcop = oldcop;
279     }
280    
281     for (i = 0; i < count; ++i)
282     {
283     INDENT;
284     encode_he (enc, hes [i]);
285    
286     if (i < count - 1)
287     COMMA;
288     }
289    
290     NL;
291     }
292     else
293     {
294     SV *sv;
295     HE *he = hv_iternext (hv);
296    
297     for (;;)
298     {
299     INDENT;
300     encode_he (enc, he);
301    
302     if (!(he = hv_iternext (hv)))
303     break;
304    
305     COMMA;
306     }
307    
308     NL;
309     }
310     }
311    
312     --enc->indent; INDENT; encode_ch (enc, '}');
313     }
314    
315     static void
316     encode_sv (enc_t *enc, SV *sv)
317     {
318     if (SvPOKp (sv))
319     {
320     STRLEN len;
321     char *str = SvPV (sv, len);
322     encode_ch (enc, '"');
323     encode_str (enc, str, len, SvUTF8 (sv));
324     encode_ch (enc, '"');
325     }
326     else if (SvNOKp (sv))
327     {
328     need (enc, NV_DIG + 32);
329     Gconvert (SvNVX (sv), NV_DIG, 0, enc->cur);
330     enc->cur += strlen (enc->cur);
331     }
332     else if (SvIOKp (sv))
333     {
334     need (enc, 64);
335     enc->cur +=
336     SvIsUV(sv)
337     ? snprintf (enc->cur, 64, "%"UVuf, (UV)SvUVX (sv))
338     : snprintf (enc->cur, 64, "%"IVdf, (IV)SvIVX (sv));
339     }
340     else if (SvROK (sv))
341     {
342     if (!--enc->max_recurse)
343     croak ("data structure too deep (hit recursion limit)");
344    
345     sv = SvRV (sv);
346    
347     switch (SvTYPE (sv))
348     {
349     case SVt_PVAV: encode_av (enc, (AV *)sv); break;
350     case SVt_PVHV: encode_hv (enc, (HV *)sv); break;
351    
352     default:
353     croak ("JSON can only represent references to arrays or hashes");
354     }
355     }
356     else if (!SvOK (sv))
357     encode_str (enc, "null", 4, 0);
358     else
359     croak ("encountered perl type that JSON cannot handle");
360     }
361    
362     static SV *
363     encode_json (SV *scalar, UV flags)
364     {
365 root 1.3 if (!(flags & F_ALLOW_NONREF) && !SvROK (scalar))
366     croak ("hash- or arraref required (not a simple scalar, use allow_nonref to allow this)");
367    
368 root 1.1 enc_t enc;
369     enc.flags = flags;
370     enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE));
371     enc.cur = SvPVX (enc.sv);
372     enc.end = SvEND (enc.sv);
373     enc.max_recurse = 0;
374     enc.indent = 0;
375    
376     SvPOK_only (enc.sv);
377     encode_sv (&enc, scalar);
378    
379     if (!(flags & (F_ASCII | F_UTF8)))
380     SvUTF8_on (enc.sv);
381    
382     SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv));
383     return enc.sv;
384     }
385    
386     /////////////////////////////////////////////////////////////////////////////
387    
388     #define WS \
389     for (;;) \
390     { \
391     char ch = *dec->cur; \
392     if (ch > 0x20 \
393     || (ch != 0x20 && ch != 0x0a && ch != 0x0d && ch != 0x09)) \
394     break; \
395     ++dec->cur; \
396     }
397    
398     #define ERR(reason) SB dec->err = reason; goto fail; SE
399     #define EXPECT_CH(ch) SB \
400     if (*dec->cur != ch) \
401     ERR (# ch " expected"); \
402     ++dec->cur; \
403     SE
404    
405     static SV *decode_sv (dec_t *dec);
406    
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];
413    
414     static UV
415     decode_4hex (dec_t *dec)
416     {
417     signed char d1, d2, d3, d4;
418    
419     d1 = decode_hexdigit [((unsigned char *)dec->cur) [0]];
420     if (d1 < 0) ERR ("four hexadecimal digits expected");
421     d2 = decode_hexdigit [((unsigned char *)dec->cur) [1]];
422     if (d2 < 0) ERR ("four hexadecimal digits expected");
423     d3 = decode_hexdigit [((unsigned char *)dec->cur) [2]];
424     if (d3 < 0) ERR ("four hexadecimal digits expected");
425     d4 = decode_hexdigit [((unsigned char *)dec->cur) [3]];
426     if (d4 < 0) ERR ("four hexadecimal digits expected");
427    
428     dec->cur += 4;
429    
430     return ((UV)d1) << 12
431     | ((UV)d2) << 8
432     | ((UV)d3) << 4
433     | ((UV)d4);
434    
435     fail:
436     return (UV)-1;
437     }
438    
439     static SV *
440     decode_str (dec_t *dec)
441     {
442     SV *sv = NEWSV (0,2);
443     STRLEN cur = 0;
444     int utf8 = 0;
445    
446     for (;;)
447     {
448     unsigned char ch = *(unsigned char *)dec->cur;
449    
450     if (ch == '"')
451     break;
452     else if (ch == '\\')
453     {
454     switch (*++dec->cur)
455     {
456     case '\\':
457     case '/':
458     case '"': APPEND_CH (*dec->cur++); break;
459    
460     case 'b': APPEND_CH ('\010'); ++dec->cur; break;
461     case 't': APPEND_CH ('\011'); ++dec->cur; break;
462     case 'n': APPEND_CH ('\012'); ++dec->cur; break;
463     case 'f': APPEND_CH ('\014'); ++dec->cur; break;
464     case 'r': APPEND_CH ('\015'); ++dec->cur; break;
465    
466     case 'u':
467     {
468     UV lo, hi;
469     ++dec->cur;
470    
471     hi = decode_4hex (dec);
472     if (hi == (UV)-1)
473     goto fail;
474    
475     // possibly a surrogate pair
476     if (hi >= 0xd800 && hi < 0xdc00)
477     {
478     if (dec->cur [0] != '\\' || dec->cur [1] != 'u')
479     ERR ("illegal surrogate character");
480    
481     dec->cur += 2;
482    
483     lo = decode_4hex (dec);
484     if (lo == (UV)-1)
485     goto fail;
486    
487     if (lo < 0xdc00 || lo >= 0xe000)
488     ERR ("surrogate pair expected");
489    
490     hi = (hi - 0xD800) * 0x400 + (lo - 0xDC00) + 0x10000;
491     }
492     else if (lo >= 0xdc00 && lo < 0xe000)
493     ERR ("illegal surrogate character");
494    
495     if (hi >= 0x80)
496     {
497     utf8 = 1;
498    
499     SvGROW (sv, cur + 4 + 1); // at most 4 bytes for 21 bits
500     cur = (char *)uvuni_to_utf8_flags (SvPVX (sv) + cur, hi, 0) - SvPVX (sv);
501     }
502     else
503     APPEND_CH (hi);
504     }
505     break;
506     }
507     }
508     else if (ch >= 0x20 && ch <= 0x7f)
509     APPEND_CH (*dec->cur++);
510     else if (ch >= 0x80)
511     {
512     STRLEN clen;
513     UV uch = utf8n_to_uvuni (dec->cur, dec->end - dec->cur, &clen, UTF8_CHECK_ONLY);
514     if (clen < 0)
515     ERR ("malformed UTF-8 character in string, cannot convert to JSON");
516    
517     SvGROW (sv, cur + clen + 1); // at most 4 bytes for 21 bits
518     memcpy (SvPVX (sv) + cur, dec->cur, clen);
519     dec->cur += clen;
520     }
521     else
522     ERR ("invalid character encountered");
523     }
524    
525     ++dec->cur;
526    
527     SvPOK_only (sv);
528    
529     SvCUR_set (sv, cur);
530     *SvEND (sv) = 0;
531    
532     if (utf8)
533     SvUTF8_on (sv);
534    
535     return sv;
536    
537     fail:
538     SvREFCNT_dec (sv);
539     return 0;
540     }
541    
542     static SV *
543     decode_num (dec_t *dec)
544     {
545     int is_nv = 0;
546     char *start = dec->cur;
547    
548     // [minus]
549     if (*dec->cur == '-')
550     ++dec->cur;
551    
552     if (*dec->cur == '0')
553     {
554     ++dec->cur;
555     if (*dec->cur >= '0' && *dec->cur <= '9')
556     ERR ("malformed number (leading zero must not be followed by another digit)");
557     }
558    
559     // int
560     while (*dec->cur >= '0' && *dec->cur <= '9')
561     ++dec->cur;
562    
563     // [frac]
564     if (*dec->cur == '.')
565     {
566     is_nv = 1;
567    
568     do
569     {
570     ++dec->cur;
571     }
572     while (*dec->cur >= '0' && *dec->cur <= '9');
573     }
574    
575     // [exp]
576     if (*dec->cur == 'e' || *dec->cur == 'E')
577     {
578     is_nv = 1;
579    
580     ++dec->cur;
581     if (*dec->cur == '-' || *dec->cur == '+')
582     ++dec->cur;
583    
584     while (*dec->cur >= '0' && *dec->cur <= '9')
585     ++dec->cur;
586     }
587    
588     if (!is_nv)
589     {
590     UV uv;
591     int numtype = grok_number (start, dec->cur - start, &uv);
592     if (numtype & IS_NUMBER_IN_UV)
593     if (numtype & IS_NUMBER_NEG)
594     {
595     if (uv < (UV)IV_MIN)
596     return newSViv (-(IV)uv);
597     }
598     else
599     return newSVuv (uv);
600     }
601    
602     return newSVnv (Atof (start));
603    
604     fail:
605     return 0;
606     }
607    
608     static SV *
609     decode_av (dec_t *dec)
610     {
611     AV *av = newAV ();
612    
613     for (;;)
614     {
615     SV *value;
616    
617     value = decode_sv (dec);
618     if (!value)
619     goto fail;
620    
621     av_push (av, value);
622    
623     WS;
624    
625     if (*dec->cur == ']')
626     {
627     ++dec->cur;
628     break;
629     }
630    
631     if (*dec->cur != ',')
632     ERR (", or ] expected while parsing array");
633    
634     ++dec->cur;
635     }
636    
637     return newRV_noinc ((SV *)av);
638    
639     fail:
640     SvREFCNT_dec (av);
641     return 0;
642     }
643    
644     static SV *
645     decode_hv (dec_t *dec)
646     {
647     HV *hv = newHV ();
648    
649     for (;;)
650     {
651     SV *key, *value;
652    
653     WS; EXPECT_CH ('"');
654    
655     key = decode_str (dec);
656     if (!key)
657     goto fail;
658    
659     WS; EXPECT_CH (':');
660    
661     value = decode_sv (dec);
662     if (!value)
663     {
664     SvREFCNT_dec (key);
665     goto fail;
666     }
667    
668     //TODO: optimise
669     hv_store_ent (hv, key, value, 0);
670    
671     WS;
672    
673     if (*dec->cur == '}')
674     {
675     ++dec->cur;
676     break;
677     }
678    
679     if (*dec->cur != ',')
680     ERR (", or } expected while parsing object/hash");
681    
682     ++dec->cur;
683     }
684    
685     return newRV_noinc ((SV *)hv);
686    
687     fail:
688     SvREFCNT_dec (hv);
689     return 0;
690     }
691    
692     static SV *
693     decode_sv (dec_t *dec)
694     {
695     WS;
696     switch (*dec->cur)
697     {
698     case '"': ++dec->cur; return decode_str (dec);
699     case '[': ++dec->cur; return decode_av (dec);
700     case '{': ++dec->cur; return decode_hv (dec);
701    
702     case '-':
703     case '0': case '1': case '2': case '3': case '4':
704     case '5': case '6': case '7': case '8': case '9':
705     return decode_num (dec);
706    
707     case 't':
708     if (dec->end - dec->cur >= 4 && !memcmp (dec->cur, "true", 4))
709     {
710     dec->cur += 4;
711     return newSViv (1);
712     }
713     else
714     ERR ("'true' expected");
715    
716     break;
717    
718     case 'f':
719     if (dec->end - dec->cur >= 5 && !memcmp (dec->cur, "false", 5))
720     {
721     dec->cur += 5;
722     return newSViv (0);
723     }
724     else
725     ERR ("'false' expected");
726    
727     break;
728    
729     case 'n':
730     if (dec->end - dec->cur >= 4 && !memcmp (dec->cur, "null", 4))
731     {
732     dec->cur += 4;
733     return newSViv (1);
734     }
735     else
736     ERR ("'null' expected");
737    
738     break;
739    
740     default:
741     ERR ("malformed json string");
742     break;
743     }
744    
745     fail:
746     return 0;
747     }
748    
749     static SV *
750     decode_json (SV *string, UV flags)
751     {
752     SV *sv;
753    
754     if (!(flags & F_UTF8))
755     sv_utf8_upgrade (string);
756    
757     SvGROW (string, SvCUR (string) + 1); // should basically be a NOP
758    
759     dec_t dec;
760     dec.flags = flags;
761     dec.cur = SvPVX (string);
762     dec.end = SvEND (string);
763     dec.err = 0;
764    
765     *dec.end = 1; // invalid anywhere
766     sv = decode_sv (&dec);
767     *dec.end = 0;
768    
769     if (!sv)
770     {
771     IV offset = utf8_distance (dec.cur, SvPVX (string));
772     SV *uni = sv_newmortal ();
773    
774     pv_uni_display (uni, dec.cur, dec.end - dec.cur, 20, UNI_DISPLAY_QQ);
775     croak ("%s, at character %d (%s)",
776     dec.err,
777     (int)offset,
778     dec.cur != dec.end ? SvPV_nolen (uni) : "(end of string)");
779     }
780    
781 root 1.3 sv = sv_2mortal (sv);
782    
783     if (!(dec.flags & F_ALLOW_NONREF) && !SvROK (sv))
784     croak ("JSON object or array expected (but number, string, true, false or null found, use allow_nonref to allow this)");
785    
786     return sv;
787 root 1.1 }
788    
789     MODULE = JSON::XS PACKAGE = JSON::XS
790    
791     BOOT:
792     {
793     int i;
794    
795     memset (decode_hexdigit, 0xff, 256);
796     for (i = 10; i--; )
797     decode_hexdigit ['0' + i] = i;
798    
799     for (i = 6; --i; )
800     {
801     decode_hexdigit ['a' + i] = 10 + i;
802     decode_hexdigit ['A' + i] = 10 + i;
803     }
804    
805     json_stash = gv_stashpv ("JSON::XS", 1);
806     }
807    
808     SV *new (char *dummy)
809     CODE:
810     RETVAL = sv_bless (newRV_noinc (newSVuv (F_DEFAULT)), json_stash);
811     OUTPUT:
812     RETVAL
813    
814     SV *ascii (SV *self, int enable)
815     ALIAS:
816     ascii = F_ASCII
817     utf8 = F_UTF8
818     indent = F_INDENT
819     canonical = F_CANONICAL
820     space_before = F_SPACE_BEFORE
821     space_after = F_SPACE_AFTER
822     json_rpc = F_JSON_RPC
823 root 1.2 pretty = F_PRETTY
824 root 1.3 allow_nonref = F_ALLOW_NONREF
825 root 1.1 CODE:
826     {
827     UV *uv = SvJSON (self);
828     if (enable)
829     *uv |= ix;
830     else
831     *uv &= ~ix;
832    
833     RETVAL = newSVsv (self);
834     }
835     OUTPUT:
836     RETVAL
837    
838     void encode (SV *self, SV *scalar)
839     PPCODE:
840     XPUSHs (encode_json (scalar, *SvJSON (self)));
841    
842 root 1.2 void decode (SV *self, SV *jsonstr)
843 root 1.1 PPCODE:
844 root 1.2 XPUSHs (decode_json (jsonstr, *SvJSON (self)));
845    
846     void to_json (SV *scalar)
847     PPCODE:
848     XPUSHs (encode_json (scalar, F_UTF8));
849    
850     void from_json (SV *jsonstr)
851     PPCODE:
852     XPUSHs (decode_json (jsonstr, F_UTF8));
853 root 1.1