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

File Contents

# Content
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 #define F_ALLOW_NONREF 0x00000080
17 #define F_SHRINK 0x00000100
18
19 #define F_PRETTY F_INDENT | F_SPACE_BEFORE | F_SPACE_AFTER
20 #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 const char *err;
47 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 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 /////////////////////////////////////////////////////////////////////////////
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 enc->end = SvPVX (enc->sv) + SvLEN (enc->sv);
79 }
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 need (enc, len);
95
96 while (str < end)
97 {
98 unsigned char ch = *(unsigned char *)str;
99
100 if (ch >= 0x20 && ch < 0x80) // most common case
101 {
102 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 ++str;
118 }
119 else
120 {
121 switch (ch)
122 {
123 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
129 default:
130 {
131 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
168 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 need (enc, len += 10); // never more than 11 bytes needed
182 enc->cur = uvuni_to_utf8_flags (enc->cur, uch, 0);
183 ++str;
184 }
185 }
186 }
187 }
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 #define SPACE SB need (enc, 1); encode_ch (enc, ' '); SE
204 #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 char *str;
248
249 SvGETMAGIC (sv);
250 str = SvPV (sv, len);
251
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 // hack to disable "use bytes"
323 COP *oldcop = PL_curcop, cop;
324 cop.op_private = 0;
325 PL_curcop = &cop;
326
327 SAVETMPS;
328 qsort (hes, count, sizeof (HE *), he_cmp_slow);
329 FREETMPS;
330
331 PL_curcop = oldcop;
332 }
333
334 for (i = 0; i < count; ++i)
335 {
336 INDENT;
337 encode_he (enc, hes [i]);
338
339 if (i < count - 1)
340 COMMA;
341 }
342
343 NL;
344 }
345 else
346 {
347 SV *sv;
348 HE *he = hv_iternext (hv);
349
350 for (;;)
351 {
352 INDENT;
353 encode_he (enc, he);
354
355 if (!(he = hv_iternext (hv)))
356 break;
357
358 COMMA;
359 }
360
361 NL;
362 }
363 }
364
365 --enc->indent; INDENT; encode_ch (enc, '}');
366 }
367
368 static void
369 encode_sv (enc_t *enc, SV *sv)
370 {
371 SvGETMAGIC (sv);
372
373 if (SvPOKp (sv))
374 {
375 STRLEN len;
376 char *str = SvPV (sv, len);
377 encode_ch (enc, '"');
378 encode_str (enc, str, len, SvUTF8 (sv));
379 encode_ch (enc, '"');
380 }
381 else if (SvNOKp (sv))
382 {
383 need (enc, NV_DIG + 32);
384 Gconvert (SvNVX (sv), NV_DIG, 0, enc->cur);
385 enc->cur += strlen (enc->cur);
386 }
387 else if (SvIOKp (sv))
388 {
389 need (enc, 64);
390 enc->cur +=
391 SvIsUV(sv)
392 ? snprintf (enc->cur, 64, "%"UVuf, (UV)SvUVX (sv))
393 : snprintf (enc->cur, 64, "%"IVdf, (IV)SvIVX (sv));
394 }
395 else if (SvROK (sv))
396 {
397 if (!--enc->max_recurse)
398 croak ("data structure too deep (hit recursion limit)");
399
400 sv = SvRV (sv);
401
402 switch (SvTYPE (sv))
403 {
404 case SVt_PVAV: encode_av (enc, (AV *)sv); break;
405 case SVt_PVHV: encode_hv (enc, (HV *)sv); break;
406
407 default:
408 croak ("JSON can only represent references to arrays or hashes");
409 }
410 }
411 else if (!SvOK (sv))
412 encode_str (enc, "null", 4, 0);
413 else
414 croak ("encountered perl type that JSON cannot handle");
415 }
416
417 static SV *
418 encode_json (SV *scalar, UV flags)
419 {
420 if (!(flags & F_ALLOW_NONREF) && !SvROK (scalar))
421 croak ("hash- or arraref required (not a simple scalar, use allow_nonref to allow this)");
422
423 enc_t enc;
424 enc.flags = flags;
425 enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE));
426 enc.cur = SvPVX (enc.sv);
427 enc.end = SvEND (enc.sv);
428 enc.max_recurse = 0;
429 enc.indent = 0;
430
431 SvPOK_only (enc.sv);
432 encode_sv (&enc, scalar);
433
434 if (!(flags & (F_ASCII | F_UTF8)))
435 SvUTF8_on (enc.sv);
436
437 SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv));
438
439 if (enc.flags & F_SHRINK)
440 shrink (enc.sv);
441
442 return enc.sv;
443 }
444
445 /////////////////////////////////////////////////////////////////////////////
446
447 #define WS \
448 for (;;) \
449 { \
450 char ch = *dec->cur; \
451 if (ch > 0x20 \
452 || (ch != 0x20 && ch != 0x0a && ch != 0x0d && ch != 0x09)) \
453 break; \
454 ++dec->cur; \
455 }
456
457 #define ERR(reason) SB dec->err = reason; goto fail; SE
458 #define EXPECT_CH(ch) SB \
459 if (*dec->cur != ch) \
460 ERR (# ch " expected"); \
461 ++dec->cur; \
462 SE
463
464 static SV *decode_sv (dec_t *dec);
465
466 static signed char decode_hexdigit[256];
467
468 static UV
469 decode_4hex (dec_t *dec)
470 {
471 signed char d1, d2, d3, d4;
472
473 d1 = decode_hexdigit [((unsigned char *)dec->cur) [0]];
474 if (d1 < 0) ERR ("four hexadecimal digits expected");
475 d2 = decode_hexdigit [((unsigned char *)dec->cur) [1]];
476 if (d2 < 0) ERR ("four hexadecimal digits expected");
477 d3 = decode_hexdigit [((unsigned char *)dec->cur) [2]];
478 if (d3 < 0) ERR ("four hexadecimal digits expected");
479 d4 = decode_hexdigit [((unsigned char *)dec->cur) [3]];
480 if (d4 < 0) ERR ("four hexadecimal digits expected");
481
482 dec->cur += 4;
483
484 return ((UV)d1) << 12
485 | ((UV)d2) << 8
486 | ((UV)d3) << 4
487 | ((UV)d4);
488
489 fail:
490 return (UV)-1;
491 }
492
493 #define APPEND_GROW(n) SB \
494 if (cur + (n) >= end) \
495 { \
496 STRLEN ofs = cur - SvPVX (sv); \
497 SvGROW (sv, ofs + (n) + 1); \
498 cur = SvPVX (sv) + ofs; \
499 end = SvEND (sv); \
500 } \
501 SE
502
503 #define APPEND_CH(ch) SB \
504 APPEND_GROW (1); \
505 *cur++ = (ch); \
506 SE
507
508 static SV *
509 decode_str (dec_t *dec)
510 {
511 SV *sv = NEWSV (0,2);
512 int utf8 = 0;
513 char *cur = SvPVX (sv);
514 char *end = SvEND (sv);
515
516 for (;;)
517 {
518 unsigned char ch = *(unsigned char *)dec->cur;
519
520 if (ch == '"')
521 break;
522 else if (ch == '\\')
523 {
524 switch (*++dec->cur)
525 {
526 case '\\':
527 case '/':
528 case '"': APPEND_CH (*dec->cur++); break;
529
530 case 'b': APPEND_CH ('\010'); ++dec->cur; break;
531 case 't': APPEND_CH ('\011'); ++dec->cur; break;
532 case 'n': APPEND_CH ('\012'); ++dec->cur; break;
533 case 'f': APPEND_CH ('\014'); ++dec->cur; break;
534 case 'r': APPEND_CH ('\015'); ++dec->cur; break;
535
536 case 'u':
537 {
538 UV lo, hi;
539 ++dec->cur;
540
541 hi = decode_4hex (dec);
542 if (hi == (UV)-1)
543 goto fail;
544
545 // possibly a surrogate pair
546 if (hi >= 0xd800 && hi < 0xdc00)
547 {
548 if (dec->cur [0] != '\\' || dec->cur [1] != 'u')
549 ERR ("missing low surrogate character in surrogate pair");
550
551 dec->cur += 2;
552
553 lo = decode_4hex (dec);
554 if (lo == (UV)-1)
555 goto fail;
556
557 if (lo < 0xdc00 || lo >= 0xe000)
558 ERR ("surrogate pair expected");
559
560 hi = (hi - 0xD800) * 0x400 + (lo - 0xDC00) + 0x10000;
561 }
562 else if (hi >= 0xdc00 && hi < 0xe000)
563 ERR ("missing high surrogate character in surrogate pair");
564
565 if (hi >= 0x80)
566 {
567 utf8 = 1;
568
569 APPEND_GROW (4); // at most 4 bytes for 21 bits
570 cur = (char *)uvuni_to_utf8_flags (cur, hi, 0);
571 }
572 else
573 APPEND_CH (hi);
574 }
575 break;
576
577 default:
578 --dec->cur;
579 ERR ("illegal backslash escape sequence in string");
580 }
581 }
582 else if (ch >= 0x20 && ch <= 0x7f)
583 APPEND_CH (*dec->cur++);
584 else if (ch >= 0x80)
585 {
586 STRLEN clen;
587 UV uch = utf8n_to_uvuni (dec->cur, dec->end - dec->cur, &clen, UTF8_CHECK_ONLY);
588 if (clen == (STRLEN)-1)
589 ERR ("malformed UTF-8 character in JSON string");
590
591 APPEND_GROW (clen);
592 do
593 {
594 *cur++ = *dec->cur++;
595 }
596 while (--clen);
597
598 utf8 = 1;
599 }
600 else if (dec->cur == dec->end)
601 ERR ("unexpected end of string while parsing json string");
602 else
603 ERR ("invalid character encountered");
604 }
605
606 ++dec->cur;
607
608 SvCUR_set (sv, cur - SvPVX (sv));
609
610 SvPOK_only (sv);
611 *SvEND (sv) = 0;
612
613 if (utf8)
614 SvUTF8_on (sv);
615
616 if (dec->flags & F_SHRINK)
617 shrink (sv);
618
619 return sv;
620
621 fail:
622 SvREFCNT_dec (sv);
623 return 0;
624 }
625
626 static SV *
627 decode_num (dec_t *dec)
628 {
629 int is_nv = 0;
630 char *start = dec->cur;
631
632 // [minus]
633 if (*dec->cur == '-')
634 ++dec->cur;
635
636 if (*dec->cur == '0')
637 {
638 ++dec->cur;
639 if (*dec->cur >= '0' && *dec->cur <= '9')
640 ERR ("malformed number (leading zero must not be followed by another digit)");
641 }
642 else if (*dec->cur < '0' || *dec->cur > '9')
643 ERR ("malformed number (no digits after initial minus)");
644 else
645 do
646 {
647 ++dec->cur;
648 }
649 while (*dec->cur >= '0' && *dec->cur <= '9');
650
651 // [frac]
652 if (*dec->cur == '.')
653 {
654 ++dec->cur;
655
656 if (*dec->cur < '0' || *dec->cur > '9')
657 ERR ("malformed number (no digits after decimal point)");
658
659 do
660 {
661 ++dec->cur;
662 }
663 while (*dec->cur >= '0' && *dec->cur <= '9');
664
665 is_nv = 1;
666 }
667
668 // [exp]
669 if (*dec->cur == 'e' || *dec->cur == 'E')
670 {
671 ++dec->cur;
672
673 if (*dec->cur == '-' || *dec->cur == '+')
674 ++dec->cur;
675
676 if (*dec->cur < '0' || *dec->cur > '9')
677 ERR ("malformed number (no digits after exp sign)");
678
679 do
680 {
681 ++dec->cur;
682 }
683 while (*dec->cur >= '0' && *dec->cur <= '9');
684
685 is_nv = 1;
686 }
687
688 if (!is_nv)
689 {
690 UV uv;
691 int numtype = grok_number (start, dec->cur - start, &uv);
692 if (numtype & IS_NUMBER_IN_UV)
693 if (numtype & IS_NUMBER_NEG)
694 {
695 if (uv < (UV)IV_MIN)
696 return newSViv (-(IV)uv);
697 }
698 else
699 return newSVuv (uv);
700 }
701
702 return newSVnv (Atof (start));
703
704 fail:
705 return 0;
706 }
707
708 static SV *
709 decode_av (dec_t *dec)
710 {
711 AV *av = newAV ();
712
713 WS;
714 if (*dec->cur == ']')
715 ++dec->cur;
716 else
717 for (;;)
718 {
719 SV *value;
720
721 value = decode_sv (dec);
722 if (!value)
723 goto fail;
724
725 av_push (av, value);
726
727 WS;
728
729 if (*dec->cur == ']')
730 {
731 ++dec->cur;
732 break;
733 }
734
735 if (*dec->cur != ',')
736 ERR (", or ] expected while parsing array");
737
738 ++dec->cur;
739 }
740
741 return newRV_noinc ((SV *)av);
742
743 fail:
744 SvREFCNT_dec (av);
745 return 0;
746 }
747
748 static SV *
749 decode_hv (dec_t *dec)
750 {
751 HV *hv = newHV ();
752
753 WS;
754 if (*dec->cur == '}')
755 ++dec->cur;
756 else
757 for (;;)
758 {
759 SV *key, *value;
760
761 WS; EXPECT_CH ('"');
762
763 key = decode_str (dec);
764 if (!key)
765 goto fail;
766
767 WS; EXPECT_CH (':');
768
769 value = decode_sv (dec);
770 if (!value)
771 {
772 SvREFCNT_dec (key);
773 goto fail;
774 }
775
776 //TODO: optimise
777 hv_store_ent (hv, key, value, 0);
778
779 WS;
780
781 if (*dec->cur == '}')
782 {
783 ++dec->cur;
784 break;
785 }
786
787 if (*dec->cur != ',')
788 ERR (", or } expected while parsing object/hash");
789
790 ++dec->cur;
791 }
792
793 return newRV_noinc ((SV *)hv);
794
795 fail:
796 SvREFCNT_dec (hv);
797 return 0;
798 }
799
800 static SV *
801 decode_sv (dec_t *dec)
802 {
803 WS;
804 switch (*dec->cur)
805 {
806 case '"': ++dec->cur; return decode_str (dec);
807 case '[': ++dec->cur; return decode_av (dec);
808 case '{': ++dec->cur; return decode_hv (dec);
809
810 case '-':
811 case '0': case '1': case '2': case '3': case '4':
812 case '5': case '6': case '7': case '8': case '9':
813 return decode_num (dec);
814
815 case 't':
816 if (dec->end - dec->cur >= 4 && !memcmp (dec->cur, "true", 4))
817 {
818 dec->cur += 4;
819 return newSViv (1);
820 }
821 else
822 ERR ("'true' expected");
823
824 break;
825
826 case 'f':
827 if (dec->end - dec->cur >= 5 && !memcmp (dec->cur, "false", 5))
828 {
829 dec->cur += 5;
830 return newSViv (0);
831 }
832 else
833 ERR ("'false' expected");
834
835 break;
836
837 case 'n':
838 if (dec->end - dec->cur >= 4 && !memcmp (dec->cur, "null", 4))
839 {
840 dec->cur += 4;
841 return newSVsv (&PL_sv_undef);
842 }
843 else
844 ERR ("'null' expected");
845
846 break;
847
848 default:
849 ERR ("malformed json string, neither array, object, number, string or atom");
850 break;
851 }
852
853 fail:
854 return 0;
855 }
856
857 static SV *
858 decode_json (SV *string, UV flags)
859 {
860 SV *sv;
861
862 if (flags & F_UTF8)
863 sv_utf8_downgrade (string, 0);
864 else
865 sv_utf8_upgrade (string);
866
867 SvGROW (string, SvCUR (string) + 1); // should basically be a NOP
868
869 dec_t dec;
870 dec.flags = flags;
871 dec.cur = SvPVX (string);
872 dec.end = SvEND (string);
873 dec.err = 0;
874
875 sv = decode_sv (&dec);
876
877 if (!sv)
878 {
879 IV offset = dec.flags & F_UTF8
880 ? dec.cur - SvPVX (string)
881 : utf8_distance (dec.cur, SvPVX (string));
882 SV *uni = sv_newmortal ();
883 // horrible hack to silence warning inside pv_uni_display
884 COP cop;
885 memset (&cop, 0, sizeof (cop));
886 cop.cop_warnings = pWARN_NONE;
887 SAVEVPTR (PL_curcop);
888 PL_curcop = &cop;
889
890 pv_uni_display (uni, dec.cur, dec.end - dec.cur, 20, UNI_DISPLAY_QQ);
891 croak ("%s, at character offset %d (%s)",
892 dec.err,
893 (int)offset,
894 dec.cur != dec.end ? SvPV_nolen (uni) : "(end of string)");
895 }
896
897 sv = sv_2mortal (sv);
898
899 if (!(dec.flags & F_ALLOW_NONREF) && !SvROK (sv))
900 croak ("JSON object or array expected (but number, string, true, false or null found, use allow_nonref to allow this)");
901
902 return sv;
903 }
904
905 MODULE = JSON::XS PACKAGE = JSON::XS
906
907 BOOT:
908 {
909 int i;
910
911 memset (decode_hexdigit, 0xff, 256);
912 for (i = 10; i--; )
913 decode_hexdigit ['0' + i] = i;
914
915 for (i = 7; i--; )
916 {
917 decode_hexdigit ['a' + i] = 10 + i;
918 decode_hexdigit ['A' + i] = 10 + i;
919 }
920
921 json_stash = gv_stashpv ("JSON::XS", 1);
922 }
923
924 PROTOTYPES: DISABLE
925
926 SV *new (char *dummy)
927 CODE:
928 RETVAL = sv_bless (newRV_noinc (newSVuv (F_DEFAULT)), json_stash);
929 OUTPUT:
930 RETVAL
931
932 SV *ascii (SV *self, int enable = 1)
933 ALIAS:
934 ascii = F_ASCII
935 utf8 = F_UTF8
936 indent = F_INDENT
937 canonical = F_CANONICAL
938 space_before = F_SPACE_BEFORE
939 space_after = F_SPACE_AFTER
940 json_rpc = F_JSON_RPC
941 pretty = F_PRETTY
942 allow_nonref = F_ALLOW_NONREF
943 shrink = F_SHRINK
944 CODE:
945 {
946 UV *uv = SvJSON (self);
947 if (enable)
948 *uv |= ix;
949 else
950 *uv &= ~ix;
951
952 RETVAL = newSVsv (self);
953 }
954 OUTPUT:
955 RETVAL
956
957 void encode (SV *self, SV *scalar)
958 PPCODE:
959 XPUSHs (encode_json (scalar, *SvJSON (self)));
960
961 void decode (SV *self, SV *jsonstr)
962 PPCODE:
963 XPUSHs (decode_json (jsonstr, *SvJSON (self)));
964
965 PROTOTYPES: ENABLE
966
967 void to_json (SV *scalar)
968 PPCODE:
969 XPUSHs (encode_json (scalar, F_UTF8));
970
971 void from_json (SV *jsonstr)
972 PPCODE:
973 XPUSHs (decode_json (jsonstr, F_UTF8));
974