ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/JSON-XS/XS.xs
Revision: 1.8
Committed: Fri Mar 23 16:13:59 2007 UTC (17 years, 2 months ago) by root
Branch: MAIN
Changes since 1.7: +14 -8 lines
Log Message:
*** empty log message ***

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