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