ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/JSON-XS/XS.xs
(Generate patch)

Comparing JSON-XS/XS.xs (file contents):
Revision 1.6 by root, Fri Mar 23 15:10:55 2007 UTC vs.
Revision 1.11 by root, Sat Mar 24 19:42:14 2007 UTC

10#define F_UTF8 0x00000002 10#define F_UTF8 0x00000002
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
16#define F_ALLOW_NONREF 0x00000080 15#define F_ALLOW_NONREF 0x00000080
17#define F_SHRINK 0x00000100 16#define F_SHRINK 0x00000100
18 17
19#define F_PRETTY F_INDENT | F_SPACE_BEFORE | F_SPACE_AFTER 18#define F_PRETTY F_INDENT | F_SPACE_BEFORE | F_SPACE_AFTER
20#define F_DEFAULT 0 19#define F_DEFAULT 0
52{ 51{
53 if (!(SvROK (sv) && SvOBJECT (SvRV (sv)) && SvSTASH (SvRV (sv)) == json_stash)) 52 if (!(SvROK (sv) && SvOBJECT (SvRV (sv)) && SvSTASH (SvRV (sv)) == json_stash))
54 croak ("object is not of type JSON::XS"); 53 croak ("object is not of type JSON::XS");
55 54
56 return &SvUVX (SvRV (sv)); 55 return &SvUVX (SvRV (sv));
56}
57
58static void
59shrink (SV *sv)
60{
61 sv_utf8_downgrade (sv, 1);
62#ifdef SvPV_shrink_to_cur
63 SvPV_shrink_to_cur (sv);
64#endif
57} 65}
58 66
59///////////////////////////////////////////////////////////////////////////// 67/////////////////////////////////////////////////////////////////////////////
60 68
61static void 69static void
124 132
125 if (is_utf8) 133 if (is_utf8)
126 { 134 {
127 uch = utf8n_to_uvuni (str, end - str, &clen, UTF8_CHECK_ONLY); 135 uch = utf8n_to_uvuni (str, end - str, &clen, UTF8_CHECK_ONLY);
128 if (clen == (STRLEN)-1) 136 if (clen == (STRLEN)-1)
129 croak ("malformed UTF-8 character in string, cannot convert to JSON"); 137 croak ("malformed or illegal unicode character in string [%.11s], cannot convert to JSON", str);
130 } 138 }
131 else 139 else
132 { 140 {
133 uch = ch; 141 uch = ch;
134 clen = 1; 142 clen = 1;
135 } 143 }
136 144
145 if (uch > 0x10FFFFUL)
146 croak ("out of range codepoint (0x%lx) encountered, unrepresentable in JSON", (unsigned long)uch);
147
137 if (uch < 0x80 || enc->flags & F_ASCII) 148 if (uch < 0x80 || enc->flags & F_ASCII)
138 { 149 {
139 if (uch > 0xFFFFUL) 150 if (uch > 0xFFFFUL)
140 { 151 {
141 need (enc, len += 11); 152 need (enc, len += 11);
142 sprintf (enc->cur, "\\u%04x\\u%04x", 153 sprintf (enc->cur, "\\u%04x\\u%04x",
143 (uch - 0x10000) / 0x400 + 0xD800, 154 (int)((uch - 0x10000) / 0x400 + 0xD800),
144 (uch - 0x10000) % 0x400 + 0xDC00); 155 (int)((uch - 0x10000) % 0x400 + 0xDC00));
145 enc->cur += 12; 156 enc->cur += 12;
146 } 157 }
147 else 158 else
148 { 159 {
149 static char hexdigit [16] = "0123456789abcdef"; 160 static char hexdigit [16] = "0123456789abcdef";
167 } 178 }
168 while (--clen); 179 while (--clen);
169 } 180 }
170 else 181 else
171 { 182 {
172 need (enc, 10); // never more than 11 bytes needed 183 need (enc, len += 10); // never more than 11 bytes needed
173 enc->cur = uvuni_to_utf8_flags (enc->cur, uch, 0); 184 enc->cur = uvuni_to_utf8_flags (enc->cur, uch, 0);
174 ++str; 185 ++str;
175 } 186 }
176 } 187 }
177 } 188 }
263 HE *b = *(HE **)b_; 274 HE *b = *(HE **)b_;
264 275
265 STRLEN la = HeKLEN (a); 276 STRLEN la = HeKLEN (a);
266 STRLEN lb = HeKLEN (b); 277 STRLEN lb = HeKLEN (b);
267 278
268 if (!(cmp == memcmp (HeKEY (a), HeKEY (b), la < lb ? la : lb))) 279 if (!(cmp = memcmp (HeKEY (a), HeKEY (b), la < lb ? la : lb)))
269 cmp = la < lb ? -1 : la == lb ? 0 : 1; 280 cmp = la - lb;
270 281
271 return cmp; 282 return cmp;
272} 283}
273 284
274// compare hash entries, used when some keys are sv's or utf-x 285// compare hash entries, used when some keys are sv's or utf-x
308 319
309 if (fast) 320 if (fast)
310 qsort (hes, count, sizeof (HE *), he_cmp_fast); 321 qsort (hes, count, sizeof (HE *), he_cmp_fast);
311 else 322 else
312 { 323 {
313 // hack to disable "use bytes" 324 // hack to forcefully disable "use bytes"
314 COP *oldcop = PL_curcop, cop; 325 COP cop = *PL_curcop;
315 cop.op_private = 0; 326 cop.op_private = 0;
327
328 ENTER;
329 SAVETMPS;
330
331 SAVEVPTR (PL_curcop);
316 PL_curcop = &cop; 332 PL_curcop = &cop;
317 333
318 SAVETMPS;
319 qsort (hes, count, sizeof (HE *), he_cmp_slow); 334 qsort (hes, count, sizeof (HE *), he_cmp_slow);
335
320 FREETMPS; 336 FREETMPS;
321 337 LEAVE;
322 PL_curcop = oldcop;
323 } 338 }
324 339
325 for (i = 0; i < count; ++i) 340 for (i = 0; i < count; ++i)
326 { 341 {
327 INDENT; 342 INDENT;
383 ? snprintf (enc->cur, 64, "%"UVuf, (UV)SvUVX (sv)) 398 ? snprintf (enc->cur, 64, "%"UVuf, (UV)SvUVX (sv))
384 : snprintf (enc->cur, 64, "%"IVdf, (IV)SvIVX (sv)); 399 : snprintf (enc->cur, 64, "%"IVdf, (IV)SvIVX (sv));
385 } 400 }
386 else if (SvROK (sv)) 401 else if (SvROK (sv))
387 { 402 {
403 SV *rv = SvRV (sv);
404
388 if (!--enc->max_recurse) 405 if (!--enc->max_recurse)
389 croak ("data structure too deep (hit recursion limit)"); 406 croak ("data structure too deep (hit recursion limit)");
390 407
391 sv = SvRV (sv);
392
393 switch (SvTYPE (sv)) 408 switch (SvTYPE (rv))
394 { 409 {
395 case SVt_PVAV: encode_av (enc, (AV *)sv); break; 410 case SVt_PVAV: encode_av (enc, (AV *)rv); break;
396 case SVt_PVHV: encode_hv (enc, (HV *)sv); break; 411 case SVt_PVHV: encode_hv (enc, (HV *)rv); break;
397 412
398 default: 413 default:
399 croak ("JSON can only represent references to arrays or hashes"); 414 croak ("encountered %s, but JSON can only represent references to arrays or hashes",
415 SvPV_nolen (sv));
400 } 416 }
401 } 417 }
402 else if (!SvOK (sv)) 418 else if (!SvOK (sv))
403 encode_str (enc, "null", 4, 0); 419 encode_str (enc, "null", 4, 0);
404 else 420 else
405 croak ("encountered perl type that JSON cannot handle"); 421 croak ("encountered perl type (%s,0x%x) that JSON cannot handle, you might want to report this",
422 SvPV_nolen (sv), SvFLAGS (sv));
406} 423}
407 424
408static SV * 425static SV *
409encode_json (SV *scalar, UV flags) 426encode_json (SV *scalar, UV flags)
410{ 427{
411 if (!(flags & F_ALLOW_NONREF) && !SvROK (scalar)) 428 if (!(flags & F_ALLOW_NONREF) && !SvROK (scalar))
412 croak ("hash- or arraref required (not a simple scalar, use allow_nonref to allow this)"); 429 croak ("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)");
413 430
414 enc_t enc; 431 enc_t enc;
415 enc.flags = flags; 432 enc.flags = flags;
416 enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); 433 enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE));
417 enc.cur = SvPVX (enc.sv); 434 enc.cur = SvPVX (enc.sv);
425 if (!(flags & (F_ASCII | F_UTF8))) 442 if (!(flags & (F_ASCII | F_UTF8)))
426 SvUTF8_on (enc.sv); 443 SvUTF8_on (enc.sv);
427 444
428 SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv)); 445 SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv));
429 446
430#ifdef SvPV_shrink_to_cur
431 if (enc.flags & F_SHRINK) 447 if (enc.flags & F_SHRINK)
432 SvPV_shrink_to_cur (enc.sv); 448 shrink (enc.sv);
433#endif 449
434 return enc.sv; 450 return enc.sv;
435} 451}
436 452
437///////////////////////////////////////////////////////////////////////////// 453/////////////////////////////////////////////////////////////////////////////
438 454
576 else if (ch >= 0x80) 592 else if (ch >= 0x80)
577 { 593 {
578 STRLEN clen; 594 STRLEN clen;
579 UV uch = utf8n_to_uvuni (dec->cur, dec->end - dec->cur, &clen, UTF8_CHECK_ONLY); 595 UV uch = utf8n_to_uvuni (dec->cur, dec->end - dec->cur, &clen, UTF8_CHECK_ONLY);
580 if (clen == (STRLEN)-1) 596 if (clen == (STRLEN)-1)
581 ERR ("malformed UTF-8 character in string, cannot convert to JSON"); 597 ERR ("malformed UTF-8 character in JSON string");
582 598
583 APPEND_GROW (clen); 599 APPEND_GROW (clen);
584 do 600 do
585 { 601 {
586 *cur++ = *dec->cur++; 602 *cur++ = *dec->cur++;
603 *SvEND (sv) = 0; 619 *SvEND (sv) = 0;
604 620
605 if (utf8) 621 if (utf8)
606 SvUTF8_on (sv); 622 SvUTF8_on (sv);
607 623
608#ifdef SvPV_shrink_to_cur
609 if (dec->flags & F_SHRINK) 624 if (dec->flags & F_SHRINK)
610 SvPV_shrink_to_cur (sv); 625 shrink (sv);
611#endif
612 626
613 return sv; 627 return sv;
614 628
615fail: 629fail:
616 SvREFCNT_dec (sv); 630 SvREFCNT_dec (sv);
838 ERR ("'null' expected"); 852 ERR ("'null' expected");
839 853
840 break; 854 break;
841 855
842 default: 856 default:
843 ERR ("malformed json string"); 857 ERR ("malformed json string, neither array, object, number, string or atom");
844 break; 858 break;
845 } 859 }
846 860
847fail: 861fail:
848 return 0; 862 return 0;
868 882
869 sv = decode_sv (&dec); 883 sv = decode_sv (&dec);
870 884
871 if (!sv) 885 if (!sv)
872 { 886 {
887 IV offset = dec.flags & F_UTF8
888 ? dec.cur - SvPVX (string)
873 IV offset = utf8_distance (dec.cur, SvPVX (string)); 889 : utf8_distance (dec.cur, SvPVX (string));
874 SV *uni = sv_newmortal (); 890 SV *uni = sv_newmortal ();
891
875 // horrible hack to silence warning inside pv_uni_display 892 // horrible hack to silence warning inside pv_uni_display
876 COP cop; 893 COP cop = *PL_curcop;
877 memset (&cop, 0, sizeof (cop));
878 cop.cop_warnings = pWARN_NONE; 894 cop.cop_warnings = pWARN_NONE;
895 ENTER;
879 SAVEVPTR (PL_curcop); 896 SAVEVPTR (PL_curcop);
880 PL_curcop = &cop; 897 PL_curcop = &cop;
881
882 pv_uni_display (uni, dec.cur, dec.end - dec.cur, 20, UNI_DISPLAY_QQ); 898 pv_uni_display (uni, dec.cur, dec.end - dec.cur, 20, UNI_DISPLAY_QQ);
899 LEAVE;
900
883 croak ("%s, at character offset %d (%s)", 901 croak ("%s, at character offset %d (%s)",
884 dec.err, 902 dec.err,
885 (int)offset, 903 (int)offset,
886 dec.cur != dec.end ? SvPV_nolen (uni) : "(end of string)"); 904 dec.cur != dec.end ? SvPV_nolen (uni) : "(end of string)");
887 } 905 }
888 906
889 sv = sv_2mortal (sv); 907 sv = sv_2mortal (sv);
890 908
891 if (!(dec.flags & F_ALLOW_NONREF) && !SvROK (sv)) 909 if (!(dec.flags & F_ALLOW_NONREF) && !SvROK (sv))
892 croak ("JSON object or array expected (but number, string, true, false or null found, use allow_nonref to allow this)"); 910 croak ("JSON text must be an object or array (but found number, string, true, false or null, use allow_nonref to allow this)");
893 911
894 return sv; 912 return sv;
895} 913}
896 914
897MODULE = JSON::XS PACKAGE = JSON::XS 915MODULE = JSON::XS PACKAGE = JSON::XS
927 utf8 = F_UTF8 945 utf8 = F_UTF8
928 indent = F_INDENT 946 indent = F_INDENT
929 canonical = F_CANONICAL 947 canonical = F_CANONICAL
930 space_before = F_SPACE_BEFORE 948 space_before = F_SPACE_BEFORE
931 space_after = F_SPACE_AFTER 949 space_after = F_SPACE_AFTER
932 json_rpc = F_JSON_RPC
933 pretty = F_PRETTY 950 pretty = F_PRETTY
934 allow_nonref = F_ALLOW_NONREF 951 allow_nonref = F_ALLOW_NONREF
935 shrink = F_SHRINK 952 shrink = F_SHRINK
936 CODE: 953 CODE:
937{ 954{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines