[svn-upgrade] Integrating new upstream version, libjson-xs-perl (2.270)
Jonathan Yu
14 years ago
0 | 0 | Revision history for Perl extension JSON::XS |
1 | ||
2 | 2.27 Thu Jan 7 07:35:08 CET 2010 | |
3 | - support relaxed option inside the incremental parser | |
4 | (testcase provided by IKEGAMI via Makamaka). | |
5 | ||
6 | 2.26 Sat Oct 10 03:26:19 CEST 2009 | |
7 | - big integers could become truncated (based on patch | |
8 | by Strobl Anton). | |
9 | - output format change: indent now adds a final newline, which is | |
10 | more expected and more true to the documentation. | |
1 | 11 | |
2 | 12 | 2.25 Sat Aug 8 12:04:41 CEST 2009 |
3 | 13 | - the perl debugger completely breaks lvalue subs - try to work |
29 | 29 | t/19_incr.t |
30 | 30 | t/20_faihu.t |
31 | 31 | t/21_evans.t |
32 | t/22_comment_at_eof.t | |
32 | 33 | t/99_binary.t |
33 | 34 | typemap |
34 | 35 | META.yml Module meta-data (added by MakeMaker) |
36 | META.json Module meta-data (added by MakeMaker) |
0 | {"no_index":{"directory":["t","inc"]},"meta-spec":{"version":1.4,"url":"http://module-build.sourceforge.net/META-spec-v1.4.html"},"generated_by":"ExtUtils::MakeMaker version 6.54","distribution_type":"module","version":"2.27","name":"JSON-XS","author":[],"license":"unknown","build_requires":{"ExtUtils::MakeMaker":0},"requires":{"common::sense":0},"abstract":null,"configure_requires":{"ExtUtils::MakeMaker":0}} |
8 | 8 | "version" : 1.4, |
9 | 9 | "url" : "http://module-build.sourceforge.net/META-spec-v1.4.html" |
10 | 10 | }, |
11 | "generated_by" : "ExtUtils::MakeMaker version 6.50", | |
11 | "generated_by" : "ExtUtils::MakeMaker version 6.54", | |
12 | 12 | "distribution_type" : "module", |
13 | "version" : "2.25", | |
13 | "version" : "2.27", | |
14 | 14 | "name" : "JSON-XS", |
15 | 15 | "author" : [], |
16 | 16 | "license" : "unknown", |
1154 | 1154 | This will *usually* generate JSON texts that also parse as valid YAML. |
1155 | 1155 | Please note that YAML has hardcoded limits on (simple) object key |
1156 | 1156 | lengths that JSON doesn't have and also has different and incompatible |
1157 | unicode handling, so you should make sure that your hash keys are | |
1158 | noticeably shorter than the 1024 "stream characters" YAML allows and | |
1159 | that you do not have characters with codepoint values outside the | |
1160 | Unicode BMP (basic multilingual page). YAML also does not allow "\/" | |
1157 | unicode character escape syntax, so you should make sure that your hash | |
1158 | keys are noticeably shorter than the 1024 "stream characters" YAML | |
1159 | allows and that you do not have characters with codepoint values outside | |
1160 | the Unicode BMP (basic multilingual page). YAML also does not allow "\/" | |
1161 | 1161 | sequences in strings (which JSON::XS does not *currently* generate, but |
1162 | 1162 | other JSON generators might). |
1163 | 1163 | |
1183 | 1183 | compatible to it, and educating users about the changes, instead of |
1184 | 1184 | spreading lies about the real compatibility for many *years* and |
1185 | 1185 | trying to silence people who point out that it isn't true. |
1186 | ||
1187 | Addendum/2009: the YAML 1.2 spec is still incomaptible with JSON, | |
1188 | even though the incompatibilities have been documented (and are | |
1189 | known to Brian) for many years and the spec makes explicit claims | |
1190 | that YAML is a superset of JSON. It would be so easy to fix, but | |
1191 | apparently, bullying and corrupting userdata is so much easier. | |
1186 | 1192 | |
1187 | 1193 | SPEED |
1188 | 1194 | It seems that JSON::XS is surprisingly fast, as shown in the following |
102 | 102 | |
103 | 103 | use common::sense; |
104 | 104 | |
105 | our $VERSION = '2.25'; | |
105 | our $VERSION = '2.27'; | |
106 | 106 | our @ISA = qw(Exporter); |
107 | 107 | |
108 | 108 | our @EXPORT = qw(encode_json decode_json to_json from_json); |
1269 | 1269 | This will I<usually> generate JSON texts that also parse as valid |
1270 | 1270 | YAML. Please note that YAML has hardcoded limits on (simple) object key |
1271 | 1271 | lengths that JSON doesn't have and also has different and incompatible |
1272 | unicode handling, so you should make sure that your hash keys are | |
1273 | noticeably shorter than the 1024 "stream characters" YAML allows and that | |
1274 | you do not have characters with codepoint values outside the Unicode BMP | |
1275 | (basic multilingual page). YAML also does not allow C<\/> sequences in | |
1276 | strings (which JSON::XS does not I<currently> generate, but other JSON | |
1277 | generators might). | |
1272 | unicode character escape syntax, so you should make sure that your hash | |
1273 | keys are noticeably shorter than the 1024 "stream characters" YAML allows | |
1274 | and that you do not have characters with codepoint values outside the | |
1275 | Unicode BMP (basic multilingual page). YAML also does not allow C<\/> | |
1276 | sequences in strings (which JSON::XS does not I<currently> generate, but | |
1277 | other JSON generators might). | |
1278 | 1278 | |
1279 | 1279 | There might be other incompatibilities that I am not aware of (or the YAML |
1280 | 1280 | specification has been changed yet again - it does so quite often). In |
1302 | 1302 | educating users about the changes, instead of spreading lies about the |
1303 | 1303 | real compatibility for many I<years> and trying to silence people who |
1304 | 1304 | point out that it isn't true. |
1305 | ||
1306 | Addendum/2009: the YAML 1.2 spec is still incomaptible with JSON, even | |
1307 | though the incompatibilities have been documented (and are known to | |
1308 | Brian) for many years and the spec makes explicit claims that YAML is a | |
1309 | superset of JSON. It would be so easy to fix, but apparently, bullying and | |
1310 | corrupting userdata is so much easier. | |
1305 | 1311 | |
1306 | 1312 | =back |
1307 | 1313 |
18 | 18 | # define UTF8_MAXBYTES 13 |
19 | 19 | #endif |
20 | 20 | |
21 | #define IVUV_MAXCHARS (sizeof (UV) * CHAR_BIT * 28 / 93 + 2) | |
21 | // three extra for rounding, sign, and end of string | |
22 | #define IVUV_MAXCHARS (sizeof (UV) * CHAR_BIT * 28 / 93 + 3) | |
22 | 23 | |
23 | 24 | #define F_ASCII 0x00000001UL |
24 | 25 | #define F_LATIN1 0x00000002UL |
77 | 78 | INCR_M_WS = 0, // initial whitespace skipping, must be 0 |
78 | 79 | INCR_M_STR, // inside string |
79 | 80 | INCR_M_BS, // inside backslash |
81 | INCR_M_C0, // inside comment in initial whitespace sequence | |
82 | INCR_M_C1, // inside comment in other places | |
80 | 83 | INCR_M_JSON // outside anything, count nesting |
81 | 84 | }; |
82 | 85 | |
760 | 763 | |
761 | 764 | SvPOK_only (enc.sv); |
762 | 765 | encode_sv (&enc, scalar); |
766 | encode_nl (&enc); | |
763 | 767 | |
764 | 768 | SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv)); |
765 | 769 | *SvEND (enc.sv) = 0; // many xs functions expect a trailing 0 for text strings |
949 | 953 | else if (ch >= 0x80) |
950 | 954 | { |
951 | 955 | STRLEN clen; |
952 | UV uch; | |
953 | 956 | |
954 | 957 | --dec_cur; |
955 | 958 | |
956 | uch = decode_utf8 (dec_cur, dec->end - dec_cur, &clen); | |
959 | decode_utf8 (dec_cur, dec->end - dec_cur, &clen); | |
957 | 960 | if (clen == (STRLEN)-1) |
958 | 961 | ERR ("malformed UTF-8 character in JSON string"); |
959 | 962 | |
1526 | 1529 | { |
1527 | 1530 | const char *p = SvPVX (self->incr_text) + self->incr_pos; |
1528 | 1531 | |
1532 | // the state machine here is a bit convoluted and could be simplified a lot | |
1533 | // but this would make it slower, so... | |
1534 | ||
1529 | 1535 | for (;;) |
1530 | 1536 | { |
1531 | 1537 | //printf ("loop pod %d *p<%c><%s>, mode %d nest %d\n", p - SvPVX (self->incr_text), *p, p, self->incr_mode, self->incr_nest);//D |
1532 | 1538 | switch (self->incr_mode) |
1533 | 1539 | { |
1534 | // only used for intiial whitespace skipping | |
1540 | // only used for initial whitespace skipping | |
1535 | 1541 | case INCR_M_WS: |
1536 | 1542 | for (;;) |
1537 | 1543 | { |
1538 | 1544 | if (*p > 0x20) |
1539 | 1545 | { |
1540 | self->incr_mode = INCR_M_JSON; | |
1541 | goto incr_m_json; | |
1546 | if (*p == '#') | |
1547 | { | |
1548 | self->incr_mode = INCR_M_C0; | |
1549 | goto incr_m_c; | |
1550 | } | |
1551 | else | |
1552 | { | |
1553 | self->incr_mode = INCR_M_JSON; | |
1554 | goto incr_m_json; | |
1555 | } | |
1542 | 1556 | } |
1543 | 1557 | else if (!*p) |
1544 | 1558 | goto interrupt; |
1554 | 1568 | ++p; |
1555 | 1569 | self->incr_mode = INCR_M_STR; |
1556 | 1570 | goto incr_m_str; |
1571 | ||
1572 | // inside #-style comments | |
1573 | case INCR_M_C0: | |
1574 | case INCR_M_C1: | |
1575 | incr_m_c: | |
1576 | for (;;) | |
1577 | { | |
1578 | if (*p == '\n') | |
1579 | { | |
1580 | self->incr_mode = self->incr_mode == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON; | |
1581 | break; | |
1582 | } | |
1583 | else if (!*p) | |
1584 | goto interrupt; | |
1585 | ||
1586 | ++p; | |
1587 | } | |
1588 | ||
1589 | break; | |
1557 | 1590 | |
1558 | 1591 | // inside a string |
1559 | 1592 | case INCR_M_STR: |
1622 | 1655 | case '}': |
1623 | 1656 | if (--self->incr_nest <= 0) |
1624 | 1657 | goto interrupt; |
1658 | break; | |
1659 | ||
1660 | case '#': | |
1661 | self->incr_mode = INCR_M_C1; | |
1662 | goto incr_m_c; | |
1625 | 1663 | } |
1626 | 1664 | } |
1627 | 1665 | } |
1632 | 1670 | |
1633 | 1671 | interrupt: |
1634 | 1672 | self->incr_pos = p - SvPVX (self->incr_text); |
1673 | //printf ("interrupt<%.*s>\n", self->incr_pos, SvPVX(self->incr_text));//D | |
1635 | 1674 | //printf ("return pos %d mode %d nest %d\n", self->incr_pos, self->incr_mode, self->incr_nest);//D |
1636 | 1675 | } |
1637 | 1676 |
10 | 10 | ok (JSON::XS->new->allow_nonref (1)->utf8 (1)->encode ("ü") eq "\"\xc3\xbc\""); |
11 | 11 | ok (JSON::XS->new->allow_nonref (1)->encode ("ü") eq "\"ü\""); |
12 | 12 | ok (JSON::XS->new->allow_nonref (1)->ascii (1)->utf8 (1)->encode (chr 0x8000) eq '"\u8000"'); |
13 | ok (JSON::XS->new->allow_nonref (1)->ascii (1)->utf8 (1)->pretty (1)->encode (chr 0x10402) eq '"\ud801\udc02"'); | |
13 | ok (JSON::XS->new->allow_nonref (1)->ascii (1)->utf8 (1)->pretty (1)->encode (chr 0x10402) eq "\"\\ud801\\udc02\"\n"); | |
14 | 14 | |
15 | 15 | eval { JSON::XS->new->allow_nonref (1)->utf8 (1)->decode ('"ü"') }; |
16 | 16 | ok $@ =~ /malformed UTF-8/; |
23 | 23 | { |
24 | 24 | "foo" : "bar" |
25 | 25 | } |
26 | ]|); | |
26 | ] | |
27 | |); | |
27 | 28 | |
28 | 29 | $obj = { foo => [ {a=>"b"}, 0, 1, 2 ] }; |
29 | 30 | $pc->pretty(0); |
43 | 44 | 1, |
44 | 45 | 2 |
45 | 46 | ] |
46 | }|); | |
47 | } | |
48 | |); | |
47 | 49 | |
48 | 50 | $obj = { foo => [ {a=>"b"}, 0, 1, 2 ] }; |
49 | 51 | $pc->pretty(0); |
53 | 55 | |
54 | 56 | $obj = {foo => "bar"}; |
55 | 57 | $pc->indent(1); |
56 | is($pc->encode($obj), qq|{\n "foo":"bar"\n}|, "nospace"); | |
58 | is($pc->encode($obj), qq|{\n "foo":"bar"\n}\n|, "nospace"); | |
57 | 59 | $pc->space_after(1); |
58 | is($pc->encode($obj), qq|{\n "foo": "bar"\n}|, "after"); | |
60 | is($pc->encode($obj), qq|{\n "foo": "bar"\n}\n|, "after"); | |
59 | 61 | $pc->space_before(1); |
60 | is($pc->encode($obj), qq|{\n "foo" : "bar"\n}|, "both"); | |
62 | is($pc->encode($obj), qq|{\n "foo" : "bar"\n}\n|, "both"); | |
61 | 63 | $pc->space_after(0); |
62 | is($pc->encode($obj), qq|{\n "foo" :"bar"\n}|, "before"); | |
64 | is($pc->encode($obj), qq|{\n "foo" :"bar"\n}\n|, "before"); | |
63 | 65 |
0 | # provided by IKEGAMI@cpan.org | |
1 | ||
2 | use strict; | |
3 | use warnings; | |
4 | ||
5 | use Test::More tests => 13; | |
6 | ||
7 | use JSON::XS; | |
8 | ||
9 | use Data::Dumper qw( Dumper ); | |
10 | ||
11 | sub decoder { | |
12 | my ($str) = @_; | |
13 | ||
14 | my $json = JSON::XS->new->relaxed; | |
15 | ||
16 | $json->incr_parse($_[0]); | |
17 | ||
18 | my $rv; | |
19 | if (!eval { $rv = $json->incr_parse(); 1 }) { | |
20 | $rv = "died with $@"; | |
21 | } | |
22 | ||
23 | local $Data::Dumper::Useqq = 1; | |
24 | local $Data::Dumper::Terse = 1; | |
25 | local $Data::Dumper::Indent = 0; | |
26 | ||
27 | return Dumper($rv); | |
28 | } | |
29 | ||
30 | is( decoder( "[]" ), '[]', 'array baseline' ); | |
31 | is( decoder( " []" ), '[]', 'space ignored before array' ); | |
32 | is( decoder( "\n[]" ), '[]', 'newline ignored before array' ); | |
33 | is( decoder( "# foo\n[]" ), '[]', 'comment ignored before array' ); | |
34 | is( decoder( "# fo[o\n[]"), '[]', 'comment ignored before array' ); | |
35 | is( decoder( "# fo]o\n[]"), '[]', 'comment ignored before array' ); | |
36 | is( decoder( "[# fo]o\n]"), '[]', 'comment ignored inside array' ); | |
37 | ||
38 | is( decoder( "" ), 'undef', 'eof baseline' ); | |
39 | is( decoder( " " ), 'undef', 'space ignored before eof' ); | |
40 | is( decoder( "\n" ), 'undef', 'newline ignored before eof' ); | |
41 | is( decoder( "#,foo\n" ), 'undef', 'comment ignored before eof' ); | |
42 | is( decoder( "# []o\n" ), 'undef', 'comment ignored before eof' ); | |
43 | ||
44 | is( decoder(qq/#\n[#foo\n"#\\n"#\n]/), '["#\n"]', 'array and string in multiple lines' ); | |
45 |