File Coverage

XS.xs
Criterion Covered Total %
statement 1577 1773 88.9
branch 1307 2012 64.9
condition n/a
subroutine n/a
pod n/a
total 2884 3785 76.2


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5             #define NEED_load_module
6             #define NEED_newCONSTSUB
7             #define NEED_vload_module
8             #define NEED_vnewSVpvf
9             #define NEED_warner
10             #define NEED_grok_number
11             #define NEED_grok_numeric_radix
12             #define NEED_newRV_noinc
13             #define NEED_sv_2pv_flags
14             #include "ppport.h"
15              
16             #include
17             #include
18             #include
19             #include
20             #include
21             #include
22              
23             #if defined(__BORLANDC__) || defined(_MSC_VER)
24             # define snprintf _snprintf // C compilers have this in stdio.h
25             #endif
26              
27             #ifndef PERL_UNUSED_RESULT
28             # if defined(__GNUC__) && defined(HASATTRIBUTE_WARN_UNUSED_RESULT)
29             # define PERL_UNUSED_RESULT(v) STMT_START { __typeof__(v) z = (v); (void)sizeof(z); } STMT_END
30             # else
31             # define PERL_UNUSED_RESULT(v) ((void)(v))
32             # endif
33             #endif
34              
35             #if defined(_AIX) && (!defined(HAS_LONG_DOUBLE) || AIX_WORKAROUND)
36             #define HAVE_NO_POWL
37             #endif
38              
39             /* Freebsd 10: It has powl, but it is too bad. strtold is good. RT #101265 */
40             #if defined(__FreeBSD__) && defined(__clang__) && defined(USE_LONG_DOUBLE)
41             #define HAVE_BAD_POWL
42             #endif
43              
44             #if PERL_VERSION < 22 && defined(HAS_SETLOCALE)
45             #define NEED_NUMERIC_LOCALE_C
46             #ifdef I_XLOCALE
47             #include
48             #endif
49             #endif
50              
51             /* FIXME: still a refcount error */
52             #define HAVE_DECODE_BOM
53             #define UTF8BOM "\357\273\277" /* EF BB BF */
54             /* UTF16/32BOM is deprecated, RFC 8259 */
55             #define UTF16BOM "\377\376" /* FF FE or +UFEFF */
56             #define UTF16BOM_BE "\376\377" /* FE FF */
57             #define UTF32BOM "\377\376\000\000" /* FF FE 00 00 or +UFEFF */
58             #define UTF32BOM_BE "\000\000\376\377" /* 00 00 FE FF */
59              
60             /* mingw with USE_LONG_DOUBLE (and implied USE_MINGW_ANSI_STDIO) do use the
61             non-msvcrt inf/nan stringification in sprintf(). */
62             #if defined(WIN32) && !defined(__USE_MINGW_ANSI_STDIO) && !defined(USE_LONG_DOUBLE)
63             /* new ucrtd.dll runtime? We do not probe the runtime or variants in the Makefile.PL yet. */
64             #define STR_INF "inf"
65             #define STR_INF2 "inf.0"
66             #define STR_NAN "nan"
67             #define STR_QNAN "nan(ind)"
68             /* old standard msvcrt.dll */
69             #define STR_INF3 "1.#INF"
70             #define STR_INF4 "1.#INF.0"
71             #define STR_NAN2 "1.#IND"
72             #define STR_QNAN2 "1.#QNAN"
73             #define HAVE_QNAN
74             #elif defined(sun) || defined(__sun)
75             #define STR_INF "Infinity"
76             #define STR_NAN "NaN"
77             #elif defined(__hpux)
78             #define STR_INF "++"
79             #define STR_NAN "-?"
80             #define HAVE_NEG_NAN
81             #define STR_NEG_INF "---"
82             #define STR_NEG_NAN "?"
83             #else
84             #define STR_INF "inf"
85             #define STR_NAN "nan"
86             #endif
87              
88             /* NV_INF compatibility for Perl 5.6 */
89             #if !defined(NV_INF) && defined(USE_LONG_DOUBLE) && defined(LDBL_INFINITY)
90             # define NV_INF LDBL_INFINITY
91             #endif
92             #if !defined(NV_INF) && defined(DBL_INFINITY)
93             # define NV_INF (NV)DBL_INFINITY
94             #endif
95             #if !defined(NV_INF) && defined(INFINITY)
96             # define NV_INF (NV)INFINITY
97             #endif
98             #if !defined(NV_INF) && defined(INF)
99             # define NV_INF (NV)INF
100             #endif
101             #if !defined(NV_INF) && defined(USE_LONG_DOUBLE) && defined(HUGE_VALL)
102             # define NV_INF (NV)HUGE_VALL
103             #endif
104             #if !defined(NV_INF) && defined(HUGE_VAL)
105             # define NV_INF (NV)HUGE_VAL
106             #endif
107              
108             /* NV_NAN compatibility for Perl 5.6 */
109             #if !defined(NV_NAN) && defined(USE_LONG_DOUBLE)
110             # if !defined(NV_NAN) && defined(LDBL_NAN)
111             # define NV_NAN LDBL_NAN
112             # endif
113             # if !defined(NV_NAN) && defined(LDBL_QNAN)
114             # define NV_NAN LDBL_QNAN
115             # endif
116             # if !defined(NV_NAN) && defined(LDBL_SNAN)
117             # define NV_NAN LDBL_SNAN
118             # endif
119             #endif
120             #if !defined(NV_NAN) && defined(DBL_NAN)
121             # define NV_NAN (NV)DBL_NAN
122             #endif
123             #if !defined(NV_NAN) && defined(DBL_QNAN)
124             # define NV_NAN (NV)DBL_QNAN
125             #endif
126             #if !defined(NV_NAN) && defined(DBL_SNAN)
127             # define NV_NAN (NV)DBL_SNAN
128             #endif
129             #if !defined(NV_NAN) && defined(QNAN)
130             # define NV_NAN (NV)QNAN
131             #endif
132             #if !defined(NV_NAN) && defined(SNAN)
133             # define NV_NAN (NV)SNAN
134             #endif
135             #if !defined(NV_NAN) && defined(NAN)
136             # define NV_NAN (NV)NAN
137             #endif
138              
139             /* modfl() segfaults for -Duselongdouble && 64-bit mingw64 && mingw
140             runtime version 4.0 [perl #125924] */
141             #if defined(USE_LONG_DOUBLE) && defined(__MINGW64__) \
142             && __MINGW64_VERSION_MAJOR == 4 && __MINGW64_VERSION_MINOR == 0
143             #undef HAS_MODFL
144             #undef Perl_modf
145             #define Perl_modf(nv, ip) mingw_modfl(nv, ip)
146             long double
147             mingw_modfl(long double x, long double *ip)
148             {
149             *ip = truncl(x);
150             return (x == *ip ? copysignl(0.0L, x) : x - *ip);
151             }
152             #endif
153              
154             #if defined(_AIX)
155             #define HAVE_QNAN
156             #undef STR_QNAN
157             #define STR_QNAN "NANQ"
158             #endif
159              
160             /* some old perls do not have this, try to make it work, no */
161             /* guarantees, though. if it breaks, you get to keep the pieces. */
162             #ifndef UTF8_MAXBYTES
163             # define UTF8_MAXBYTES 13
164             #endif
165              
166             /* 5.6: */
167             #ifndef IS_NUMBER_IN_UV
168             #define IS_NUMBER_IN_UV 0x01 /* number within UV range (maybe not
169             int). value returned in pointed-
170             to UV */
171             #define IS_NUMBER_GREATER_THAN_UV_MAX 0x02 /* pointed to UV undefined */
172             #define IS_NUMBER_NOT_INT 0x04 /* saw . or E notation */
173             #define IS_NUMBER_NEG 0x08 /* leading minus sign */
174             #define IS_NUMBER_INFINITY 0x10 /* this is big */
175             #define IS_NUMBER_NAN 0x20 /* this is not */
176             #endif
177             #ifndef UNI_DISPLAY_QQ
178             #define UNI_DISPLAY_ISPRINT 0x0001
179             #define UNI_DISPLAY_BACKSLASH 0x0002
180             #define UNI_DISPLAY_QQ (UNI_DISPLAY_ISPRINT|UNI_DISPLAY_BACKSLASH)
181             #define UNI_DISPLAY_REGEX (UNI_DISPLAY_ISPRINT|UNI_DISPLAY_BACKSLASH)
182             #endif
183             /* with 5.6 hek can only be non-utf8 */
184             #ifndef HeKUTF8
185             #define HeKUTF8(he) 0
186             #endif
187             #ifndef GV_NOADD_NOINIT
188             #define GV_NOADD_NOINIT 0
189             #endif
190             /* since 5.8.1 */
191             #ifndef SvIsCOW_shared_hash
192             #define SvIsCOW_shared_hash(pv) 0
193             #endif
194             /* 5.8.1 has a broken assert_not_ROK */
195             #if PERL_VERSION == 8 && PERL_SUBVERSION == 1
196             # undef assert_not_ROK
197             # if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
198             # define assert_not_ROK(sv) ({assert(!SvROK(sv) || !SvRV(sv));}),
199             # else
200             # define assert_not_ROK(sv)
201             # endif
202             #endif
203             /* compatibility with perl <5.14 */
204             #ifndef SvTRUE_nomg
205             #define SvTRUE_nomg SvTRUE
206             #endif
207             #ifndef SvNV_nomg
208             #define SvNV_nomg SvNV
209             #endif
210             #ifndef PERL_UNICODE_MAX
211             #define PERL_UNICODE_MAX 0x10FFFF
212             #endif
213             #ifndef HvNAMELEN_get
214             # define HvNAMELEN_get(hv) strlen (HvNAME (hv))
215             #endif
216             #ifndef HvNAMELEN
217             # define HvNAMELEN(hv) HvNAMELEN_get (hv)
218             #endif
219             #ifndef HvNAMEUTF8
220             # define HvNAMEUTF8(hv) 0
221             #endif
222             /* since 5.14 check use warnings 'nonchar' */
223             #ifdef WARN_NONCHAR
224             #define WARNER_NONCHAR(hi) \
225             Perl_ck_warner_d(aTHX_ packWARN(WARN_NONCHAR), \
226             "Unicode non-character U+%04" UVXf " is not " \
227             "recommended for open interchange", hi)
228             /* before check use warnings 'utf8' */
229             #elif PERL_VERSION > 10
230             #define WARNER_NONCHAR(hi) \
231             Perl_ck_warner_d(aTHX_ packWARN(WARN_UTF8), \
232             "Unicode non-character U+%04" UVXf " is illegal " \
233             "for interchange", hi)
234             #else
235             #define WARNER_NONCHAR(hi) \
236             Perl_warner(aTHX_ packWARN(WARN_UTF8), \
237             "Unicode non-character U+%04lX is illegal", (unsigned long)hi)
238             #endif
239              
240             /* since 5.16 */
241             #ifndef GV_NO_SVGMAGIC
242             #define GV_NO_SVGMAGIC 0
243             #endif
244             /* since 5.18 */
245             #ifndef SvREFCNT_dec_NN
246             #define SvREFCNT_dec_NN(sv) SvREFCNT_dec(sv)
247             #endif
248             /* from cperl */
249             #ifndef strEQc
250             /* the buffer ends with \0, includes comparison of the \0.
251             better than strEQ as it uses memcmp, word-wise comparison. */
252             # define strEQc(s, c) memEQ(s, ("" c ""), sizeof(c))
253             #endif
254             #ifndef memEQc
255             /* excluding the final \0, so the string s may continue */
256             # define memEQc(s, c) memEQ(s, ("" c ""), sizeof(c)-1)
257             #endif
258             #ifndef He_IS_SVKEY
259             # define He_IS_SVKEY(he) HeKLEN (he) == HEf_SVKEY
260             #endif
261              
262             /* av_len has 2 different possible types */
263             #ifndef HVMAX_T
264             # if PERL_VERSION >= 20
265             # define HVMAX_T SSize_t
266             # else
267             # define HVMAX_T I32
268             # endif
269             #endif
270             /* and riter 3 */
271             #ifndef RITER_T
272             # ifdef USE_CPERL
273             # if PERL_VERSION >= 25
274             # define RITER_T U32
275             # else
276             # define RITER_T SSize_t
277             # endif
278             # else
279             # define RITER_T I32
280             # endif
281             #endif
282              
283             /* types */
284             #define JSON_TYPE_SCALAR 0x0000
285             #define JSON_TYPE_BOOL 0x0001
286             #define JSON_TYPE_INT 0x0002
287             #define JSON_TYPE_FLOAT 0x0003
288             #define JSON_TYPE_STRING 0x0004
289              
290             /* flags */
291             #define JSON_TYPE_CAN_BE_NULL 0x0100
292              
293             /* null type */
294             #define JSON_TYPE_NULL JSON_TYPE_CAN_BE_NULL
295              
296             /* classes */
297             #define JSON_TYPE_CLASS "Cpanel::JSON::XS::Type"
298             #define JSON_TYPE_ARRAYOF_CLASS "Cpanel::JSON::XS::Type::ArrayOf"
299             #define JSON_TYPE_HASHOF_CLASS "Cpanel::JSON::XS::Type::HashOf"
300             #define JSON_TYPE_ANYOF_CLASS "Cpanel::JSON::XS::Type::AnyOf"
301              
302             #define JSON_TYPE_ANYOF_SCALAR_INDEX 0
303             #define JSON_TYPE_ANYOF_ARRAY_INDEX 1
304             #define JSON_TYPE_ANYOF_HASH_INDEX 2
305              
306             /* three extra for rounding, sign, and end of string */
307             #define IVUV_MAXCHARS (sizeof (UV) * CHAR_BIT * 28 / 93 + 3)
308              
309             #define F_ASCII 0x00000001UL
310             #define F_LATIN1 0x00000002UL
311             #define F_UTF8 0x00000004UL
312             #define F_INDENT 0x00000008UL
313             #define F_CANONICAL 0x00000010UL
314             #define F_SPACE_BEFORE 0x00000020UL
315             #define F_SPACE_AFTER 0x00000040UL
316             #define F_ALLOW_NONREF 0x00000100UL
317             #define F_SHRINK 0x00000200UL
318             #define F_ALLOW_BLESSED 0x00000400UL
319             #define F_CONV_BLESSED 0x00000800UL
320             #define F_RELAXED 0x00001000UL
321             #define F_ALLOW_UNKNOWN 0x00002000UL
322             #define F_ALLOW_TAGS 0x00004000UL
323             #define F_BINARY 0x00008000UL
324             #define F_ALLOW_BAREKEY 0x00010000UL
325             #define F_ALLOW_SQUOTE 0x00020000UL
326             #define F_ALLOW_BIGNUM 0x00040000UL
327             #define F_ESCAPE_SLASH 0x00080000UL
328             #define F_SORT_BY 0x00100000UL
329             #define F_ALLOW_STRINGIFY 0x00200000UL
330             #define F_UNBLESSED_BOOL 0x00400000UL
331             #define F_ALLOW_DUPKEYS 0x00800000UL
332             #define F_REQUIRE_TYPES 0x01000000UL
333             #define F_TYPE_ALL_STRING 0x02000000UL
334             #define F_HOOK 0x80000000UL /* some hooks exist, so slow-path processing */
335              
336             #define F_PRETTY F_INDENT | F_SPACE_BEFORE | F_SPACE_AFTER
337             #define SET_RELAXED (F_RELAXED | F_ALLOW_BAREKEY | F_ALLOW_SQUOTE | F_ALLOW_DUPKEYS)
338              
339             #define INIT_SIZE 32 /* initial scalar size to be allocated */
340             #define INDENT_STEP 3 /* default spaces per indentation level */
341              
342             #define SHORT_STRING_LEN 16384 /* special-case strings of up to this size */
343              
344             #define DECODE_WANTS_OCTETS(json) ((json)->flags & F_UTF8)
345              
346             #define SB do {
347             #define SE } while (0)
348              
349             #if __GNUC__ >= 3
350             # define _expect(expr,value) __builtin_expect ((expr), (value))
351             # define INLINE static inline
352             #else
353             # define _expect(expr,value) (expr)
354             # define INLINE static
355             #endif
356             #ifndef LIKELY
357             #define LIKELY(expr) _expect ((long)(expr) != 0, 1)
358             #define UNLIKELY(expr) _expect ((long)(expr) != 0, 0)
359             #endif
360              
361             #define IN_RANGE_INC(type,val,beg,end) \
362             ((unsigned type)((unsigned type)(val) - (unsigned type)(beg)) \
363             <= (unsigned type)((unsigned type)(end) - (unsigned type)(beg)))
364              
365             #define ERR_NESTING_EXCEEDED "json text or perl structure exceeds maximum nesting level (max_depth set too low?)"
366              
367             # define JSON_STASH MY_CXT.json_stash
368              
369             #define MY_CXT_KEY "Cpanel::JSON::XS::_guts"
370              
371             typedef struct {
372             HV *json_stash; /* Cpanel::JSON::XS:: */
373             HV *json_boolean_stash; /* JSON::PP::Boolean:: */
374             HV *jsonold_boolean_stash; /* JSON::XS::Boolean:: if empty will be (HV*)1 */
375             HV *mojo_boolean_stash; /* Mojo::JSON::_Bool:: if empty will be (HV*)1 */
376             SV *json_true, *json_false;
377             SV *sv_json;
378             } my_cxt_t;
379              
380             /* the amount of HEs to allocate on the stack, when sorting keys */
381             #define STACK_HES 64
382              
383             START_MY_CXT
384              
385             INLINE SV * get_bool (pTHX_ const char *name);
386              
387             enum {
388             INCR_M_WS = 0, /* initial whitespace skipping, must be 0 */
389             INCR_M_STR, /* inside string */
390             INCR_M_BS, /* inside backslash */
391             INCR_M_C0, /* inside comment in initial whitespace sequence */
392             INCR_M_C1, /* inside comment in other places */
393             INCR_M_JSON /* outside anything, count nesting */
394             };
395              
396             #define INCR_DONE(json) ((json)->incr_nest <= 0 && (json)->incr_mode == INCR_M_JSON)
397              
398             typedef struct {
399             U32 flags;
400             U32 max_depth;
401             U32 indent_length; /* how much padding to use when indenting */
402             STRLEN max_size;
403              
404             SV *cb_object;
405             HV *cb_sk_object;
406             SV *cb_sort_by;
407              
408             /* for the incremental parser */
409             SV *incr_text; /* the source text so far */
410             STRLEN incr_pos; /* the current offset into the text */
411             int incr_nest; /* {[]}-nesting level */
412             unsigned char incr_mode;
413             unsigned char infnan_mode;
414             } JSON;
415              
416             INLINE void
417 647           json_init (JSON *json)
418             {
419 647           Zero (json, 1, JSON);
420 647           json->max_depth = 512;
421 647           json->indent_length = INDENT_STEP;
422 647           }
423              
424             /* dTHX/threads TODO*/
425             /* END dtor call not needed, all of these *s refcnts are owned by the stash
426             treem not C code */
427             static void
428 58           init_MY_CXT(pTHX_ my_cxt_t * cxt)
429             {
430 58           cxt->json_stash = gv_stashpvn ("Cpanel::JSON::XS", sizeof("Cpanel::JSON::XS")-1, 1);
431 58           cxt->json_boolean_stash = gv_stashpvn ("JSON::PP::Boolean", sizeof("JSON::PP::Boolean")-1, 1);
432 58           cxt->jsonold_boolean_stash = gv_stashpvn ("JSON::XS::Boolean", sizeof("JSON::XS::Boolean")-1, 0);
433 58           cxt->mojo_boolean_stash = gv_stashpvn ("Mojo::JSON::_Bool", sizeof("Mojo::JSON::_Bool")-1, 0);
434 58 50         if ( !cxt->mojo_boolean_stash )
435 58           cxt->mojo_boolean_stash = (HV*)1; /* invalid ptr to compare against, better than a NULL stash */
436 58 50         if ( !cxt->jsonold_boolean_stash )
437 58           cxt->jsonold_boolean_stash = (HV*)1;
438              
439 58           cxt->json_true = get_bool (aTHX_ "Cpanel::JSON::XS::true");
440 58           cxt->json_false = get_bool (aTHX_ "Cpanel::JSON::XS::false");
441              
442 58           cxt->sv_json = newSVpv ("JSON", 0);
443 58           SvREADONLY_on (cxt->sv_json);
444 58           }
445              
446              
447             /*/////////////////////////////////////////////////////////////////////////// */
448             /* utility functions */
449              
450             /* Unpacks the 2 boolean objects from the global references */
451             INLINE SV *
452 116           get_bool (pTHX_ const char *name)
453             {
454             dMY_CXT;
455             #if PERL_VERSION > 7
456 116           SV *sv = get_sv (name, 1);
457             #else
458             SV *sv = GvSV(gv_fetchpv(name, 1, SVt_PV));
459             #endif
460 116           SV* rv = SvRV(sv);
461 116 50         if (!SvOBJECT(sv) || !SvSTASH(sv)) {
    0          
462 116           SvREADONLY_off (sv);
463 116           SvREADONLY_off (rv);
464 116           (void)sv_bless(sv, MY_CXT.json_boolean_stash); /* bless the ref */
465             }
466 116           SvREADONLY_on (rv);
467 116           SvREADONLY_on (sv);
468 116           return sv;
469             }
470              
471             INLINE void
472 200           shrink (pTHX_ SV *sv)
473             {
474             /* ignore errors */
475 200           (void)sv_utf8_downgrade (sv, 1);
476              
477 200 50         if (SvLEN (sv) > SvCUR (sv) + 1)
478             {
479             #ifdef SvPV_shrink_to_cur
480 200           SvPV_shrink_to_cur (sv);
481             #elif defined (SvPV_renew)
482             SvPV_renew (sv, SvCUR (sv) + 1);
483             #endif
484             }
485 200           }
486              
487             /* decode an utf-8 character and return it, or (UV)-1 in */
488             /* case of an error. */
489             /* we special-case "safe" characters from U+80 .. U+7FF, */
490             /* but use the very good perl function to parse anything else. */
491             /* note that we never call this function for a ascii codepoints */
492             INLINE UV
493 2791           decode_utf8 (pTHX_ unsigned char *s, STRLEN len, int relaxed, STRLEN *clen)
494             {
495 2791 50         if (LIKELY(len >= 2
    100          
    100          
    100          
496             && IN_RANGE_INC (char, s[0], 0xc2, 0xdf)
497             && IN_RANGE_INC (char, s[1], 0x80, 0xbf)))
498             {
499 1306           *clen = 2;
500 1306           return ((s[0] & 0x1f) << 6) | (s[1] & 0x3f);
501             }
502             else {
503             /* Since perl 5.14 we can disallow illegal unicode above U+10FFFF.
504             Before we could only warn with warnings 'utf8'.
505             We accept only valid unicode, unless we are in the relaxed mode. */
506             #if PERL_VERSION > 12
507 1485 100         UV c = utf8n_to_uvuni (s, len, clen,
508             UTF8_CHECK_ONLY | (relaxed ? 0 : UTF8_DISALLOW_SUPER));
509             #elif PERL_VERSION >= 8
510             UV c = utf8n_to_uvuni (s, len, clen, UTF8_CHECK_ONLY);
511             #endif
512             #if PERL_VERSION >= 8 && PERL_VERSION <= 12
513             if (c > PERL_UNICODE_MAX && !relaxed)
514             *clen = -1;
515             #endif
516             #if PERL_VERSION >= 8
517 1485           return c;
518             #else
519             /* 5.6 does not detect certain ill-formed sequences, esp. overflows,
520             which are security relevant. so we add code to detect these. */
521             UV c = utf8_to_uv(s, len, clen, UTF8_CHECK_ONLY);
522             if (!relaxed) {
523             if (!c || c > PERL_UNICODE_MAX)
524             *clen = -1;
525             /* need to check manually for some overflows. 5.6 unicode bug */
526             else if (len >= 2
527             && IN_RANGE_INC (char, s[0], 0xc0, 0xfe)
528             && !IN_RANGE_INC (char, s[0], 0xc2, 0xdf)) {
529             U8 *s0, *send;
530             UV uv = *s;
531             UV expectlen = UTF8SKIP(s);
532              
533             #define UTF_CONTINUATION_MASK ((U8) ((1U << 6) - 1))
534             #define UTF_ACCUMULATION_OVERFLOW_MASK \
535             (((UV) UTF_CONTINUATION_MASK) << ((sizeof(UV) * 8) - 6))
536              
537             s0 = s;
538             /*printf ("maybe overlong <%.*s> %d/%d %x %x\n", len, s, c,
539             *clen, s[0], s[1]);*/
540             if (*clen > 4) {
541             *clen = -1;
542             return c;
543             }
544             send = (U8*) s0 + ((expectlen <= len) ? len : len);
545             for (s = s0 + 1; s < send; s++) {
546             if (LIKELY(UTF8_IS_CONTINUATION(*s))) {
547             if (uv & UTF_ACCUMULATION_OVERFLOW_MASK) {
548             /*printf ("overflow\n");*/
549             *clen = -1;
550             return c;
551             }
552             uv = UTF8_ACCUMULATE(uv, *s);
553             }
554             else {
555             /*printf ("unexpected non continuation\n");*/
556             *clen = -1;
557             return c;
558             }
559             }
560             }
561             }
562             return c;
563             #endif
564             }
565             }
566              
567             /* Likewise for encoding, also never called for ascii codepoints. */
568             /* This function takes advantage of this fact, although current gcc's */
569             /* seem to optimise the check for >= 0x80 away anyways. */
570             INLINE unsigned char *
571 1335           encode_utf8 (unsigned char *s, UV ch)
572             {
573 1335 50         if (UNLIKELY(ch < 0x000080))
574 0           *s++ = ch;
575 1335 100         else if (LIKELY(ch < 0x000800))
576 736           *s++ = 0xc0 | ( ch >> 6),
577 736           *s++ = 0x80 | ( ch & 0x3f);
578 599 100         else if (ch < 0x010000)
579 267           *s++ = 0xe0 | ( ch >> 12),
580 267           *s++ = 0x80 | ((ch >> 6) & 0x3f),
581 267           *s++ = 0x80 | ( ch & 0x3f);
582 332 50         else if (ch < 0x110000)
583 332           *s++ = 0xf0 | ( ch >> 18),
584 332           *s++ = 0x80 | ((ch >> 12) & 0x3f),
585 332           *s++ = 0x80 | ((ch >> 6) & 0x3f),
586 332           *s++ = 0x80 | ( ch & 0x3f);
587              
588 1335           return s;
589             }
590              
591             /* convert offset to character index, sv must be string */
592             static STRLEN
593 353           ptr_to_index (pTHX_ SV *sv, const STRLEN offset)
594             {
595 353           return SvUTF8 (sv)
596 50           ? (STRLEN)utf8_distance ((U8*)(SvPVX(sv)+offset), (U8*)SvPVX (sv))
597 403 100         : offset;
598             }
599              
600             /*/////////////////////////////////////////////////////////////////////////// */
601             /* fp hell */
602              
603             #ifdef HAVE_NO_POWL
604             /* Ulisse Monari: this is a patch for AIX 5.3, perl 5.8.8 without HAS_LONG_DOUBLE
605             There Perl_pow maps to pow(...) - NOT TO powl(...), core dumps at Perl_pow(...)
606              
607             Base code is from http://bytes.com/topic/c/answers/748317-replacement-pow-function
608             This is my change to fs_pow that goes into libc/libm for calling fmod/exp/log.
609             NEED TO MODIFY Makefile, after perl Makefile.PL by adding "-lm" onto the LDDLFLAGS line */
610             static double fs_powEx(double x, double y)
611             {
612             double p = 0;
613              
614             if (0 > x && fmod(y, 1) == 0) {
615             if (fmod(y, 2) == 0) {
616             p = exp(log(-x) * y);
617             } else {
618             p = -exp(log(-x) * y);
619             }
620             } else {
621             if (x != 0 || 0 >= y) {
622             p = exp(log( x) * y);
623             }
624             }
625             return p;
626             }
627             #endif
628              
629             #ifndef Perl_strtod
630             /* scan a group of digits, and a trailing exponent */
631             static void
632             json_atof_scan1 (const char *s, NV *accum, int *expo, int postdp, int maxdepth)
633             {
634             UV uaccum = 0;
635             int eaccum = 0;
636              
637             #if defined(HAVE_BAD_POWL)
638             *accum = strtold(s, NULL);
639             #else
640             /* if we recurse too deep, skip all remaining digits */
641             /* to avoid a stack overflow attack */
642             if (UNLIKELY(--maxdepth <= 0))
643             while (((U8)*s - '0') < 10)
644             ++s;
645              
646             for (;;)
647             {
648             U8 dig = (U8)*s - '0';
649              
650             if (UNLIKELY(dig >= 10))
651             {
652             if (dig == (U8)((U8)'.' - (U8)'0'))
653             {
654             ++s;
655             json_atof_scan1 (s, accum, expo, 1, maxdepth);
656             }
657             else if ((dig | ' ') == 'e' - '0')
658             {
659             int exp2 = 0;
660             int neg = 0;
661              
662             ++s;
663              
664             if (*s == '-')
665             {
666             ++s;
667             neg = 1;
668             }
669             else if (*s == '+')
670             ++s;
671              
672             while ((dig = (U8)*s - '0') < 10)
673             exp2 = exp2 * 10 + *s++ - '0';
674              
675             *expo += neg ? -exp2 : exp2;
676             }
677              
678             break;
679             }
680              
681             ++s;
682              
683             uaccum = uaccum * 10 + dig;
684             ++eaccum;
685              
686             /* if we have too many digits, then recurse for more */
687             /* we actually do this for rather few digits */
688             if (uaccum >= (UV_MAX - 9) / 10)
689             {
690             if (postdp) *expo -= eaccum;
691             json_atof_scan1 (s, accum, expo, postdp, maxdepth);
692             if (postdp) *expo += eaccum;
693              
694             break;
695             }
696             }
697              
698             /* This relies greatly on the quality of the pow () */
699             /* implementation of the platform, but a good */
700             /* implementation is hard to beat. */
701             /* (IEEE 754 conformant ones are required to be exact) */
702             if (postdp) *expo -= eaccum;
703             #ifdef HAVE_NO_POWL
704             /* powf() unfortunately is not accurate enough */
705             *accum += uaccum * fs_powEx(10., *expo );
706             #else
707             *accum += uaccum * Perl_pow (10., *expo);
708             #endif
709             *expo += eaccum;
710             #endif
711             }
712             #endif
713              
714             static NV
715 79           json_atof (const char *s)
716             {
717 79           NV accum = 0.;
718             #ifndef Perl_strtod
719             int expo = 0;
720             #endif
721 79           int neg = 0;
722              
723 79 100         if (*s == '-')
724             {
725 17           ++s;
726 17           neg = 1;
727             }
728              
729             /* Fix accuracy mismatches compared to perl (using strtod).
730             Available since v5.21.4, but see perl5 af5a4640bf25a62438c05f73a87c1d6be6096b02.
731             Resets LC_NUMERIC only since v5.29.10. (dot, not comma)
732             See GH #154, where the pow method may return a different result than strtod.
733             */
734             #ifdef Perl_strtod
735 79           accum = Perl_strtod (s, NULL);
736             #else
737             /* a recursion depth of ten gives us >>500 bits */
738             json_atof_scan1 (s, &accum, &expo, 0, 10);
739             #endif
740              
741 79 100         return neg ? -accum : accum;
742             }
743              
744             INLINE int
745 65           is_bignum_obj (pTHX_ SV *sv)
746             {
747 65           HV *stash = SvSTASH (sv);
748 65 100         return (stash == gv_stashpvs ("Math::BigInt", 0) || stash == gv_stashpvs ("Math::BigFloat", 0)) ? 1 : 0;
    100          
749             }
750              
751             INLINE int
752 129           is_bool_obj (pTHX_ SV *sv)
753             {
754             dMY_CXT;
755              
756 129           HV *bstash = MY_CXT.json_boolean_stash; /* JSON-XS-3.x interop (Types::Serialiser/JSON::PP::Boolean) */
757 129           HV *oldstash = MY_CXT.jsonold_boolean_stash; /* JSON-XS-2.x interop (JSON::XS::Boolean) */
758 129           HV *mstash = MY_CXT.mojo_boolean_stash; /* Mojo::JSON::_Bool interop */
759 129           HV *stash = SvSTASH (sv);
760              
761 129 100         return (stash == bstash || stash == mstash || stash == oldstash) ? 1 : 0;
    50          
    50          
762             }
763              
764             /* target of scalar reference is bool? -1 == nope, 0 == false, 1 == true */
765             static int
766 1846           ref_bool_type (pTHX_ SV *sv)
767             {
768 1846           svtype svt = SvTYPE (sv);
769              
770 1846 100         if (svt < SVt_PVAV)
771             {
772 27           STRLEN len = 0;
773 27 100         char *pv = svt ? SvPV_nomg (sv, len) : 0;
    100          
774              
775 27 100         if (len == 1) {
776 9 100         if (*pv == '1')
777 8           return 1;
778 4 100         else if (*pv == '0')
779 22           return 0;
780             }
781              
782             }
783              
784 1838           return -1;
785             }
786              
787             /* returns whether scalar is not a reference in the sense of allow_nonref */
788             static int
789 1840           json_nonref (pTHX_ SV *scalar)
790             {
791 1840 100         if (!SvROK (scalar))
792 7           return 1;
793              
794 1833           scalar = SvRV (scalar);
795              
796 1833 100         if (!SvOBJECT (scalar) && ref_bool_type (aTHX_ scalar) >= 0)
    50          
797 0           return 1;
798              
799 1833 100         if (SvOBJECT (scalar) && is_bool_obj (aTHX_ scalar))
    100          
800 2           return 1;
801            
802 1831           return 0;
803             }
804              
805             /*/////////////////////////////////////////////////////////////////////////// */
806             /* encoder */
807              
808             /* structure used for encoding JSON */
809             typedef struct
810             {
811             char *cur; /* SvPVX (sv) + current output position */
812             char *end; /* SvEND (sv) */
813             SV *sv; /* result scalar */
814             JSON json;
815             U32 indent; /* indentation level */
816             UV limit; /* escape character values >= this value when encoding */
817             } enc_t;
818              
819             INLINE void
820 60668           need (pTHX_ enc_t *enc, STRLEN len)
821             {
822             #if PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION >= 1)
823             DEBUG_v(Perl_deb(aTHX_ "need enc: %p %p %4ld, want: %lu\n", enc->cur, enc->end,
824             (long)(enc->end - enc->cur), (unsigned long)len));
825             #endif
826             assert(enc->cur <= enc->end);
827 60668 100         if (UNLIKELY(enc->cur + len >= enc->end))
828             {
829 3174           STRLEN cur = enc->cur - (char *)SvPVX (enc->sv);
830 3174 50         SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1);
    100          
831 3174           enc->cur = SvPVX (enc->sv) + cur;
832 3174           enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1;
833             }
834 60668           }
835              
836             INLINE void
837 9108           encode_ch (pTHX_ enc_t *enc, char ch)
838             {
839 9108           need (aTHX_ enc, 1);
840 9108           *enc->cur++ = ch;
841 9108           }
842              
843             static void
844 2349           encode_str (pTHX_ enc_t *enc, char *str, STRLEN len, int is_utf8)
845             {
846 2349           char *end = str + len;
847              
848             #if PERL_VERSION < 8
849             /* perl5.6 encodes to utf8 automatically, reverse it */
850             if (is_utf8 && (enc->json.flags & F_BINARY))
851             {
852             str = (char *)utf8_to_bytes((U8*)str, &len);
853             if (!str)
854             croak ("illegal unicode character in binary string", str);
855             end = str + len;
856             }
857             #endif
858 2349           need (aTHX_ enc, len);
859              
860 50355 100         while (str < end)
861             {
862 48006           unsigned char ch = *(unsigned char *)str;
863             #if PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION >= 1)
864             DEBUG_v(Perl_deb(aTHX_ "str enc: %p %p %4ld, want: %lu\n", enc->cur, enc->end,
865             (long)(enc->end - enc->cur), (long unsigned)len));
866             #endif
867 48006 100         if (LIKELY(ch >= 0x20 && ch < 0x80)) /* most common case */
    100          
868             {
869             assert(enc->cur <= enc->end);
870 39756 100         if (UNLIKELY(ch == '"')) /* but with slow exceptions */
871             {
872 225           need (aTHX_ enc, 2);
873 225           *enc->cur++ = '\\';
874 225           *enc->cur++ = '"';
875 225           ++len;
876             }
877 39531 100         else if (UNLIKELY(ch == '\\'))
878             {
879 414           need (aTHX_ enc, 2);
880 414           *enc->cur++ = '\\';
881 414           *enc->cur++ = '\\';
882 414           ++len;
883             }
884 39117 100         else if (UNLIKELY(ch == '/' && (enc->json.flags & F_ESCAPE_SLASH)))
    100          
885             {
886 1           need (aTHX_ enc, 2);
887 1           *enc->cur++ = '\\';
888 1           *enc->cur++ = '/';
889 1           ++len;
890             }
891             else {
892 39116           need (aTHX_ enc, 1);
893 39116           *enc->cur++ = ch;
894             }
895              
896 39756           ++str;
897             }
898             else
899             {
900             assert(enc->cur <= enc->end);
901 8250           switch (ch)
902             {
903 81           case '\010': need (aTHX_ enc, 2);
904 81           *enc->cur++ = '\\'; *enc->cur++ = 'b'; ++len; ++str; break;
905 79           case '\011': need (aTHX_ enc, 2);
906 79           *enc->cur++ = '\\'; *enc->cur++ = 't'; ++len; ++str; break;
907 274           case '\012': need (aTHX_ enc, 2);
908 274           *enc->cur++ = '\\'; *enc->cur++ = 'n'; ++len; ++str; break;
909 65           case '\014': need (aTHX_ enc, 2);
910 65           *enc->cur++ = '\\'; *enc->cur++ = 'f'; ++len; ++str; break;
911 61           case '\015': need (aTHX_ enc, 2);
912 61           *enc->cur++ = '\\'; *enc->cur++ = 'r'; ++len; ++str; break;
913              
914             default:
915             {
916             STRLEN clen;
917             UV uch;
918              
919 7690 100         if (is_utf8 && !(enc->json.flags & F_BINARY))
    100          
920             {
921 1620           uch = decode_utf8 (aTHX_ (unsigned char *)str, end - str,
922 1620           enc->json.flags & F_RELAXED, &clen);
923 1620 50         if (clen == (STRLEN)-1)
924 0           croak ("malformed or illegal unicode character in string [%.11s], cannot convert to JSON", str);
925             }
926             else
927             {
928 6070           uch = ch;
929 6070           clen = 1;
930             }
931              
932 7690 100         if (uch < 0x80/*0x20*/ || uch >= enc->limit)
    100          
933             {
934 6525 100         if (enc->json.flags & F_BINARY)
935             {
936             /* MB cannot arrive here */
937 5015           need (aTHX_ enc, 4);
938 5015           *enc->cur++ = '\\';
939 5015           *enc->cur++ = 'x';
940 5015           *enc->cur++ = PL_hexdigit [(uch >> 4) & 15];
941 5015           *enc->cur++ = PL_hexdigit [ uch & 15];
942 5015           len += 3;
943             }
944 1510 100         else if (uch >= 0x10000UL)
945             {
946 320 50         if (uch >= 0x110000UL)
947 0           croak ("out of range codepoint (0x%lx) encountered, unrepresentable in JSON", (unsigned long)uch);
948              
949 320           need (aTHX_ enc, 12);
950 640           sprintf (enc->cur, "\\u%04x\\u%04x",
951 320           (int)((uch - 0x10000) / 0x400 + 0xD800),
952             (int)((uch - 0x10000) % 0x400 + 0xDC00));
953 320           enc->cur += 12;
954 320           len += 11;
955             }
956             else
957             {
958 1190           need (aTHX_ enc, 6);
959 1190           *enc->cur++ = '\\';
960 1190           *enc->cur++ = 'u';
961 1190           *enc->cur++ = PL_hexdigit [ uch >> 12 ];
962 1190           *enc->cur++ = PL_hexdigit [(uch >> 8) & 15];
963 1190           *enc->cur++ = PL_hexdigit [(uch >> 4) & 15];
964 1190           *enc->cur++ = PL_hexdigit [ uch & 15];
965 1190           len += 5;
966             }
967              
968 6525           str += clen;
969             }
970 1165 100         else if (enc->json.flags & F_LATIN1)
971             {
972 8           need (aTHX_ enc, 1);
973 8           *enc->cur++ = uch;
974 8           str += clen;
975             }
976 1157 50         else if (enc->json.flags & F_BINARY)
977             {
978 0           need (aTHX_ enc, 1);
979 0           *enc->cur++ = uch;
980 0           str += clen;
981             }
982 1157 100         else if (is_utf8)
983             {
984 915           need (aTHX_ enc, clen);
985 915           len += clen;
986             do
987             {
988 2766           *enc->cur++ = *str++;
989             }
990 2766 100         while (--clen);
991             }
992             else
993             { /* never more than 11 bytes needed */
994 242           need (aTHX_ enc, UTF8_MAXBYTES);
995 242           enc->cur = (char*)encode_utf8 ((U8*)enc->cur, uch);
996 242           ++str;
997 7690           len += UTF8_MAXBYTES - 1;
998             }
999             }
1000             }
1001             }
1002              
1003 48006           --len;
1004             }
1005 2349           }
1006              
1007             INLINE void
1008 217           encode_const_str (pTHX_ enc_t *enc, const char *str, STRLEN len, int is_utf8)
1009             {
1010 217           encode_str (aTHX_ enc, (char *)str, len, is_utf8);
1011 217           }
1012              
1013             INLINE void
1014 3730           encode_indent (pTHX_ enc_t *enc)
1015             {
1016 3730 100         if (enc->json.flags & F_INDENT)
1017             {
1018 32           int spaces = enc->indent * enc->json.indent_length;
1019              
1020 32           need (aTHX_ enc, spaces);
1021 32           memset (enc->cur, ' ', spaces);
1022 32           enc->cur += spaces;
1023             }
1024 3730           }
1025              
1026             INLINE void
1027 14           encode_space (pTHX_ enc_t *enc)
1028             {
1029 14           encode_ch (aTHX_ enc, ' ');
1030 14           }
1031              
1032             INLINE void
1033 3852           encode_nl (pTHX_ enc_t *enc)
1034             {
1035 3852 100         if (enc->json.flags & F_INDENT)
1036             {
1037 40           encode_ch (aTHX_ enc, '\n');
1038             }
1039 3852           }
1040              
1041             INLINE void
1042 1212           encode_comma (pTHX_ enc_t *enc)
1043             {
1044 1212           encode_ch (aTHX_ enc, ',');
1045              
1046 1212 100         if (enc->json.flags & F_INDENT)
1047 8           encode_nl (aTHX_ enc);
1048 1204 50         else if (enc->json.flags & F_SPACE_AFTER)
1049 0           encode_space (aTHX_ enc);
1050 1212           }
1051              
1052             static void encode_sv (pTHX_ enc_t *enc, SV *sv, SV *typesv);
1053              
1054             static void
1055 898           encode_av (pTHX_ enc_t *enc, AV *av, SV *typesv)
1056             {
1057 898           AV *typeav = NULL;
1058 898           HVMAX_T i, len = av_len (av);
1059              
1060 898 100         if (enc->indent >= enc->json.max_depth)
1061 1           croak (ERR_NESTING_EXCEEDED);
1062              
1063 897 100         if (UNLIKELY (SvOK (typesv)))
    50          
    50          
    50          
1064             {
1065 22 50         if (SvROK (typesv) &&
    100          
1066 16 100         SvOBJECT (SvRV (typesv)) &&
1067 16           SvTYPE (SvRV (typesv)) == SVt_PVAV)
1068             {
1069 11           HV *stash = SvSTASH (SvRV (typesv));
1070 11 50         char *name = LIKELY (!!stash) ? HvNAME (stash) : NULL;
    50          
    50          
    50          
    0          
    50          
    50          
1071 11 50         if (LIKELY (name && strEQ (name, JSON_TYPE_ANYOF_CLASS)))
    50          
1072             {
1073 11           AV *type_any = (AV *)SvRV (typesv);
1074 11           SV **typesv_ref = av_fetch (type_any, JSON_TYPE_ANYOF_ARRAY_INDEX, 0);
1075 11 50         if (UNLIKELY (!typesv_ref))
1076 0 0         croak ("incorrectly constructed anyof type (%s, 0x%x) was specified for '%s'",
    0          
1077 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1078 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)av))));
1079 11           typesv = *typesv_ref;
1080 11 50         SvGETMAGIC (typesv);
    0          
1081 11 50         if (!SvOK (typesv))
    0          
    0          
1082 0 0         croak ("no array alternative in anyof was specified for '%s'",
1083 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)av))));
1084             }
1085             }
1086              
1087 22 50         if (UNLIKELY (!SvROK (typesv)))
1088 0 0         croak ("encountered type (%s, 0x%x) was specified for '%s'",
    0          
1089 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1090 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)av))));
1091              
1092 22 100         if (!SvOBJECT (SvRV (typesv)) && SvTYPE (SvRV (typesv)) == SVt_PVAV)
    50          
1093             {
1094 9           typeav = (AV *)SvRV (typesv);
1095 9 50         if (len != av_len (typeav))
1096 0 0         croak ("array '%s' has different number of elements as in specified type '%s'",
    0          
1097 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)av))),
1098 0           SvPV_nolen (typesv));
1099             }
1100 13 50         else if (SvOBJECT (SvRV (typesv)) &&
    50          
1101 13           SvTYPE (SvRV (typesv)) < SVt_PVAV)
1102 13           {
1103 13           HV *stash = SvSTASH (SvRV (typesv));
1104 13 50         char *name = LIKELY (!!stash) ? HvNAME (stash) : NULL;
    50          
    50          
    50          
    0          
    50          
    50          
1105 13 50         if (LIKELY (name && strEQ (name, JSON_TYPE_ARRAYOF_CLASS)))
    50          
1106 13           typesv = (SV *)SvRV (typesv);
1107             else
1108 0 0         croak ("encountered type (%s, 0x%x) was specified for '%s'",
    0          
1109 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1110 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)av))));
1111             }
1112             else
1113 0 0         croak ("encountered type (%s, 0x%x) was specified for '%s'",
    0          
1114 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1115 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)av))));
1116             }
1117              
1118 897           encode_ch (aTHX_ enc, '[');
1119            
1120 897 100         if (len >= 0)
1121             {
1122 887           encode_nl (aTHX_ enc); ++enc->indent;
1123              
1124 2608 100         for (i = 0; i <= len; ++i)
1125             {
1126 1736           SV **svp = av_fetch (av, i, 0);
1127              
1128 1736 100         if (typeav)
1129             {
1130 23           SV **typerv = av_fetch (typeav, i, 0);
1131 23 50         if (typerv)
1132 23           typesv = *typerv;
1133             }
1134              
1135 1736           encode_indent (aTHX_ enc);
1136              
1137 1736 100         if (svp)
1138 1734           encode_sv (aTHX_ enc, *svp, typesv);
1139             else
1140 2           encode_const_str (aTHX_ enc, "null", 4, 0);
1141              
1142 1721 100         if (i < len)
1143 849           encode_comma (aTHX_ enc);
1144             }
1145              
1146 872           encode_nl (aTHX_ enc); --enc->indent; encode_indent (aTHX_ enc);
1147             }
1148            
1149 882           encode_ch (aTHX_ enc, ']');
1150 882           }
1151              
1152             INLINE void
1153 745           retrieve_hk (pTHX_ HE *he, char **key, I32 *klen)
1154             {
1155             int utf8;
1156              
1157 745 100         if (He_IS_SVKEY(he))
1158             {
1159             STRLEN len;
1160 1 50         SV *sv = HeSVKEY (he);
    50          
1161 1 50         *key = SvPV (sv, len);
1162 1           *klen = (I32)len;
1163 1           utf8 = SvUTF8 (sv);
1164             }
1165             else
1166             {
1167 744           *key = HeKEY (he);
1168 744           *klen = HeKLEN (he);
1169 744           utf8 = HeKUTF8 (he);
1170             }
1171              
1172 745 100         if (utf8) *klen = -(*klen);
1173 745           }
1174              
1175             static void
1176 745           encode_hk (pTHX_ enc_t *enc, char *key, I32 klen)
1177             {
1178 745           encode_ch (aTHX_ enc, '"');
1179 745           encode_str (aTHX_ enc, key, klen < 0 ? -klen : klen, klen < 0);
1180 745           encode_ch (aTHX_ enc, '"');
1181              
1182 745 100         if (enc->json.flags & F_SPACE_BEFORE) encode_space (aTHX_ enc);
1183 745           encode_ch (aTHX_ enc, ':');
1184 745 100         if (enc->json.flags & F_SPACE_AFTER ) encode_space (aTHX_ enc);
1185 745           }
1186              
1187             /* compare hash entries, used when all keys are bytestrings */
1188             static int
1189 316           he_cmp_fast (const void *a_, const void *b_)
1190             {
1191             int cmp;
1192              
1193 316           HE *a = *(HE **)a_;
1194 316           HE *b = *(HE **)b_;
1195              
1196 316           STRLEN la = HeKLEN (a);
1197 316           STRLEN lb = HeKLEN (b);
1198              
1199 316 100         if (!(cmp = memcmp (HeKEY (b), HeKEY (a), lb < la ? lb : la)))
1200 198           cmp = lb - la;
1201              
1202 316           return cmp;
1203             }
1204              
1205             /* compare hash entries, used when some keys are sv's or utf-x */
1206             static int
1207 371           he_cmp_slow (const void *a, const void *b)
1208             {
1209             dTHX;
1210 371 50         return sv_cmp (HeSVKEY_force (*(HE **)b), HeSVKEY_force (*(HE **)a));
    50          
    100          
    50          
    50          
    100          
1211             }
1212              
1213             static void
1214 393           encode_hv (pTHX_ enc_t *enc, HV *hv, SV *typesv)
1215             {
1216 393           HV *typehv = NULL;
1217             HE *he;
1218              
1219 393 100         if (enc->indent >= enc->json.max_depth)
1220 1           croak (ERR_NESTING_EXCEEDED);
1221              
1222 392 100         if (UNLIKELY (SvOK (typesv)))
    50          
    50          
    50          
1223             {
1224 17 50         if (SvROK (typesv) &&
    100          
1225 6 100         SvOBJECT (SvRV (typesv)) &&
1226 6           SvTYPE (SvRV (typesv)) == SVt_PVAV)
1227             {
1228 4           HV *stash = SvSTASH (SvRV (typesv));
1229 4 50         char *name = LIKELY (!!stash) ? HvNAME (stash) : NULL;
    50          
    50          
    50          
    0          
    50          
    50          
1230 4 50         if (LIKELY (name && strEQ (name, JSON_TYPE_ANYOF_CLASS)))
    50          
1231             {
1232 4           AV *type_any = (AV *)SvRV (typesv);
1233 4           SV **typesv_ref = av_fetch (type_any, JSON_TYPE_ANYOF_HASH_INDEX, 0);
1234 4 50         if (UNLIKELY (!typesv_ref))
1235 0 0         croak ("incorrectly constructed anyof type (%s, 0x%x) was specified for '%s'",
    0          
1236 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1237 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)hv))));
1238 4           typesv = *typesv_ref;
1239 4 50         SvGETMAGIC (typesv);
    0          
1240 4 50         if (!SvOK (typesv))
    0          
    0          
1241 0 0         croak ("no hash alternative in anyof was specified for '%s'",
1242 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)hv))));
1243             }
1244             }
1245              
1246 17 50         if (UNLIKELY (!SvROK (typesv)))
1247 0 0         croak ("encountered type (%s, 0x%x) was specified for '%s'",
    0          
1248 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1249 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)hv))));
1250              
1251 17 100         if (!SvOBJECT (SvRV (typesv)) && SvTYPE (SvRV (typesv)) == SVt_PVHV)
    50          
1252 13           typehv = (HV *)SvRV (typesv);
1253 4 50         else if (SvOBJECT (SvRV (typesv)) &&
    50          
1254 4           SvTYPE (SvRV (typesv)) < SVt_PVAV)
1255 4           {
1256 4           HV *stash = SvSTASH (SvRV (typesv));
1257 4 50         char *name = LIKELY (!!stash) ? HvNAME (stash) : NULL;
    50          
    50          
    50          
    0          
    50          
    50          
1258 4 50         if (LIKELY (name && strEQ (name, JSON_TYPE_HASHOF_CLASS)))
    50          
1259 4           typesv = (SV *)SvRV (typesv);
1260             else
1261 0 0         croak ("encountered type (%s, 0x%x) was specified for '%s'",
    0          
1262 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1263 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)hv))));
1264             }
1265             else
1266 0 0         croak ("encountered type (%s, 0x%x) was specified for '%s'",
    0          
1267 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1268 0           SvPV_nolen (sv_2mortal (newRV_inc ((SV *)hv))));
1269             }
1270              
1271              
1272 392           encode_ch (aTHX_ enc, '{');
1273              
1274             /* for canonical output we have to sort by keys first */
1275             /* caused by randomised hash orderings */
1276 392 100         if (enc->json.flags & F_CANONICAL && !SvTIED_mg((SV*)hv, PERL_MAGIC_tied))
    50          
    0          
1277 239           {
1278 240           RITER_T i, count = hv_iterinit (hv);
1279              
1280 240 50         if (SvMAGICAL (hv))
1281             {
1282             /* need to count by iterating. could improve by dynamically building the vector below */
1283             /* but I don't care for the speed of this special case. */
1284             /* note also that we will run into undefined behaviour when the two iterations */
1285             /* do not result in the same count, something I might care for in some later release. */
1286              
1287 0           count = 0;
1288 0 0         while (hv_iternext (hv))
1289 0           ++count;
1290              
1291 0           hv_iterinit (hv);
1292             }
1293              
1294 240 100         if (count)
1295             {
1296 234           int fast = 1;
1297             HE *hes_stack [STACK_HES];
1298 234           HE **hes = hes_stack;
1299              
1300             /* allocate larger arrays on the heap */
1301 234 50         if (count > STACK_HES)
1302             {
1303 0           SV *sv = sv_2mortal (NEWSV (0, count * sizeof (*hes)));
1304 0           hes = (HE **)SvPVX (sv);
1305             }
1306              
1307 234           i = 0;
1308 819 100         while ((he = hv_iternext (hv)))
1309             {
1310 585           hes [i++] = he;
1311 585 50         if (HeKLEN (he) < 0 || HeKUTF8 (he))
    100          
1312 3           fast = 0;
1313             }
1314              
1315             assert (i == count);
1316              
1317 234 100         if (fast)
1318 231           qsort (hes, count, sizeof (HE *), he_cmp_fast);
1319             else
1320             {
1321             /* hack to forcefully disable "use bytes" */
1322 3           COP cop = *PL_curcop;
1323 3           cop.op_private = 0;
1324              
1325 3           ENTER;
1326 3           SAVETMPS;
1327              
1328 3           SAVEVPTR (PL_curcop);
1329 3           PL_curcop = &cop;
1330              
1331 3           qsort (hes, count, sizeof (HE *), he_cmp_slow);
1332              
1333 3 50         FREETMPS;
1334 3           LEAVE;
1335             }
1336              
1337 234           encode_nl (aTHX_ enc); ++enc->indent;
1338              
1339 818 100         while (count--)
1340             {
1341             char *key;
1342             I32 klen;
1343              
1344 585           encode_indent (aTHX_ enc);
1345 585           he = hes [count];
1346 585           retrieve_hk (aTHX_ he, &key, &klen);
1347 585           encode_hk (aTHX_ enc, key, klen);
1348              
1349 585 100         if (UNLIKELY (PTR2ul (typehv)))
1350             {
1351 29           SV **typesv_ref = hv_fetch (typehv, key, klen, 0);
1352 29 50         if (UNLIKELY (!typesv_ref))
1353 0           croak ("no type was specified for hash key '%s'", key);
1354              
1355 29           typesv = *typesv_ref;
1356             }
1357              
1358 585 50         encode_sv (aTHX_ enc, UNLIKELY(SvMAGICAL (hv)) ? hv_iterval (hv, he) : HeVAL (he), typesv);
1359              
1360 584 100         if (count)
1361 584           encode_comma (aTHX_ enc);
1362             }
1363              
1364 233           encode_nl (aTHX_ enc); --enc->indent; encode_indent (aTHX_ enc);
1365             }
1366             }
1367             else
1368             {
1369 152 100         if (hv_iterinit (hv) || SvMAGICAL (hv))
    100          
1370 148 50         if ((he = hv_iternext (hv)))
1371             {
1372 148           encode_nl (aTHX_ enc); ++enc->indent;
1373              
1374             for (;;)
1375             {
1376             char *key;
1377             I32 klen;
1378              
1379 160           encode_indent (aTHX_ enc);
1380 160           retrieve_hk (aTHX_ he, &key, &klen);
1381 160           encode_hk (aTHX_ enc, key, klen);
1382              
1383 160 50         if (UNLIKELY (PTR2ul (typehv)))
1384             {
1385 0           SV **typesv_ref = hv_fetch (typehv, key, klen, 0);
1386 0 0         if (UNLIKELY (!typesv_ref))
1387 0           croak ("no type was specified for hash key '%s'", key);
1388              
1389 0           typesv = *typesv_ref;
1390             }
1391              
1392 160 100         encode_sv (aTHX_ enc, UNLIKELY(SvMAGICAL (hv)) ? hv_iterval (hv, he) : HeVAL (he), typesv);
1393              
1394 156 100         if (!(he = hv_iternext (hv)))
1395 144           break;
1396              
1397 12           encode_comma (aTHX_ enc);
1398 12           }
1399              
1400 144           encode_nl (aTHX_ enc); --enc->indent; encode_indent (aTHX_ enc);
1401             }
1402             }
1403              
1404 387           encode_ch (aTHX_ enc, '}');
1405 387           }
1406              
1407             /* implement convert_blessed, sv is already unref'ed here */
1408             static void
1409 11           encode_stringify(pTHX_ enc_t *enc, SV *sv, int isref)
1410             {
1411 11           char *str = NULL;
1412             STRLEN len;
1413 11           SV *pv = NULL;
1414 11           svtype type = SvTYPE(sv);
1415             #if PERL_VERSION <= 8
1416             MAGIC *mg;
1417             #endif
1418              
1419             /* SvAMAGIC without the ref */
1420             #if PERL_VERSION > 17
1421             #define MyAMG(sv) (SvOBJECT(sv) && HvAMAGIC(SvSTASH(sv)))
1422             #else
1423             #if PERL_VERSION > 8
1424             #define MyAMG(sv) (SvOBJECT(sv) && (SvFLAGS(sv) & SVf_AMAGIC))
1425             #else
1426             #define MyAMG(sv) (SvOBJECT(sv) && ((SvFLAGS(sv) & SVf_AMAGIC) \
1427             || ((mg = mg_find((SV*)SvSTASH(sv), PERL_MAGIC_overload_table)) \
1428             && mg->mg_ptr && AMT_AMAGIC((AMT*)mg->mg_ptr))))
1429             #endif
1430             #endif
1431              
1432 11 100         if (isref && SvAMAGIC(sv))
    50          
    50          
    50          
1433             ;
1434             /* if no string overload found, check allow_stringify */
1435 2 50         else if (!MyAMG(sv) && !(enc->json.flags & F_ALLOW_STRINGIFY)) {
    50          
    50          
1436 2 50         if (isref && !(enc->json.flags & F_ALLOW_UNKNOWN))
    0          
1437 0 0         croak ("cannot encode reference to scalar '%s' unless the scalar is 0 or 1",
1438 0           SvPV_nolen (sv_2mortal (newRV_inc (sv))));
1439 2           encode_const_str (aTHX_ enc, "null", 4, 0);
1440 9           return;
1441             }
1442             /* sv_2pv_flags does not accept those types: */
1443 9 50         if (type != SVt_PVAV && type != SVt_PVHV && type != SVt_PVFM) {
    50          
    50          
1444             /* the essential of pp_stringify */
1445             #if PERL_VERSION > 7
1446 9           pv = newSVpvs("");
1447 9           sv_copypv(pv, sv);
1448 9 50         SvSETMAGIC(pv);
1449 9 50         str = SvPVutf8_force(pv, len);
1450             #else
1451             char *s;
1452             if (isref) {
1453             pv = AMG_CALLun(sv,string);
1454             len = SvCUR(pv);
1455             str = SvPVX(pv);
1456             SvREFCNT_inc(pv);
1457             }
1458             else {
1459             pv = newSVpvs("");
1460             s = SvPV(sv,len);
1461             sv_setpvn(pv,s,len);
1462             if (SvUTF8(sv))
1463             SvUTF8_on(pv);
1464             else
1465             SvUTF8_off(pv);
1466             SvSETMAGIC(pv);
1467             str = SvPVutf8_force(pv, len);
1468             }
1469             #endif
1470 9 50         if (!len) {
1471 0           encode_const_str (aTHX_ enc, "null", 4, 0);
1472 0           SvREFCNT_dec(pv);
1473 0           return;
1474             }
1475             } else {
1476             /* manually call all possible magic on AV, HV, FM */
1477 0 0         if (SvGMAGICAL(sv)) mg_get(sv);
1478 0 0         if (MyAMG(sv)) { /* force a RV here */
    0          
1479 0           SV* rv = newRV(SvREFCNT_inc(sv));
1480             #if PERL_VERSION <= 8
1481             HV *stash = SvSTASH(sv);
1482             if (!SvSTASH(rv) || !(SvFLAGS(sv) & SVf_AMAGIC)) {
1483             sv_bless(rv, stash);
1484             Gv_AMupdate(stash);
1485             SvFLAGS(sv) |= SVf_AMAGIC;
1486             }
1487             #endif
1488             #if PERL_VERSION > 13
1489 0           pv = AMG_CALLunary(rv, string_amg);
1490             #else
1491             pv = AMG_CALLun(rv, string);
1492             #endif
1493 0 0         TAINT_IF(pv && SvTAINTED(pv));
    0          
    0          
    0          
1494 0 0         if (pv && SvPOK(pv)) {
    0          
1495 0 0         str = SvPVutf8_force(pv, len);
1496 0           encode_ch (aTHX_ enc, '"');
1497 0           encode_str (aTHX_ enc, str, len, 0);
1498 0           encode_ch (aTHX_ enc, '"');
1499 0           SvREFCNT_dec(rv);
1500 0           return;
1501             }
1502 0           SvREFCNT_dec(rv);
1503             }
1504             }
1505 9 50         if (UNLIKELY(isref == 1 && (enc->json.flags & F_ALLOW_BIGNUM) && str && str[0] == '+')) {
    50          
    50          
    50          
    50          
    50          
1506 0           str++;
1507 0           len--;
1508             }
1509             /* if ALLOW_BIGNUM and Math::Big* and NaN => according to stringify_infnan */
1510 9 50         if (UNLIKELY(
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
    100          
1511             (enc->json.flags & F_ALLOW_BIGNUM)
1512             && str
1513             && SvROK(sv)
1514             && (memEQc(str, "NaN") || memEQc(str, "nan") ||
1515             memEQc(str, "inf") || memEQc(str, "-inf"))))
1516             {
1517 7 50         if (is_bignum_obj (aTHX_ SvRV (sv)))
1518             {
1519 7 100         if (enc->json.infnan_mode == 0) {
1520 4           encode_const_str (aTHX_ enc, "null", 4, 0);
1521 4 50         if (pv) SvREFCNT_dec(pv);
1522 4           return;
1523 3 50         } else if (enc->json.infnan_mode == 3) {
1524 3 100         if (memEQc(str, "NaN") || memEQc(str, "nan"))
    50          
1525 1           encode_const_str (aTHX_ enc, "nan", 3, 0);
1526 2 100         else if (memEQc(str, "inf"))
1527 1           encode_const_str (aTHX_ enc, "inf", 3, 0);
1528             else
1529 1           encode_const_str (aTHX_ enc, "-inf", 4, 0);
1530 3 50         if (pv) SvREFCNT_dec(pv);
1531 3           return;
1532             }
1533             }
1534             }
1535 2 50         if (!str)
1536 0           encode_const_str (aTHX_ enc, "null", 4, 0);
1537             else {
1538 2 50         if (isref != 1)
1539 0           encode_ch (aTHX_ enc, '"');
1540 2           encode_str (aTHX_ enc, str, len, 0);
1541 2 50         if (isref != 1)
1542 2           encode_ch (aTHX_ enc, '"');
1543             }
1544             #undef MyAMG
1545             }
1546              
1547             INLINE int
1548 63           encode_bool_obj (pTHX_ enc_t *enc, SV *sv, int force_conversion, int as_string)
1549             {
1550 63 100         if (is_bool_obj (aTHX_ sv))
1551             {
1552 35 100         if (as_string)
1553 3           encode_ch (aTHX_ enc, '"');
1554 35 50         if (SvIV_nomg (sv))
    100          
1555 20           encode_const_str (aTHX_ enc, "true", 4, 0);
1556             else
1557 15           encode_const_str (aTHX_ enc, "false", 5, 0);
1558 35 100         if (as_string)
1559 35           encode_ch (aTHX_ enc, '"');
1560             }
1561 28 50         else if (force_conversion && enc->json.flags & F_CONV_BLESSED)
    0          
1562             {
1563 0 0         if (as_string)
1564 0           encode_ch (aTHX_ enc, '"');
1565 0 0         if (SvTRUE_nomg (sv))
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1566 0           encode_const_str (aTHX_ enc, "true", 4, 0);
1567             else
1568 0           encode_const_str (aTHX_ enc, "false", 5, 0);
1569 0 0         if (as_string)
1570 0           encode_ch (aTHX_ enc, '"');
1571             }
1572             else
1573 28           return 0;
1574              
1575 35           return 1;
1576             }
1577              
1578             INLINE int
1579 27           encode_bool_ref (pTHX_ enc_t *enc, SV *sv)
1580             {
1581 27           int bool_type = ref_bool_type (aTHX_ sv);
1582              
1583 27 100         if (bool_type == 1)
1584 5           encode_const_str (aTHX_ enc, "true", 4, 0);
1585 22 100         else if (bool_type == 0)
1586 3           encode_const_str (aTHX_ enc, "false", 5, 0);
1587             else
1588 19           return 0;
1589              
1590 8           return 1;
1591             }
1592              
1593             /* encode objects, arrays and special \0=false and \1=true values
1594             and other representations of booleans: JSON::PP::Boolean, Mojo::JSON::_Bool
1595             */
1596             static void
1597 80           encode_rv (pTHX_ enc_t *enc, SV *rv)
1598             {
1599             svtype svt;
1600             GV *method;
1601 80           SV *sv = SvRV(rv);
1602              
1603 80           svt = SvTYPE (sv);
1604              
1605 80 100         if (UNLIKELY (SvOBJECT (sv)))
1606             {
1607 51 100         if (!encode_bool_obj (aTHX_ enc, sv, 0, 0))
1608             {
1609 28           HV *stash = SvSTASH (sv);
1610 28 100         if ((enc->json.flags & F_ALLOW_TAGS)
1611 7 100         && (method = gv_fetchmethod_autoload (stash, "FREEZE", 0)))
1612 48           {
1613             dMY_CXT;
1614 6           dSP;
1615             int count, items;
1616              
1617 6 50         ENTER; SAVETMPS; SAVESTACK_POS (); PUSHMARK (SP);
    50          
1618 6 50         EXTEND (SP, 2);
1619 6           PUSHs (rv);
1620 6           PUSHs (MY_CXT.sv_json);
1621              
1622 6           PUTBACK;
1623 6           count = call_sv ((SV *)GvCV (method), G_ARRAY);
1624 6           items = count;
1625 6           SPAGAIN;
1626              
1627             /* catch this surprisingly common error */
1628 6 100         if (SvROK (TOPs) && SvRV (TOPs) == sv)
    50          
1629 0 0         croak ("%s::FREEZE method returned same object as was passed instead of a new one",
    0          
1630 0 0         HvNAME (SvSTASH (sv)));
    0          
    0          
    0          
1631              
1632 6           encode_ch (aTHX_ enc, '(');
1633 6           encode_ch (aTHX_ enc, '"');
1634 6 50         encode_str (aTHX_ enc, HvNAME (stash), HvNAMELEN (stash), HvNAMEUTF8 (stash));
    50          
    50          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    50          
    50          
1635 6           encode_ch (aTHX_ enc, '"');
1636 6           encode_ch (aTHX_ enc, ')');
1637 6           encode_ch (aTHX_ enc, '[');
1638              
1639 261 100         while (count)
1640             {
1641 255           encode_sv (aTHX_ enc, SP[1 - count--], &PL_sv_undef);
1642 255           SPAGAIN;
1643              
1644 255 100         if (count)
1645 249           encode_ch (aTHX_ enc, ',');
1646             }
1647              
1648 6           encode_ch (aTHX_ enc, ']');
1649              
1650 6           SP -= items;
1651 6           PUTBACK;
1652              
1653 6 50         FREETMPS; LEAVE;
1654             }
1655 22 100         else if ((enc->json.flags & F_CONV_BLESSED)
1656 18 100         && (method = gv_fetchmethod_autoload (stash, "TO_JSON", 0)))
1657 6           {
1658 7           dSP;
1659              
1660 7 50         ENTER; SAVETMPS; PUSHMARK (SP);
1661              
1662 7 50         XPUSHs (rv);
1663              
1664             /* calling with G_SCALAR ensures that we always get a 1 return value */
1665 7           PUTBACK;
1666 7           call_sv ((SV *)GvCV (method), G_SCALAR);
1667 7           SPAGAIN;
1668            
1669             /* catch this surprisingly common error */
1670 7 100         if (SvROK (TOPs) && SvRV (TOPs) == sv)
    100          
1671 1 50         croak ("%s::TO_JSON method returned same object as was passed instead of a new one", HvNAME (SvSTASH (sv)));
    50          
    50          
    0          
    50          
    50          
1672              
1673 6           sv = POPs;
1674 6           PUTBACK;
1675              
1676 6           encode_sv (aTHX_ enc, sv, &PL_sv_undef);
1677              
1678 6 50         FREETMPS; LEAVE;
1679             }
1680 15 100         else if ((enc->json.flags & F_ALLOW_BIGNUM) && is_bignum_obj (aTHX_ sv))
    50          
1681 9           encode_stringify(aTHX_ enc, rv, 1);
1682 6 100         else if (enc->json.flags & F_CONV_BLESSED)
1683 2           encode_stringify(aTHX_ enc, sv, 0);
1684 4 100         else if (enc->json.flags & F_ALLOW_BLESSED)
1685 2           encode_const_str (aTHX_ enc, "null", 4, 0);
1686             else
1687 4 50         croak ("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)",
1688 4           SvPV_nolen (sv_2mortal (newRV_inc (sv))));
1689             }
1690             }
1691 29 100         else if (svt < SVt_PVAV && svt != SVt_PVGV && svt != SVt_PVHV && svt != SVt_PVAV)
    100          
    50          
    50          
1692             {
1693 31 100         if (!encode_bool_ref (aTHX_ enc, sv))
1694             {
1695 19 50         if (enc->json.flags & F_ALLOW_STRINGIFY)
1696 0           encode_stringify(aTHX_ enc, sv, SvROK(sv));
1697 19 100         else if (enc->json.flags & F_ALLOW_UNKNOWN)
1698 7           encode_const_str (aTHX_ enc, "null", 4, 0);
1699             else
1700 24 50         croak ("cannot encode reference to scalar '%s' unless the scalar is 0 or 1",
1701 24           SvPV_nolen (sv_2mortal (newRV_inc (sv))));
1702             }
1703             }
1704 5 100         else if (enc->json.flags & F_ALLOW_UNKNOWN)
1705 2           encode_const_str (aTHX_ enc, "null", 4, 0);
1706             else
1707 6 50         croak ("encountered %s, but JSON can only represent references to arrays or hashes",
1708 6           SvPV_nolen (sv_2mortal (newRV_inc (sv))));
1709 62           }
1710              
1711             static void
1712 107           encode_bool (pTHX_ enc_t *enc, SV *sv)
1713             {
1714             svtype svt;
1715              
1716 107 100         if (!SvROK (sv))
1717             {
1718 95 100         if (UNLIKELY (sv == &PL_sv_yes))
1719 8           encode_const_str (aTHX_ enc, "true", 4, 0);
1720 87 100         else if (UNLIKELY (sv == &PL_sv_no))
1721 6           encode_const_str (aTHX_ enc, "false", 5, 0);
1722 81 100         else if (!SvOK (sv))
    50          
    50          
1723 1           encode_const_str (aTHX_ enc, "false", 5, 0);
1724 80 50         else if (SvTRUE_nomg (sv))
    50          
    0          
    0          
    100          
    50          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    100          
    100          
    100          
    0          
1725 65           encode_const_str (aTHX_ enc, "true", 4, 0);
1726             else
1727 95           encode_const_str (aTHX_ enc, "false", 5, 0);
1728             }
1729             else
1730             {
1731 12           sv = SvRV (sv);
1732 12           svt = SvTYPE (sv);
1733              
1734 12 100         if (UNLIKELY (SvOBJECT (sv)))
1735             {
1736 9 50         if (!encode_bool_obj (aTHX_ enc, sv, 1, 0))
1737 0 0         croak ("encountered object '%s', but convert_blessed is not enabled",
1738 0           SvPV_nolen (sv_2mortal (newRV_inc (sv))));
1739             }
1740 3 50         else if (svt < SVt_PVAV && svt != SVt_PVGV)
    50          
1741             {
1742 3 50         if (!encode_bool_ref (aTHX_ enc, sv))
1743 0 0         croak ("cannot encode reference to scalar '%s' unless the scalar is 0 or 1",
1744 0           SvPV_nolen (sv_2mortal (newRV_inc (sv))));
1745             }
1746             else
1747 0 0         croak ("encountered %s, but does not represent boolean",
1748 0           SvPV_nolen (sv_2mortal (newRV_inc (sv))));
1749             }
1750 107           }
1751              
1752             static void
1753 31           sv_to_ivuv (pTHX_ SV *sv, int *is_neg, IV *iv, UV *uv)
1754             {
1755 31 50         *iv = SvIV_nomg (sv);
1756 31           *uv = (UV)(*iv);
1757             /* SvIV and SvUV may modify SvIsUV flag */
1758 31           *is_neg = !SvIsUV (sv);
1759 31 100         if (!*is_neg)
1760             {
1761 9 50         *uv = SvUV_nomg (sv);
1762 9           *iv = (IV)(*uv);
1763             }
1764 31           }
1765              
1766             static void
1767 4095           encode_sv (pTHX_ enc_t *enc, SV *sv, SV *typesv)
1768             {
1769 4095           IV type = 0;
1770 4095           int can_be_null = 0;
1771 4095           int process_ref = 0;
1772 4095           int force_conversion = 0;
1773              
1774 4095 100         SvGETMAGIC (sv);
    50          
1775 4095 50         SvGETMAGIC (typesv);
    0          
1776              
1777 4095 100         if (UNLIKELY (!(SvOK (typesv)) && (enc->json.flags & F_REQUIRE_TYPES) && !(enc->json.flags & F_TYPE_ALL_STRING)))
    50          
    50          
    50          
    100          
    100          
    100          
    100          
1778 8 50         croak ("type for '%s' was not specified", SvPV_nolen (sv));
1779              
1780 4087 100         if (SvROK (sv) && !SvOBJECT (SvRV (sv)))
    100          
1781             {
1782 1323           svtype svt = SvTYPE (SvRV (sv));
1783 1323 100         if (svt == SVt_PVHV)
1784             {
1785 393           encode_hv (aTHX_ enc, (HV *)SvRV (sv), typesv);
1786 387           return;
1787             }
1788 930 100         else if (svt == SVt_PVAV)
1789             {
1790 898           encode_av (aTHX_ enc, (AV *)SvRV (sv), typesv);
1791 882           return;
1792             }
1793             }
1794              
1795 2796 100         if (UNLIKELY (!(SvOK (typesv)) && (enc->json.flags & F_TYPE_ALL_STRING)))
    50          
    50          
    50          
    100          
    100          
1796 9           typesv = sv_2mortal (newSViv (JSON_TYPE_STRING | JSON_TYPE_CAN_BE_NULL));
1797              
1798 2796 100         if (UNLIKELY (SvOK (typesv)))
    50          
    50          
    50          
1799             {
1800 404 100         if (SvROK (sv) && SvOBJECT (SvRV (sv)) && !(enc->json.flags & (F_ALLOW_TAGS|F_CONV_BLESSED|F_ALLOW_BLESSED)) && !is_bool_obj (aTHX_ SvRV (sv)) && !is_bignum_obj (aTHX_ SvRV (sv)))
    100          
    50          
    100          
    100          
1801 1 50         croak ("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)", SvPV_nolen (sv));
1802              
1803 403 100         if (!SvIOKp (typesv))
1804             {
1805 83 50         if (SvROK (typesv) &&
    50          
1806 83 50         SvOBJECT (SvRV (typesv)) &&
1807 83           SvTYPE (SvRV (typesv)) == SVt_PVAV)
1808 83           {
1809 83           HV *stash = SvSTASH (SvRV (typesv));
1810 83 50         char *name = LIKELY (!!stash) ? HvNAME (stash) : NULL;
    50          
    50          
    50          
    0          
    50          
    50          
1811 83 50         if (LIKELY (name && strEQ (name, JSON_TYPE_ANYOF_CLASS)))
    50          
1812 83           {
1813 83           AV *type_any = (AV *)SvRV (typesv);
1814 83           SV **typesv_ref = av_fetch (type_any, JSON_TYPE_ANYOF_SCALAR_INDEX, 0);
1815 83 50         if (UNLIKELY (!typesv_ref))
1816 0 0         croak ("incorrectly constructed anyof type (%s, 0x%x) was specified for '%s'",
    0          
1817 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1818 0           SvPV_nolen (sv));
1819 83           typesv = *typesv_ref;
1820 83 50         SvGETMAGIC (typesv);
    0          
1821 83 50         if (!SvIOKp (typesv))
1822 0 0         croak ("no scalar alternative in anyof was specified for '%s'", SvPV_nolen (sv));
1823             }
1824             else
1825 0 0         croak ("encountered type (%s, 0x%x) was specified for '%s'",
    0          
1826 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1827 0           SvPV_nolen (sv));
1828             }
1829             else
1830 0 0         croak ("encountered type (%s, 0x%x) was specified for '%s'",
    0          
1831 0           SvPV_nolen (typesv), (unsigned int)SvFLAGS (typesv),
1832 0           SvPV_nolen (sv));
1833             }
1834 403           type = SvIVX (typesv);
1835             }
1836              
1837 2795 100         if (UNLIKELY (type))
1838             {
1839 401           force_conversion = 1;
1840 401           can_be_null = (type & JSON_TYPE_CAN_BE_NULL);
1841 401           type &= ~JSON_TYPE_CAN_BE_NULL;
1842             }
1843             else
1844             {
1845 2394 100         if (UNLIKELY (sv == &PL_sv_yes || sv == &PL_sv_no)) type = JSON_TYPE_BOOL;
    100          
1846 2386 100         else if (SvNOKp (sv)) type = JSON_TYPE_FLOAT;
1847 2308 100         else if (SvIOKp (sv)) type = JSON_TYPE_INT;
1848 1436 100         else if (SvPOKp (sv)) type = JSON_TYPE_STRING;
1849 122 100         else if (SvROK (sv)) process_ref = 1;
1850 42 50         else if (!SvOK (sv)) can_be_null = 1;
    50          
    50          
1851             }
1852              
1853 2795 100         if (can_be_null && !SvOK (sv))
    100          
    50          
    50          
1854 55           encode_const_str (aTHX_ enc, "null", 4, 0);
1855 2740 100         else if (type == JSON_TYPE_BOOL)
1856 107           encode_bool (aTHX_ enc, sv);
1857 2633 100         else if (type == JSON_TYPE_FLOAT)
1858             {
1859 161           int is_bigobj = 0;
1860             char *savecur, *saveend;
1861 161           char inf_or_nan = 0;
1862             #ifdef NEED_NUMERIC_LOCALE_C
1863             # ifdef HAS_USELOCALE
1864             locale_t oldloc = (locale_t)0;
1865             locale_t newloc;
1866             # endif
1867             bool loc_changed = FALSE;
1868             char *locale = NULL;
1869             #endif
1870 161           NV nv = 0;
1871 161           int had_nokp = SvNOKp(sv);
1872              
1873 161 100         if (UNLIKELY (SvROK (sv) && SvOBJECT (SvRV (sv))) && (enc->json.flags & F_ALLOW_BIGNUM) && is_bignum_obj (aTHX_ SvRV (sv)))
    50          
    100          
    50          
1874 16           is_bigobj = 1;
1875              
1876 161 100         if (UNLIKELY (is_bigobj))
1877             {
1878             STRLEN len;
1879 16 50         char *str = SvPV_nomg (sv, len);
1880 16 50         if (UNLIKELY (str[0] == '+'))
1881             {
1882 0           str++;
1883 0           len--;
1884             }
1885 16 100         if (UNLIKELY (memEQc (str, "NaN") || memEQc (str, "nan")))
    50          
1886             {
1887 2           nv = NV_NAN;
1888 2           is_bigobj = 0;
1889             }
1890 14 100         else if (UNLIKELY (memEQc (str, "inf")))
1891             {
1892 2           nv = NV_INF;
1893 2           is_bigobj = 0;
1894             }
1895 12 100         else if (UNLIKELY (memEQc (str, "-inf")))
1896             {
1897 2           nv = -NV_INF;
1898 2           is_bigobj = 0;
1899             }
1900             else
1901             {
1902 10           need (aTHX_ enc, len+1+2); /* +2 for '.0' */
1903 10           savecur = enc->cur;
1904 10           saveend = enc->end;
1905 10           memcpy (enc->cur, str, len);
1906 16           *(enc->cur+len) = '\0';
1907             }
1908             }
1909 145 100         else if (SvNOKp (sv))
1910             {
1911 116           nv = SvNVX (sv);
1912             }
1913             else
1914             {
1915 29 100         if (enc->json.flags & F_ALLOW_BIGNUM)
1916             {
1917             STRLEN len;
1918             char *str;
1919             SV *pv;
1920             SV *errsv;
1921             int numtype;
1922              
1923 15 50         str = SvPV_nomg (sv, len);
1924              
1925 15           numtype = grok_number (str, len, NULL);
1926 15 100         if (UNLIKELY (numtype & IS_NUMBER_INFINITY))
1927 2 100         nv = (numtype & IS_NUMBER_NEG) ? -NV_INF : NV_INF;
1928 13 100         else if (UNLIKELY (numtype & IS_NUMBER_NAN))
1929 1           nv = NV_NAN;
1930 12 50         else if (UNLIKELY (!numtype))
1931 0 0         nv = SvNV_nomg (sv);
1932             else
1933             {
1934 12           pv = newSVpvs ("require Math::BigFloat && Math::BigFloat->new(\"");
1935 12           sv_catpvn (pv, str, len);
1936 12           sv_catpvs (pv, "\");");
1937              
1938 12           eval_sv (pv, G_SCALAR);
1939 12           SvREFCNT_dec (pv);
1940              
1941             /* rethrow current error */
1942 12 50         errsv = ERRSV;
1943 12 50         if (SvROK (errsv))
1944 0           croak (NULL);
1945 12 50         else if (SvTRUE (errsv))
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
1946 0           croak ("%" SVf, SVfARG (errsv));
1947              
1948             {
1949 12           dSP;
1950 12           pv = POPs;
1951 12           PUTBACK;
1952             }
1953              
1954 12 50         str = SvPV (pv, len);
1955 12 50         if (UNLIKELY (str[0] == '+'))
1956             {
1957 0           str++;
1958 0           len--;
1959             }
1960 12           need (aTHX_ enc, len+1);
1961 12           savecur = enc->cur;
1962 12           saveend = enc->end;
1963 12           memcpy (enc->cur, str, len);
1964 12           *(enc->cur+len) = '\0';
1965 15           is_bigobj = 1;
1966             }
1967             }
1968             else
1969             {
1970              
1971             #if PERL_VERSION < 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 8)
1972             if (SvPOKp (sv))
1973             {
1974             int numtype = grok_number (SvPVX (sv), SvCUR (sv), NULL);
1975             if (UNLIKELY (numtype & IS_NUMBER_INFINITY))
1976             nv = (numtype & IS_NUMBER_NEG) ? -NV_INF : NV_INF;
1977             else if (UNLIKELY (numtype & IS_NUMBER_NAN))
1978             nv = NV_NAN;
1979             else
1980             nv = SvNV_nomg (sv);
1981             }
1982             else
1983             {
1984             nv = SvNV_nomg (sv);
1985             }
1986             #else
1987 14 50         nv = SvNV_nomg (sv);
1988             #endif
1989             }
1990             }
1991              
1992 161 100         if (LIKELY (!is_bigobj))
1993             {
1994             /* trust that perl will do the right thing w.r.t. JSON syntax. */
1995 139           need (aTHX_ enc, NV_DIG + 32);
1996 139           savecur = enc->cur;
1997 139           saveend = enc->end;
1998              
1999 139 100         if (force_conversion)
2000             {
2001 61           had_nokp = 0;
2002             #if defined(USE_QUADMATH) && defined(HAVE_ISINFL)
2003             if (UNLIKELY(isinfl(nv)))
2004             #else
2005 61 100         if (UNLIKELY(isinf(nv)))
2006             #endif
2007 16 100         nv = (nv > 0) ? NV_MAX : -NV_MAX;
2008             #if defined(USE_QUADMATH) && defined(HAVE_ISNANL)
2009             if (UNLIKELY(isnanl(nv)))
2010             #else
2011 61 100         if (UNLIKELY(isnan(nv)))
2012             #endif
2013 61           nv = 0;
2014             }
2015             /* With no stringify_infnan we can skip the conversion, returning null. */
2016 78 100         else if (enc->json.infnan_mode == 0)
2017             {
2018             #if defined(USE_QUADMATH) && defined(HAVE_ISINFL)
2019             if (UNLIKELY(isinfl(nv)))
2020             #else
2021 63 100         if (UNLIKELY(isinf(nv)))
2022             #endif
2023             {
2024 2 100         inf_or_nan = (nv > 0) ? 1 : 2;
2025 2           goto is_inf_or_nan;
2026             }
2027             #if defined(USE_QUADMATH) && defined(HAVE_ISNANL)
2028             if (UNLIKELY(isnanl(nv)))
2029             #else
2030 61 100         if (UNLIKELY(isnan(nv)))
2031             #endif
2032             {
2033 3           inf_or_nan = 3;
2034 3           goto is_inf_or_nan;
2035             }
2036             }
2037             /* locale insensitive sprintf radix #96 */
2038             #ifdef NEED_NUMERIC_LOCALE_C
2039             locale = setlocale(LC_NUMERIC, NULL);
2040             if (!locale || strNE(locale, "C"))
2041             {
2042             loc_changed = TRUE;
2043             # ifdef HAS_USELOCALE
2044             /* thread-safe variant for children not changing the global state */
2045             oldloc = uselocale((locale_t)0);
2046             if (oldloc == LC_GLOBAL_LOCALE)
2047             newloc = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
2048             else
2049             newloc = newlocale(LC_NUMERIC_MASK, "C", oldloc);
2050             uselocale(newloc);
2051             # else
2052             setlocale(LC_NUMERIC, "C");
2053             # endif
2054             }
2055             #endif
2056              
2057             #ifdef USE_QUADMATH
2058             quadmath_snprintf(enc->cur, enc->end - enc->cur, "%.*Qg", (int)NV_DIG, nv);
2059             #else
2060 134           PERL_UNUSED_RESULT(Gconvert (nv, NV_DIG, 0, enc->cur));
2061             #endif
2062              
2063             #ifdef NEED_NUMERIC_LOCALE_C
2064             if (loc_changed)
2065             {
2066             # ifdef HAS_USELOCALE
2067             (void)uselocale(oldloc);
2068             if (newloc)
2069             freelocale(newloc);
2070             # else
2071             (void)setlocale(LC_NUMERIC, locale);
2072             # endif
2073             }
2074             #endif
2075              
2076             #ifdef STR_INF4
2077             if (UNLIKELY(strEQc(enc->cur, STR_INF)
2078             || strEQc(enc->cur, STR_INF2)
2079             || strEQc(enc->cur, STR_INF3)
2080             || strEQc(enc->cur, STR_INF4)))
2081             #elif defined(STR_INF2)
2082             if (UNLIKELY(strEQc(enc->cur, STR_INF)
2083             || strEQc(enc->cur, STR_INF2)))
2084             #else
2085 134 100         if (UNLIKELY(strEQc(enc->cur, STR_INF)))
2086             #endif
2087 3           inf_or_nan = 1;
2088             #if defined(__hpux)
2089             else if (UNLIKELY(strEQc(enc->cur, STR_NEG_INF)))
2090             inf_or_nan = 2;
2091             else if (UNLIKELY(strEQc(enc->cur, STR_NEG_NAN)))
2092             inf_or_nan = 3;
2093             #endif
2094             else if
2095             #ifdef HAVE_QNAN
2096             # ifdef STR_QNAN2
2097             (UNLIKELY(strEQc(enc->cur, STR_NAN)
2098             || strEQc(enc->cur, STR_QNAN)
2099             || strEQc(enc->cur, STR_NAN2)
2100             || strEQc(enc->cur, STR_QNAN2)))
2101             # else
2102             (UNLIKELY(strEQc(enc->cur, STR_NAN)
2103             || strEQc(enc->cur, STR_QNAN)))
2104             # endif
2105             #else
2106 131 100         (UNLIKELY(strEQc(enc->cur, STR_NAN)))
2107             #endif
2108 3           inf_or_nan = 3;
2109 128 100         else if (*enc->cur == '-') {
2110             #ifdef STR_INF4
2111             if (UNLIKELY(strEQc(enc->cur+1, STR_INF)
2112             || strEQc(enc->cur+1, STR_INF2)
2113             || strEQc(enc->cur+1, STR_INF3)
2114             || strEQc(enc->cur+1, STR_INF4)))
2115             #elif defined(STR_INF2)
2116             if (UNLIKELY(strEQc(enc->cur+1, STR_INF)
2117             || strEQc(enc->cur+1, STR_INF2)))
2118             #else
2119 25 100         if (UNLIKELY(strEQc(enc->cur+1, STR_INF)))
2120             #endif
2121 3           inf_or_nan = 2;
2122             else if
2123             #ifdef HAVE_QNAN
2124             # ifdef STR_QNAN2
2125             (UNLIKELY(strEQc(enc->cur+1, STR_NAN)
2126             || strEQc(enc->cur+1, STR_QNAN)
2127             || strEQc(enc->cur+1, STR_NAN2)
2128             || strEQc(enc->cur+1, STR_QNAN2)))
2129             # else
2130             (UNLIKELY(strEQc(enc->cur+1, STR_NAN)
2131             || strEQc(enc->cur+1, STR_QNAN)))
2132             # endif
2133             #else
2134 22 100         (UNLIKELY(strEQc(enc->cur+1, STR_NAN)))
2135             #endif
2136 6           inf_or_nan = 3;
2137             }
2138 134 100         if (UNLIKELY(inf_or_nan)) {
2139             is_inf_or_nan:
2140 20 100         if (enc->json.infnan_mode == 0) {
2141 5           strncpy(enc->cur, "null\0", 5);
2142             }
2143 15 100         else if (enc->json.infnan_mode == 1) {
2144 5           const int l = strlen(enc->cur);
2145 5           memmove(enc->cur+1, enc->cur, l);
2146 5           *enc->cur = '"';
2147 5           *(enc->cur + l+1) = '"';
2148 5           *(enc->cur + l+2) = 0;
2149             }
2150 10 100         else if (enc->json.infnan_mode == 3) {
2151 5 100         if (inf_or_nan == 1)
2152 1           strncpy(enc->cur, "\"inf\"\0", 6);
2153 4 100         else if (inf_or_nan == 2)
2154 1           strncpy(enc->cur, "\"-inf\"\0", 7);
2155 3 50         else if (inf_or_nan == 3)
2156 5           strncpy(enc->cur, "\"nan\"\0", 6);
2157             }
2158 5 50         else if (enc->json.infnan_mode != 2) {
2159 0           croak ("invalid stringify_infnan mode %c. Must be 0, 1, 2 or 3",
2160 0           enc->json.infnan_mode);
2161             }
2162             }
2163              
2164             }
2165              
2166 164 100         if (!force_conversion && SvPOKp (sv) && !strEQ(enc->cur, SvPVX (sv))) {
    100          
    100          
2167 3           char *str = SvPVX (sv);
2168 3           STRLEN len = SvCUR (sv);
2169 3           enc->cur = savecur;
2170 3           enc->end = saveend;
2171 3           encode_ch (aTHX_ enc, '"');
2172 3           encode_str (aTHX_ enc, str, len, SvUTF8 (sv));
2173 3           encode_ch (aTHX_ enc, '"');
2174 3           *enc->cur = 0;
2175             }
2176             else {
2177             NV intpart;
2178 243 100         if (!( inf_or_nan || (had_nokp && Perl_modf(SvNVX(sv), &intpart)) || (!force_conversion && SvIOK(sv))
    100          
    100          
    100          
    100          
    100          
2179 108 100         || strchr(enc->cur,'e') || strchr(enc->cur,'E') || strchr(savecur,'.')
    50          
2180             #if PERL_VERSION < 10
2181             /* !!1 with 5.8 */
2182             || (SvPOKp(sv) && strEQc(SvPVX(sv), "1")
2183             && SvNVX(sv) == 1.0) /* yes */
2184             #endif
2185             ) )
2186             {
2187 73           char *tempend = enc->cur + strlen(enc->cur);
2188 73           strncpy(tempend, ".0\0", 3);
2189             }
2190 161           enc->cur += strlen (enc->cur);
2191             }
2192             }
2193 2472 100         else if (type == JSON_TYPE_INT)
2194             {
2195             char *savecur, *saveend;
2196             /* we assume we can always read an IV as a UV and vice versa */
2197             /* we assume two's complement */
2198             /* we assume no aliasing issues in the union */
2199 1014           UV uv = 0;
2200 1014           IV iv = 0;
2201 1014           int is_neg = 0;
2202              
2203 1014 100         if (UNLIKELY (SvROK (sv) && SvOBJECT (SvRV (sv))) && (enc->json.flags & F_ALLOW_BIGNUM))
    50          
    100          
2204             {
2205 16           HV *stash = SvSTASH (SvRV (sv));
2206 16 50         int is_bigint = (stash && stash == gv_stashpvs ("Math::BigInt", 0));
    100          
2207 16 50         int is_bigfloat = (stash && stash == gv_stashpvs ("Math::BigFloat", 0));
    100          
2208              
2209 16 100         if (is_bigint || is_bigfloat)
    50          
2210             {
2211             STRLEN len;
2212             char *str;
2213              
2214 16 100         if (is_bigfloat)
2215             {
2216 8           dSP;
2217             int is_negative;
2218              
2219 8           ENTER;
2220 8           SAVETMPS;
2221              
2222 8 50         PUSHMARK (SP);
2223 8 50         XPUSHs (sv);
2224 8           PUTBACK;
2225              
2226 8           call_method ("is_negative", G_SCALAR);
2227              
2228 8           SPAGAIN;
2229 8 50         is_negative = SvTRUEx (POPs);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
2230 8           PUTBACK;
2231              
2232 8 50         PUSHMARK (SP);
2233 8 50         XPUSHs (sv);
2234 8           PUTBACK;
2235              
2236             /* This bceil/bfloor logic can be replaced by just one "bint" method call
2237             * but it is not supported by older Math::BigFloat versions.
2238             * Older Math::BigFloat versions have also "as_number" method which should
2239             * do same thing as "bint" method but it is broken and loose precision.
2240             * This bceil/bfloor logic needs Math::BigFloat 1.16 which is in Perl 5.8.0. */
2241 8 100         call_method (is_negative ? "bceil" : "bfloor", G_SCALAR);
2242              
2243 8           SPAGAIN;
2244 8           sv = POPs;
2245 8           PUTBACK;
2246             }
2247              
2248 16 50         str = SvPV_nomg (sv, len);
2249 16 50         if (UNLIKELY (str[0] == '+'))
2250             {
2251 0           str++;
2252 0           len--;
2253             }
2254              
2255 16 100         if (UNLIKELY (strEQc (str, "NaN") || strEQc (str, "nan")))
    50          
2256             {
2257 2           encode_const_str (aTHX_ enc, "0", 1, 0);
2258             }
2259 14 100         else if (UNLIKELY (strEQc (str, "inf")))
2260             {
2261 2           need (aTHX_ enc, IVUV_MAXCHARS);
2262 2           savecur = enc->cur;
2263 2           saveend = enc->end;
2264 2           enc->cur += snprintf (enc->cur, IVUV_MAXCHARS, "%" UVuf, UV_MAX);
2265             }
2266 12 100         else if (UNLIKELY (strEQc (str, "-inf")))
2267             {
2268 2           need (aTHX_ enc, IVUV_MAXCHARS);
2269 2           savecur = enc->cur;
2270 2           saveend = enc->end;
2271 2           enc->cur += snprintf (enc->cur, IVUV_MAXCHARS, "%" IVdf, IV_MIN);
2272             }
2273             else
2274             {
2275 10           need (aTHX_ enc, len+1);
2276 10           savecur = enc->cur;
2277 10           saveend = enc->end;
2278 10           memcpy (enc->cur, str, len);
2279 10           enc->cur += len;
2280 10           *enc->cur = '\0';
2281             }
2282              
2283 16 100         if (is_bigfloat)
2284             {
2285 8 50         FREETMPS;
2286 8           LEAVE;
2287             }
2288              
2289 16           return;
2290             }
2291             }
2292              
2293 998 100         if (SvIOK (sv))
2294             {
2295 915           is_neg = !SvIsUV (sv);
2296 915           iv = SvIVX (sv);
2297 915           uv = SvUVX (sv);
2298             }
2299 83 100         else if (SvPOKp (sv))
2300             {
2301 56           int numtype = grok_number (SvPVX (sv), SvCUR (sv), &uv);
2302 56 100         if (numtype & IS_NUMBER_IN_UV)
2303             {
2304 42 100         if (numtype & IS_NUMBER_NEG)
2305             {
2306 10           is_neg = 1;
2307 10 100         if (LIKELY(uv <= (UV)(IV_MAX) + 1))
2308 3           iv = -(IV)uv;
2309             else
2310             {
2311 7           iv = IV_MIN; /* underflow, but F_ALLOW_BIGNUM can handle this */
2312 7           numtype |= IS_NUMBER_GREATER_THAN_UV_MAX;
2313             }
2314 10           uv = (UV)iv;
2315             }
2316             else
2317 42           iv = (IV)uv;
2318             }
2319 14 100         else if (UNLIKELY (numtype & IS_NUMBER_INFINITY))
2320             {
2321 2           is_neg = (numtype & IS_NUMBER_NEG);
2322 2 100         if (is_neg)
2323             {
2324 1           iv = IV_MIN;
2325 1           uv = (UV)iv;
2326             }
2327             else
2328             {
2329 1           uv = UV_MAX;
2330 1           iv = (IV)uv;
2331             }
2332             }
2333              
2334 56 100         if ((numtype & (IS_NUMBER_GREATER_THAN_UV_MAX|IS_NUMBER_NOT_INT)) && (enc->json.flags & F_ALLOW_BIGNUM))
    100          
2335             {
2336             STRLEN len;
2337             char *str;
2338             SV *pv;
2339             SV *errsv;
2340              
2341 12 100         if (numtype & IS_NUMBER_NOT_INT)
2342 6           pv = newSVpvs ("my $obj; require Math::BigFloat && ($obj = Math::BigFloat->new(\"");
2343             else
2344 6           pv = newSVpvs ("require Math::BigInt && return Math::BigInt->new(\"");
2345              
2346 12           sv_catpvn (pv, SvPVX (sv), SvCUR (sv));
2347              
2348 12 100         if (numtype & IS_NUMBER_NOT_INT)
2349             /* This bceil/bfloor logic can be replaced by just one "bint" method call
2350             * but it is not supported by older Math::BigFloat versions.
2351             * Older Math::BigFloat versions have also "as_number" method which should
2352             * do same thing as "bint" method but it is broken and loose precision.
2353             * This bceil/bfloor logic needs Math::BigFloat 1.16 which is in Perl 5.8.0. */
2354 6           sv_catpvs (pv, "\")) && ($obj->is_negative ? $obj->bceil : $obj->bfloor);");
2355             else
2356 6           sv_catpvs (pv, "\");");
2357              
2358 12           eval_sv (pv, G_SCALAR);
2359 12           SvREFCNT_dec (pv);
2360              
2361             /* rethrow current error */
2362 12 50         errsv = ERRSV;
2363 12 50         if (SvROK (errsv))
2364 0           croak (NULL);
2365 12 50         else if (SvTRUE (errsv))
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
2366 0           croak ("%" SVf, SVfARG (errsv));
2367              
2368             {
2369 12           dSP;
2370 12           pv = POPs;
2371 12           PUTBACK;
2372             }
2373              
2374 12 50         str = SvPV (pv, len);
2375 12 50         if (UNLIKELY (str[0] == '+'))
2376             {
2377 0           str++;
2378 0           len--;
2379             }
2380 12           need (aTHX_ enc, len+1);
2381 12           savecur = enc->cur;
2382 12           saveend = enc->end;
2383 12           memcpy (enc->cur, str, len);
2384 12           enc->cur += len;
2385 12           *enc->cur = '\0';
2386              
2387 12           return;
2388             }
2389 44 100         else if (!(numtype & (IS_NUMBER_IN_UV|IS_NUMBER_INFINITY|IS_NUMBER_NAN)))
2390             {
2391 44           sv_to_ivuv (aTHX_ sv, &is_neg, &iv, &uv);
2392             }
2393             }
2394             else
2395             {
2396             #if PERL_VERSION < 8
2397             /* SvIV() and SvUV() in Perl 5.6 does not handle Inf and NaN in NV slot */
2398             # if defined(USE_QUADMATH) && defined(HAVE_ISINFL) && defined(HAVE_ISNANL)
2399             if (SvNOKp (sv) && UNLIKELY (isinfl (SvNVX (sv))))
2400             # else
2401             if (SvNOKp (sv) && UNLIKELY (isinf (SvNVX (sv))))
2402             # endif
2403             {
2404             if (SvNVX (sv) < 0)
2405             {
2406             is_neg = 1;
2407             iv = IV_MIN;
2408             uv = (UV)iv;
2409             }
2410             else
2411             {
2412             uv = UV_MAX;
2413             iv = (IV)uv;
2414             }
2415             }
2416             # if defined(USE_QUADMATH) && defined(HAVE_ISINFL) && defined(HAVE_ISNANL)
2417             else if (!SvNOKp (sv) || LIKELY (!isnanl (SvNVX (sv))))
2418             # else
2419             else if (!SvNOKp (sv) || LIKELY (!isnan (SvNVX (sv))))
2420             # endif
2421             #endif
2422 27           sv_to_ivuv (aTHX_ sv, &is_neg, &iv, &uv);
2423             }
2424 986 100         if (is_neg ? iv <= 59000 && iv >= -59000
    100          
    100          
    100          
2425             : uv <= 59000)
2426             {
2427             /* optimise the "small number case" */
2428             /* code will likely be branchless and use only a single multiplication */
2429             /* works for numbers up to 59074 */
2430 957           I32 i = iv;
2431             U32 u;
2432 957           char digit, nz = 0;
2433              
2434 957           need (aTHX_ enc, 6);
2435 957           savecur = enc->cur;
2436 957           saveend = enc->end;
2437              
2438 957 100         *enc->cur = '-'; enc->cur += i < 0 ? 1 : 0;
2439 957           u = i < 0 ? -i : i;
2440              
2441             /* convert to 4.28 fixed-point representation */
2442 957           u = u * ((0xfffffff + 10000) / 10000); /* 10**5, 5 fractional digits */
2443              
2444             /* now output digit by digit, each time masking out the integer part */
2445             /* and multiplying by 5 while moving the decimal point one to the right, */
2446             /* resulting in a net multiplication by 10. */
2447             /* we always write the digit to memory but conditionally increment */
2448             /* the pointer, to enable the use of conditional move instructions. */
2449 957 50         digit = u >> 28; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0xfffffffUL) * 5;
    100          
2450 957 100         digit = u >> 27; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x7ffffffUL) * 5;
    100          
2451 957 100         digit = u >> 26; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x3ffffffUL) * 5;
    100          
2452 957 100         digit = u >> 25; *enc->cur = digit + '0'; enc->cur += (nz = nz || digit); u = (u & 0x1ffffffUL) * 5;
    100          
2453 957           digit = u >> 24; *enc->cur = digit + '0'; enc->cur += 1; /* correctly generate '0' */
2454 957           *enc->cur = 0;
2455             }
2456             else
2457             {
2458             /* large integer, use the (rather slow) snprintf way. */
2459 29           need (aTHX_ enc, IVUV_MAXCHARS);
2460 29           savecur = enc->cur;
2461 29           saveend = enc->end;
2462 29           enc->cur +=
2463 29           !is_neg
2464 16           ? snprintf (enc->cur, IVUV_MAXCHARS, "%" UVuf, uv)
2465 29 100         : snprintf (enc->cur, IVUV_MAXCHARS, "%" IVdf, iv);
2466             }
2467              
2468 986 100         if (!force_conversion && SvPOKp (sv) && !strEQ(savecur, SvPVX (sv))) {
    100          
    100          
2469 1           char *str = SvPVX (sv);
2470 1           STRLEN len = SvCUR (sv);
2471 1           enc->cur = savecur;
2472 1           enc->end = saveend;
2473 1           encode_ch (aTHX_ enc, '"');
2474 1           encode_str (aTHX_ enc, str, len, SvUTF8 (sv));
2475 1           encode_ch (aTHX_ enc, '"');
2476 1014           *enc->cur = 0;
2477             }
2478             }
2479 1458 100         else if (type == JSON_TYPE_STRING)
2480             {
2481 1378 50         if (UNLIKELY (sv == &PL_sv_yes))
2482             {
2483 0           encode_ch (aTHX_ enc, '"');
2484 0           encode_const_str (aTHX_ enc, "true", 4, 0);
2485 0           encode_ch (aTHX_ enc, '"');
2486             }
2487 1378 50         else if (UNLIKELY (sv == &PL_sv_no))
2488             {
2489 0           encode_ch (aTHX_ enc, '"');
2490 0           encode_const_str (aTHX_ enc, "false", 5, 0);
2491 0           encode_ch (aTHX_ enc, '"');
2492             }
2493 1378 100         else if (!UNLIKELY (SvROK(sv) && SvOBJECT (SvRV(sv))) || !encode_bool_obj (aTHX_ enc, SvRV(sv), 0, 1))
    50          
    50          
2494             {
2495             char *str;
2496             STRLEN len;
2497 1375 100         if (SvPOKp (sv))
2498             {
2499 1355           str = SvPVX (sv);
2500 1355           len = SvCUR (sv);
2501             }
2502             else
2503             {
2504 20 50         str = SvPV_nomg (sv, len);
2505             }
2506 1375           encode_ch (aTHX_ enc, '"');
2507 1375           encode_str (aTHX_ enc, str, len, SvUTF8 (sv));
2508 1378           encode_ch (aTHX_ enc, '"');
2509             }
2510             }
2511 80 50         else if (process_ref)
2512 80           encode_rv (aTHX_ enc, sv);
2513 0 0         else if (enc->json.flags & F_ALLOW_UNKNOWN)
2514 0           encode_const_str (aTHX_ enc, "null", 4, 0);
2515             else
2516 0 0         croak ("encountered perl type (%s,0x%x) that JSON cannot handle, check your input data",
2517 0           SvPV_nolen (sv), (unsigned int)SvFLAGS (sv));
2518             }
2519              
2520             static SV *
2521 1355           encode_json (pTHX_ SV *scalar, JSON *json, SV *typesv)
2522             {
2523             enc_t enc;
2524              
2525 1355 100         if (!(json->flags & F_ALLOW_NONREF) && json_nonref (aTHX_ scalar))
    50          
2526 0           croak ("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)");
2527              
2528 1355           enc.json = *json;
2529 1355           enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE));
2530 1355           enc.cur = SvPVX (enc.sv);
2531 1355           enc.end = SvEND (enc.sv);
2532 1355           enc.indent = 0;
2533 2710           enc.limit = enc.json.flags & F_ASCII ? 0x000080UL
2534 2598 100         : enc.json.flags & F_BINARY ? 0x000080UL
2535 2283 100         : enc.json.flags & F_LATIN1 ? 0x000100UL
2536 1040 100         : 0x110000UL;
2537              
2538 1355           SvPOK_only (enc.sv);
2539 1355           encode_sv (aTHX_ &enc, scalar, typesv);
2540 1326           encode_nl (aTHX_ &enc);
2541              
2542 1326           SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv));
2543 1326           *SvEND (enc.sv) = 0; /* many xs functions expect a trailing 0 for text strings */
2544              
2545 1326 100         if (!(enc.json.flags & (F_ASCII | F_LATIN1 | F_BINARY | F_UTF8)))
2546 677           SvUTF8_on (enc.sv);
2547              
2548 1326 100         if (enc.json.flags & F_SHRINK)
2549 200           shrink (aTHX_ enc.sv);
2550              
2551 1326           return enc.sv;
2552             }
2553              
2554             /*/////////////////////////////////////////////////////////////////////////// */
2555             /* decoder */
2556              
2557             /* structure used for decoding JSON */
2558             typedef struct
2559             {
2560             char *cur; /* current parser pointer */
2561             char *end; /* end of input string */
2562             const char *err; /* parse error, if != 0 */
2563             JSON json;
2564             U32 depth; /* recursion depth */
2565             U32 maxdepth; /* recursion depth limit */
2566             } dec_t;
2567              
2568             INLINE void
2569 9           decode_comment (dec_t *dec)
2570             {
2571             /* only '#'-style comments allowed a.t.m. */
2572              
2573 47 50         while (*dec->cur && *dec->cur != 0x0a && *dec->cur != 0x0d)
    100          
    50          
2574 38           ++dec->cur;
2575 9           }
2576              
2577             INLINE void
2578 39114           decode_ws (dec_t *dec)
2579             {
2580             for (;;)
2581             {
2582 118670           char ch = *dec->cur;
2583              
2584 118670 100         if (ch > 0x20)
2585             {
2586 38262 100         if (UNLIKELY(ch == '#'))
2587             {
2588 11 100         if (dec->json.flags & F_RELAXED)
2589 9           decode_comment (dec);
2590             else
2591 2           break;
2592             }
2593             else
2594 38251           break;
2595             }
2596 80408 100         else if (ch != 0x20 && ch != 0x0a && ch != 0x0d && ch != 0x09)
    100          
    50          
    100          
2597 861           break; /* parse error, but let higher level handle it, gives better error messages */
2598              
2599 79556           ++dec->cur;
2600 79556           }
2601 39114           }
2602              
2603             #define ERR(reason) SB dec->err = reason; goto fail; SE
2604              
2605             #define EXPECT_CH(ch) SB \
2606             if (*dec->cur != ch) \
2607             ERR (# ch " expected"); \
2608             ++dec->cur; \
2609             SE
2610              
2611             #define DEC_INC_DEPTH if (++dec->depth > dec->json.max_depth) ERR (ERR_NESTING_EXCEEDED)
2612             #define DEC_DEC_DEPTH --dec->depth
2613              
2614             static SV *decode_sv (pTHX_ dec_t *dec, SV *typesv);
2615              
2616             /* #regen code
2617             my $i;
2618             for ($i = 0; $i < 256; ++$i){
2619             print
2620             " $i >= '0' && $i <= '9' ? $i - '0' : $i >= 'a' && $i <= 'f' ? $i - 'a' + 10
2621             : $i >= 'A' && $i <= 'F' ? $i - 'A' + 10 : -1 ,
2622             ";
2623             }
2624             */
2625             static const signed char decode_hexdigit[256] = {
2626             0 >= '0' && 0 <= '9' ? 0 - '0' : 0 >= 'a' && 0 <= 'f' ? 0 - 'a' + 10
2627             : 0 >= 'A' && 0 <= 'F' ? 0 - 'A' + 10 : -1 ,
2628             1 >= '0' && 1 <= '9' ? 1 - '0' : 1 >= 'a' && 1 <= 'f' ? 1 - 'a' + 10
2629             : 1 >= 'A' && 1 <= 'F' ? 1 - 'A' + 10 : -1 ,
2630             2 >= '0' && 2 <= '9' ? 2 - '0' : 2 >= 'a' && 2 <= 'f' ? 2 - 'a' + 10
2631             : 2 >= 'A' && 2 <= 'F' ? 2 - 'A' + 10 : -1 ,
2632             3 >= '0' && 3 <= '9' ? 3 - '0' : 3 >= 'a' && 3 <= 'f' ? 3 - 'a' + 10
2633             : 3 >= 'A' && 3 <= 'F' ? 3 - 'A' + 10 : -1 ,
2634             4 >= '0' && 4 <= '9' ? 4 - '0' : 4 >= 'a' && 4 <= 'f' ? 4 - 'a' + 10
2635             : 4 >= 'A' && 4 <= 'F' ? 4 - 'A' + 10 : -1 ,
2636             5 >= '0' && 5 <= '9' ? 5 - '0' : 5 >= 'a' && 5 <= 'f' ? 5 - 'a' + 10
2637             : 5 >= 'A' && 5 <= 'F' ? 5 - 'A' + 10 : -1 ,
2638             6 >= '0' && 6 <= '9' ? 6 - '0' : 6 >= 'a' && 6 <= 'f' ? 6 - 'a' + 10
2639             : 6 >= 'A' && 6 <= 'F' ? 6 - 'A' + 10 : -1 ,
2640             7 >= '0' && 7 <= '9' ? 7 - '0' : 7 >= 'a' && 7 <= 'f' ? 7 - 'a' + 10
2641             : 7 >= 'A' && 7 <= 'F' ? 7 - 'A' + 10 : -1 ,
2642             8 >= '0' && 8 <= '9' ? 8 - '0' : 8 >= 'a' && 8 <= 'f' ? 8 - 'a' + 10
2643             : 8 >= 'A' && 8 <= 'F' ? 8 - 'A' + 10 : -1 ,
2644             9 >= '0' && 9 <= '9' ? 9 - '0' : 9 >= 'a' && 9 <= 'f' ? 9 - 'a' + 10
2645             : 9 >= 'A' && 9 <= 'F' ? 9 - 'A' + 10 : -1 ,
2646             10 >= '0' && 10 <= '9' ? 10 - '0' : 10 >= 'a' && 10 <= 'f' ? 10 - 'a' + 10
2647             : 10 >= 'A' && 10 <= 'F' ? 10 - 'A' + 10 : -1 ,
2648             11 >= '0' && 11 <= '9' ? 11 - '0' : 11 >= 'a' && 11 <= 'f' ? 11 - 'a' + 10
2649             : 11 >= 'A' && 11 <= 'F' ? 11 - 'A' + 10 : -1 ,
2650             12 >= '0' && 12 <= '9' ? 12 - '0' : 12 >= 'a' && 12 <= 'f' ? 12 - 'a' + 10
2651             : 12 >= 'A' && 12 <= 'F' ? 12 - 'A' + 10 : -1 ,
2652             13 >= '0' && 13 <= '9' ? 13 - '0' : 13 >= 'a' && 13 <= 'f' ? 13 - 'a' + 10
2653             : 13 >= 'A' && 13 <= 'F' ? 13 - 'A' + 10 : -1 ,
2654             14 >= '0' && 14 <= '9' ? 14 - '0' : 14 >= 'a' && 14 <= 'f' ? 14 - 'a' + 10
2655             : 14 >= 'A' && 14 <= 'F' ? 14 - 'A' + 10 : -1 ,
2656             15 >= '0' && 15 <= '9' ? 15 - '0' : 15 >= 'a' && 15 <= 'f' ? 15 - 'a' + 10
2657             : 15 >= 'A' && 15 <= 'F' ? 15 - 'A' + 10 : -1 ,
2658             16 >= '0' && 16 <= '9' ? 16 - '0' : 16 >= 'a' && 16 <= 'f' ? 16 - 'a' + 10
2659             : 16 >= 'A' && 16 <= 'F' ? 16 - 'A' + 10 : -1 ,
2660             17 >= '0' && 17 <= '9' ? 17 - '0' : 17 >= 'a' && 17 <= 'f' ? 17 - 'a' + 10
2661             : 17 >= 'A' && 17 <= 'F' ? 17 - 'A' + 10 : -1 ,
2662             18 >= '0' && 18 <= '9' ? 18 - '0' : 18 >= 'a' && 18 <= 'f' ? 18 - 'a' + 10
2663             : 18 >= 'A' && 18 <= 'F' ? 18 - 'A' + 10 : -1 ,
2664             19 >= '0' && 19 <= '9' ? 19 - '0' : 19 >= 'a' && 19 <= 'f' ? 19 - 'a' + 10
2665             : 19 >= 'A' && 19 <= 'F' ? 19 - 'A' + 10 : -1 ,
2666             20 >= '0' && 20 <= '9' ? 20 - '0' : 20 >= 'a' && 20 <= 'f' ? 20 - 'a' + 10
2667             : 20 >= 'A' && 20 <= 'F' ? 20 - 'A' + 10 : -1 ,
2668             21 >= '0' && 21 <= '9' ? 21 - '0' : 21 >= 'a' && 21 <= 'f' ? 21 - 'a' + 10
2669             : 21 >= 'A' && 21 <= 'F' ? 21 - 'A' + 10 : -1 ,
2670             22 >= '0' && 22 <= '9' ? 22 - '0' : 22 >= 'a' && 22 <= 'f' ? 22 - 'a' + 10
2671             : 22 >= 'A' && 22 <= 'F' ? 22 - 'A' + 10 : -1 ,
2672             23 >= '0' && 23 <= '9' ? 23 - '0' : 23 >= 'a' && 23 <= 'f' ? 23 - 'a' + 10
2673             : 23 >= 'A' && 23 <= 'F' ? 23 - 'A' + 10 : -1 ,
2674             24 >= '0' && 24 <= '9' ? 24 - '0' : 24 >= 'a' && 24 <= 'f' ? 24 - 'a' + 10
2675             : 24 >= 'A' && 24 <= 'F' ? 24 - 'A' + 10 : -1 ,
2676             25 >= '0' && 25 <= '9' ? 25 - '0' : 25 >= 'a' && 25 <= 'f' ? 25 - 'a' + 10
2677             : 25 >= 'A' && 25 <= 'F' ? 25 - 'A' + 10 : -1 ,
2678             26 >= '0' && 26 <= '9' ? 26 - '0' : 26 >= 'a' && 26 <= 'f' ? 26 - 'a' + 10
2679             : 26 >= 'A' && 26 <= 'F' ? 26 - 'A' + 10 : -1 ,
2680             27 >= '0' && 27 <= '9' ? 27 - '0' : 27 >= 'a' && 27 <= 'f' ? 27 - 'a' + 10
2681             : 27 >= 'A' && 27 <= 'F' ? 27 - 'A' + 10 : -1 ,
2682             28 >= '0' && 28 <= '9' ? 28 - '0' : 28 >= 'a' && 28 <= 'f' ? 28 - 'a' + 10
2683             : 28 >= 'A' && 28 <= 'F' ? 28 - 'A' + 10 : -1 ,
2684             29 >= '0' && 29 <= '9' ? 29 - '0' : 29 >= 'a' && 29 <= 'f' ? 29 - 'a' + 10
2685             : 29 >= 'A' && 29 <= 'F' ? 29 - 'A' + 10 : -1 ,
2686             30 >= '0' && 30 <= '9' ? 30 - '0' : 30 >= 'a' && 30 <= 'f' ? 30 - 'a' + 10
2687             : 30 >= 'A' && 30 <= 'F' ? 30 - 'A' + 10 : -1 ,
2688             31 >= '0' && 31 <= '9' ? 31 - '0' : 31 >= 'a' && 31 <= 'f' ? 31 - 'a' + 10
2689             : 31 >= 'A' && 31 <= 'F' ? 31 - 'A' + 10 : -1 ,
2690             32 >= '0' && 32 <= '9' ? 32 - '0' : 32 >= 'a' && 32 <= 'f' ? 32 - 'a' + 10
2691             : 32 >= 'A' && 32 <= 'F' ? 32 - 'A' + 10 : -1 ,
2692             33 >= '0' && 33 <= '9' ? 33 - '0' : 33 >= 'a' && 33 <= 'f' ? 33 - 'a' + 10
2693             : 33 >= 'A' && 33 <= 'F' ? 33 - 'A' + 10 : -1 ,
2694             34 >= '0' && 34 <= '9' ? 34 - '0' : 34 >= 'a' && 34 <= 'f' ? 34 - 'a' + 10
2695             : 34 >= 'A' && 34 <= 'F' ? 34 - 'A' + 10 : -1 ,
2696             35 >= '0' && 35 <= '9' ? 35 - '0' : 35 >= 'a' && 35 <= 'f' ? 35 - 'a' + 10
2697             : 35 >= 'A' && 35 <= 'F' ? 35 - 'A' + 10 : -1 ,
2698             36 >= '0' && 36 <= '9' ? 36 - '0' : 36 >= 'a' && 36 <= 'f' ? 36 - 'a' + 10
2699             : 36 >= 'A' && 36 <= 'F' ? 36 - 'A' + 10 : -1 ,
2700             37 >= '0' && 37 <= '9' ? 37 - '0' : 37 >= 'a' && 37 <= 'f' ? 37 - 'a' + 10
2701             : 37 >= 'A' && 37 <= 'F' ? 37 - 'A' + 10 : -1 ,
2702             38 >= '0' && 38 <= '9' ? 38 - '0' : 38 >= 'a' && 38 <= 'f' ? 38 - 'a' + 10
2703             : 38 >= 'A' && 38 <= 'F' ? 38 - 'A' + 10 : -1 ,
2704             39 >= '0' && 39 <= '9' ? 39 - '0' : 39 >= 'a' && 39 <= 'f' ? 39 - 'a' + 10
2705             : 39 >= 'A' && 39 <= 'F' ? 39 - 'A' + 10 : -1 ,
2706             40 >= '0' && 40 <= '9' ? 40 - '0' : 40 >= 'a' && 40 <= 'f' ? 40 - 'a' + 10
2707             : 40 >= 'A' && 40 <= 'F' ? 40 - 'A' + 10 : -1 ,
2708             41 >= '0' && 41 <= '9' ? 41 - '0' : 41 >= 'a' && 41 <= 'f' ? 41 - 'a' + 10
2709             : 41 >= 'A' && 41 <= 'F' ? 41 - 'A' + 10 : -1 ,
2710             42 >= '0' && 42 <= '9' ? 42 - '0' : 42 >= 'a' && 42 <= 'f' ? 42 - 'a' + 10
2711             : 42 >= 'A' && 42 <= 'F' ? 42 - 'A' + 10 : -1 ,
2712             43 >= '0' && 43 <= '9' ? 43 - '0' : 43 >= 'a' && 43 <= 'f' ? 43 - 'a' + 10
2713             : 43 >= 'A' && 43 <= 'F' ? 43 - 'A' + 10 : -1 ,
2714             44 >= '0' && 44 <= '9' ? 44 - '0' : 44 >= 'a' && 44 <= 'f' ? 44 - 'a' + 10
2715             : 44 >= 'A' && 44 <= 'F' ? 44 - 'A' + 10 : -1 ,
2716             45 >= '0' && 45 <= '9' ? 45 - '0' : 45 >= 'a' && 45 <= 'f' ? 45 - 'a' + 10
2717             : 45 >= 'A' && 45 <= 'F' ? 45 - 'A' + 10 : -1 ,
2718             46 >= '0' && 46 <= '9' ? 46 - '0' : 46 >= 'a' && 46 <= 'f' ? 46 - 'a' + 10
2719             : 46 >= 'A' && 46 <= 'F' ? 46 - 'A' + 10 : -1 ,
2720             47 >= '0' && 47 <= '9' ? 47 - '0' : 47 >= 'a' && 47 <= 'f' ? 47 - 'a' + 10
2721             : 47 >= 'A' && 47 <= 'F' ? 47 - 'A' + 10 : -1 ,
2722             48 >= '0' && 48 <= '9' ? 48 - '0' : 48 >= 'a' && 48 <= 'f' ? 48 - 'a' + 10
2723             : 48 >= 'A' && 48 <= 'F' ? 48 - 'A' + 10 : -1 ,
2724             49 >= '0' && 49 <= '9' ? 49 - '0' : 49 >= 'a' && 49 <= 'f' ? 49 - 'a' + 10
2725             : 49 >= 'A' && 49 <= 'F' ? 49 - 'A' + 10 : -1 ,
2726             50 >= '0' && 50 <= '9' ? 50 - '0' : 50 >= 'a' && 50 <= 'f' ? 50 - 'a' + 10
2727             : 50 >= 'A' && 50 <= 'F' ? 50 - 'A' + 10 : -1 ,
2728             51 >= '0' && 51 <= '9' ? 51 - '0' : 51 >= 'a' && 51 <= 'f' ? 51 - 'a' + 10
2729             : 51 >= 'A' && 51 <= 'F' ? 51 - 'A' + 10 : -1 ,
2730             52 >= '0' && 52 <= '9' ? 52 - '0' : 52 >= 'a' && 52 <= 'f' ? 52 - 'a' + 10
2731             : 52 >= 'A' && 52 <= 'F' ? 52 - 'A' + 10 : -1 ,
2732             53 >= '0' && 53 <= '9' ? 53 - '0' : 53 >= 'a' && 53 <= 'f' ? 53 - 'a' + 10
2733             : 53 >= 'A' && 53 <= 'F' ? 53 - 'A' + 10 : -1 ,
2734             54 >= '0' && 54 <= '9' ? 54 - '0' : 54 >= 'a' && 54 <= 'f' ? 54 - 'a' + 10
2735             : 54 >= 'A' && 54 <= 'F' ? 54 - 'A' + 10 : -1 ,
2736             55 >= '0' && 55 <= '9' ? 55 - '0' : 55 >= 'a' && 55 <= 'f' ? 55 - 'a' + 10
2737             : 55 >= 'A' && 55 <= 'F' ? 55 - 'A' + 10 : -1 ,
2738             56 >= '0' && 56 <= '9' ? 56 - '0' : 56 >= 'a' && 56 <= 'f' ? 56 - 'a' + 10
2739             : 56 >= 'A' && 56 <= 'F' ? 56 - 'A' + 10 : -1 ,
2740             57 >= '0' && 57 <= '9' ? 57 - '0' : 57 >= 'a' && 57 <= 'f' ? 57 - 'a' + 10
2741             : 57 >= 'A' && 57 <= 'F' ? 57 - 'A' + 10 : -1 ,
2742             58 >= '0' && 58 <= '9' ? 58 - '0' : 58 >= 'a' && 58 <= 'f' ? 58 - 'a' + 10
2743             : 58 >= 'A' && 58 <= 'F' ? 58 - 'A' + 10 : -1 ,
2744             59 >= '0' && 59 <= '9' ? 59 - '0' : 59 >= 'a' && 59 <= 'f' ? 59 - 'a' + 10
2745             : 59 >= 'A' && 59 <= 'F' ? 59 - 'A' + 10 : -1 ,
2746             60 >= '0' && 60 <= '9' ? 60 - '0' : 60 >= 'a' && 60 <= 'f' ? 60 - 'a' + 10
2747             : 60 >= 'A' && 60 <= 'F' ? 60 - 'A' + 10 : -1 ,
2748             61 >= '0' && 61 <= '9' ? 61 - '0' : 61 >= 'a' && 61 <= 'f' ? 61 - 'a' + 10
2749             : 61 >= 'A' && 61 <= 'F' ? 61 - 'A' + 10 : -1 ,
2750             62 >= '0' && 62 <= '9' ? 62 - '0' : 62 >= 'a' && 62 <= 'f' ? 62 - 'a' + 10
2751             : 62 >= 'A' && 62 <= 'F' ? 62 - 'A' + 10 : -1 ,
2752             63 >= '0' && 63 <= '9' ? 63 - '0' : 63 >= 'a' && 63 <= 'f' ? 63 - 'a' + 10
2753             : 63 >= 'A' && 63 <= 'F' ? 63 - 'A' + 10 : -1 ,
2754             64 >= '0' && 64 <= '9' ? 64 - '0' : 64 >= 'a' && 64 <= 'f' ? 64 - 'a' + 10
2755             : 64 >= 'A' && 64 <= 'F' ? 64 - 'A' + 10 : -1 ,
2756             65 >= '0' && 65 <= '9' ? 65 - '0' : 65 >= 'a' && 65 <= 'f' ? 65 - 'a' + 10
2757             : 65 >= 'A' && 65 <= 'F' ? 65 - 'A' + 10 : -1 ,
2758             66 >= '0' && 66 <= '9' ? 66 - '0' : 66 >= 'a' && 66 <= 'f' ? 66 - 'a' + 10
2759             : 66 >= 'A' && 66 <= 'F' ? 66 - 'A' + 10 : -1 ,
2760             67 >= '0' && 67 <= '9' ? 67 - '0' : 67 >= 'a' && 67 <= 'f' ? 67 - 'a' + 10
2761             : 67 >= 'A' && 67 <= 'F' ? 67 - 'A' + 10 : -1 ,
2762             68 >= '0' && 68 <= '9' ? 68 - '0' : 68 >= 'a' && 68 <= 'f' ? 68 - 'a' + 10
2763             : 68 >= 'A' && 68 <= 'F' ? 68 - 'A' + 10 : -1 ,
2764             69 >= '0' && 69 <= '9' ? 69 - '0' : 69 >= 'a' && 69 <= 'f' ? 69 - 'a' + 10
2765             : 69 >= 'A' && 69 <= 'F' ? 69 - 'A' + 10 : -1 ,
2766             70 >= '0' && 70 <= '9' ? 70 - '0' : 70 >= 'a' && 70 <= 'f' ? 70 - 'a' + 10
2767             : 70 >= 'A' && 70 <= 'F' ? 70 - 'A' + 10 : -1 ,
2768             71 >= '0' && 71 <= '9' ? 71 - '0' : 71 >= 'a' && 71 <= 'f' ? 71 - 'a' + 10
2769             : 71 >= 'A' && 71 <= 'F' ? 71 - 'A' + 10 : -1 ,
2770             72 >= '0' && 72 <= '9' ? 72 - '0' : 72 >= 'a' && 72 <= 'f' ? 72 - 'a' + 10
2771             : 72 >= 'A' && 72 <= 'F' ? 72 - 'A' + 10 : -1 ,
2772             73 >= '0' && 73 <= '9' ? 73 - '0' : 73 >= 'a' && 73 <= 'f' ? 73 - 'a' + 10
2773             : 73 >= 'A' && 73 <= 'F' ? 73 - 'A' + 10 : -1 ,
2774             74 >= '0' && 74 <= '9' ? 74 - '0' : 74 >= 'a' && 74 <= 'f' ? 74 - 'a' + 10
2775             : 74 >= 'A' && 74 <= 'F' ? 74 - 'A' + 10 : -1 ,
2776             75 >= '0' && 75 <= '9' ? 75 - '0' : 75 >= 'a' && 75 <= 'f' ? 75 - 'a' + 10
2777             : 75 >= 'A' && 75 <= 'F' ? 75 - 'A' + 10 : -1 ,
2778             76 >= '0' && 76 <= '9' ? 76 - '0' : 76 >= 'a' && 76 <= 'f' ? 76 - 'a' + 10
2779             : 76 >= 'A' && 76 <= 'F' ? 76 - 'A' + 10 : -1 ,
2780             77 >= '0' && 77 <= '9' ? 77 - '0' : 77 >= 'a' && 77 <= 'f' ? 77 - 'a' + 10
2781             : 77 >= 'A' && 77 <= 'F' ? 77 - 'A' + 10 : -1 ,
2782             78 >= '0' && 78 <= '9' ? 78 - '0' : 78 >= 'a' && 78 <= 'f' ? 78 - 'a' + 10
2783             : 78 >= 'A' && 78 <= 'F' ? 78 - 'A' + 10 : -1 ,
2784             79 >= '0' && 79 <= '9' ? 79 - '0' : 79 >= 'a' && 79 <= 'f' ? 79 - 'a' + 10
2785             : 79 >= 'A' && 79 <= 'F' ? 79 - 'A' + 10 : -1 ,
2786             80 >= '0' && 80 <= '9' ? 80 - '0' : 80 >= 'a' && 80 <= 'f' ? 80 - 'a' + 10
2787             : 80 >= 'A' && 80 <= 'F' ? 80 - 'A' + 10 : -1 ,
2788             81 >= '0' && 81 <= '9' ? 81 - '0' : 81 >= 'a' && 81 <= 'f' ? 81 - 'a' + 10
2789             : 81 >= 'A' && 81 <= 'F' ? 81 - 'A' + 10 : -1 ,
2790             82 >= '0' && 82 <= '9' ? 82 - '0' : 82 >= 'a' && 82 <= 'f' ? 82 - 'a' + 10
2791             : 82 >= 'A' && 82 <= 'F' ? 82 - 'A' + 10 : -1 ,
2792             83 >= '0' && 83 <= '9' ? 83 - '0' : 83 >= 'a' && 83 <= 'f' ? 83 - 'a' + 10
2793             : 83 >= 'A' && 83 <= 'F' ? 83 - 'A' + 10 : -1 ,
2794             84 >= '0' && 84 <= '9' ? 84 - '0' : 84 >= 'a' && 84 <= 'f' ? 84 - 'a' + 10
2795             : 84 >= 'A' && 84 <= 'F' ? 84 - 'A' + 10 : -1 ,
2796             85 >= '0' && 85 <= '9' ? 85 - '0' : 85 >= 'a' && 85 <= 'f' ? 85 - 'a' + 10
2797             : 85 >= 'A' && 85 <= 'F' ? 85 - 'A' + 10 : -1 ,
2798             86 >= '0' && 86 <= '9' ? 86 - '0' : 86 >= 'a' && 86 <= 'f' ? 86 - 'a' + 10
2799             : 86 >= 'A' && 86 <= 'F' ? 86 - 'A' + 10 : -1 ,
2800             87 >= '0' && 87 <= '9' ? 87 - '0' : 87 >= 'a' && 87 <= 'f' ? 87 - 'a' + 10
2801             : 87 >= 'A' && 87 <= 'F' ? 87 - 'A' + 10 : -1 ,
2802             88 >= '0' && 88 <= '9' ? 88 - '0' : 88 >= 'a' && 88 <= 'f' ? 88 - 'a' + 10
2803             : 88 >= 'A' && 88 <= 'F' ? 88 - 'A' + 10 : -1 ,
2804             89 >= '0' && 89 <= '9' ? 89 - '0' : 89 >= 'a' && 89 <= 'f' ? 89 - 'a' + 10
2805             : 89 >= 'A' && 89 <= 'F' ? 89 - 'A' + 10 : -1 ,
2806             90 >= '0' && 90 <= '9' ? 90 - '0' : 90 >= 'a' && 90 <= 'f' ? 90 - 'a' + 10
2807             : 90 >= 'A' && 90 <= 'F' ? 90 - 'A' + 10 : -1 ,
2808             91 >= '0' && 91 <= '9' ? 91 - '0' : 91 >= 'a' && 91 <= 'f' ? 91 - 'a' + 10
2809             : 91 >= 'A' && 91 <= 'F' ? 91 - 'A' + 10 : -1 ,
2810             92 >= '0' && 92 <= '9' ? 92 - '0' : 92 >= 'a' && 92 <= 'f' ? 92 - 'a' + 10
2811             : 92 >= 'A' && 92 <= 'F' ? 92 - 'A' + 10 : -1 ,
2812             93 >= '0' && 93 <= '9' ? 93 - '0' : 93 >= 'a' && 93 <= 'f' ? 93 - 'a' + 10
2813             : 93 >= 'A' && 93 <= 'F' ? 93 - 'A' + 10 : -1 ,
2814             94 >= '0' && 94 <= '9' ? 94 - '0' : 94 >= 'a' && 94 <= 'f' ? 94 - 'a' + 10
2815             : 94 >= 'A' && 94 <= 'F' ? 94 - 'A' + 10 : -1 ,
2816             95 >= '0' && 95 <= '9' ? 95 - '0' : 95 >= 'a' && 95 <= 'f' ? 95 - 'a' + 10
2817             : 95 >= 'A' && 95 <= 'F' ? 95 - 'A' + 10 : -1 ,
2818             96 >= '0' && 96 <= '9' ? 96 - '0' : 96 >= 'a' && 96 <= 'f' ? 96 - 'a' + 10
2819             : 96 >= 'A' && 96 <= 'F' ? 96 - 'A' + 10 : -1 ,
2820             97 >= '0' && 97 <= '9' ? 97 - '0' : 97 >= 'a' && 97 <= 'f' ? 97 - 'a' + 10
2821             : 97 >= 'A' && 97 <= 'F' ? 97 - 'A' + 10 : -1 ,
2822             98 >= '0' && 98 <= '9' ? 98 - '0' : 98 >= 'a' && 98 <= 'f' ? 98 - 'a' + 10
2823             : 98 >= 'A' && 98 <= 'F' ? 98 - 'A' + 10 : -1 ,
2824             99 >= '0' && 99 <= '9' ? 99 - '0' : 99 >= 'a' && 99 <= 'f' ? 99 - 'a' + 10
2825             : 99 >= 'A' && 99 <= 'F' ? 99 - 'A' + 10 : -1 ,
2826             100 >= '0' && 100 <= '9' ? 100 - '0' : 100 >= 'a' && 100 <= 'f' ? 100 - 'a' + 10
2827             : 100 >= 'A' && 100 <= 'F' ? 100 - 'A' + 10 : -1 ,
2828             101 >= '0' && 101 <= '9' ? 101 - '0' : 101 >= 'a' && 101 <= 'f' ? 101 - 'a' + 10
2829             : 101 >= 'A' && 101 <= 'F' ? 101 - 'A' + 10 : -1 ,
2830             102 >= '0' && 102 <= '9' ? 102 - '0' : 102 >= 'a' && 102 <= 'f' ? 102 - 'a' + 10
2831             : 102 >= 'A' && 102 <= 'F' ? 102 - 'A' + 10 : -1 ,
2832             103 >= '0' && 103 <= '9' ? 103 - '0' : 103 >= 'a' && 103 <= 'f' ? 103 - 'a' + 10
2833             : 103 >= 'A' && 103 <= 'F' ? 103 - 'A' + 10 : -1 ,
2834             104 >= '0' && 104 <= '9' ? 104 - '0' : 104 >= 'a' && 104 <= 'f' ? 104 - 'a' + 10
2835             : 104 >= 'A' && 104 <= 'F' ? 104 - 'A' + 10 : -1 ,
2836             105 >= '0' && 105 <= '9' ? 105 - '0' : 105 >= 'a' && 105 <= 'f' ? 105 - 'a' + 10
2837             : 105 >= 'A' && 105 <= 'F' ? 105 - 'A' + 10 : -1 ,
2838             106 >= '0' && 106 <= '9' ? 106 - '0' : 106 >= 'a' && 106 <= 'f' ? 106 - 'a' + 10
2839             : 106 >= 'A' && 106 <= 'F' ? 106 - 'A' + 10 : -1 ,
2840             107 >= '0' && 107 <= '9' ? 107 - '0' : 107 >= 'a' && 107 <= 'f' ? 107 - 'a' + 10
2841             : 107 >= 'A' && 107 <= 'F' ? 107 - 'A' + 10 : -1 ,
2842             108 >= '0' && 108 <= '9' ? 108 - '0' : 108 >= 'a' && 108 <= 'f' ? 108 - 'a' + 10
2843             : 108 >= 'A' && 108 <= 'F' ? 108 - 'A' + 10 : -1 ,
2844             109 >= '0' && 109 <= '9' ? 109 - '0' : 109 >= 'a' && 109 <= 'f' ? 109 - 'a' + 10
2845             : 109 >= 'A' && 109 <= 'F' ? 109 - 'A' + 10 : -1 ,
2846             110 >= '0' && 110 <= '9' ? 110 - '0' : 110 >= 'a' && 110 <= 'f' ? 110 - 'a' + 10
2847             : 110 >= 'A' && 110 <= 'F' ? 110 - 'A' + 10 : -1 ,
2848             111 >= '0' && 111 <= '9' ? 111 - '0' : 111 >= 'a' && 111 <= 'f' ? 111 - 'a' + 10
2849             : 111 >= 'A' && 111 <= 'F' ? 111 - 'A' + 10 : -1 ,
2850             112 >= '0' && 112 <= '9' ? 112 - '0' : 112 >= 'a' && 112 <= 'f' ? 112 - 'a' + 10
2851             : 112 >= 'A' && 112 <= 'F' ? 112 - 'A' + 10 : -1 ,
2852             113 >= '0' && 113 <= '9' ? 113 - '0' : 113 >= 'a' && 113 <= 'f' ? 113 - 'a' + 10
2853             : 113 >= 'A' && 113 <= 'F' ? 113 - 'A' + 10 : -1 ,
2854             114 >= '0' && 114 <= '9' ? 114 - '0' : 114 >= 'a' && 114 <= 'f' ? 114 - 'a' + 10
2855             : 114 >= 'A' && 114 <= 'F' ? 114 - 'A' + 10 : -1 ,
2856             115 >= '0' && 115 <= '9' ? 115 - '0' : 115 >= 'a' && 115 <= 'f' ? 115 - 'a' + 10
2857             : 115 >= 'A' && 115 <= 'F' ? 115 - 'A' + 10 : -1 ,
2858             116 >= '0' && 116 <= '9' ? 116 - '0' : 116 >= 'a' && 116 <= 'f' ? 116 - 'a' + 10
2859             : 116 >= 'A' && 116 <= 'F' ? 116 - 'A' + 10 : -1 ,
2860             117 >= '0' && 117 <= '9' ? 117 - '0' : 117 >= 'a' && 117 <= 'f' ? 117 - 'a' + 10
2861             : 117 >= 'A' && 117 <= 'F' ? 117 - 'A' + 10 : -1 ,
2862             118 >= '0' && 118 <= '9' ? 118 - '0' : 118 >= 'a' && 118 <= 'f' ? 118 - 'a' + 10
2863             : 118 >= 'A' && 118 <= 'F' ? 118 - 'A' + 10 : -1 ,
2864             119 >= '0' && 119 <= '9' ? 119 - '0' : 119 >= 'a' && 119 <= 'f' ? 119 - 'a' + 10
2865             : 119 >= 'A' && 119 <= 'F' ? 119 - 'A' + 10 : -1 ,
2866             120 >= '0' && 120 <= '9' ? 120 - '0' : 120 >= 'a' && 120 <= 'f' ? 120 - 'a' + 10
2867             : 120 >= 'A' && 120 <= 'F' ? 120 - 'A' + 10 : -1 ,
2868             121 >= '0' && 121 <= '9' ? 121 - '0' : 121 >= 'a' && 121 <= 'f' ? 121 - 'a' + 10
2869             : 121 >= 'A' && 121 <= 'F' ? 121 - 'A' + 10 : -1 ,
2870             122 >= '0' && 122 <= '9' ? 122 - '0' : 122 >= 'a' && 122 <= 'f' ? 122 - 'a' + 10
2871             : 122 >= 'A' && 122 <= 'F' ? 122 - 'A' + 10 : -1 ,
2872             123 >= '0' && 123 <= '9' ? 123 - '0' : 123 >= 'a' && 123 <= 'f' ? 123 - 'a' + 10
2873             : 123 >= 'A' && 123 <= 'F' ? 123 - 'A' + 10 : -1 ,
2874             124 >= '0' && 124 <= '9' ? 124 - '0' : 124 >= 'a' && 124 <= 'f' ? 124 - 'a' + 10
2875             : 124 >= 'A' && 124 <= 'F' ? 124 - 'A' + 10 : -1 ,
2876             125 >= '0' && 125 <= '9' ? 125 - '0' : 125 >= 'a' && 125 <= 'f' ? 125 - 'a' + 10
2877             : 125 >= 'A' && 125 <= 'F' ? 125 - 'A' + 10 : -1 ,
2878             126 >= '0' && 126 <= '9' ? 126 - '0' : 126 >= 'a' && 126 <= 'f' ? 126 - 'a' + 10
2879             : 126 >= 'A' && 126 <= 'F' ? 126 - 'A' + 10 : -1 ,
2880             127 >= '0' && 127 <= '9' ? 127 - '0' : 127 >= 'a' && 127 <= 'f' ? 127 - 'a' + 10
2881             : 127 >= 'A' && 127 <= 'F' ? 127 - 'A' + 10 : -1 ,
2882             128 >= '0' && 128 <= '9' ? 128 - '0' : 128 >= 'a' && 128 <= 'f' ? 128 - 'a' + 10
2883             : 128 >= 'A' && 128 <= 'F' ? 128 - 'A' + 10 : -1 ,
2884             129 >= '0' && 129 <= '9' ? 129 - '0' : 129 >= 'a' && 129 <= 'f' ? 129 - 'a' + 10
2885             : 129 >= 'A' && 129 <= 'F' ? 129 - 'A' + 10 : -1 ,
2886             130 >= '0' && 130 <= '9' ? 130 - '0' : 130 >= 'a' && 130 <= 'f' ? 130 - 'a' + 10
2887             : 130 >= 'A' && 130 <= 'F' ? 130 - 'A' + 10 : -1 ,
2888             131 >= '0' && 131 <= '9' ? 131 - '0' : 131 >= 'a' && 131 <= 'f' ? 131 - 'a' + 10
2889             : 131 >= 'A' && 131 <= 'F' ? 131 - 'A' + 10 : -1 ,
2890             132 >= '0' && 132 <= '9' ? 132 - '0' : 132 >= 'a' && 132 <= 'f' ? 132 - 'a' + 10
2891             : 132 >= 'A' && 132 <= 'F' ? 132 - 'A' + 10 : -1 ,
2892             133 >= '0' && 133 <= '9' ? 133 - '0' : 133 >= 'a' && 133 <= 'f' ? 133 - 'a' + 10
2893             : 133 >= 'A' && 133 <= 'F' ? 133 - 'A' + 10 : -1 ,
2894             134 >= '0' && 134 <= '9' ? 134 - '0' : 134 >= 'a' && 134 <= 'f' ? 134 - 'a' + 10
2895             : 134 >= 'A' && 134 <= 'F' ? 134 - 'A' + 10 : -1 ,
2896             135 >= '0' && 135 <= '9' ? 135 - '0' : 135 >= 'a' && 135 <= 'f' ? 135 - 'a' + 10
2897             : 135 >= 'A' && 135 <= 'F' ? 135 - 'A' + 10 : -1 ,
2898             136 >= '0' && 136 <= '9' ? 136 - '0' : 136 >= 'a' && 136 <= 'f' ? 136 - 'a' + 10
2899             : 136 >= 'A' && 136 <= 'F' ? 136 - 'A' + 10 : -1 ,
2900             137 >= '0' && 137 <= '9' ? 137 - '0' : 137 >= 'a' && 137 <= 'f' ? 137 - 'a' + 10
2901             : 137 >= 'A' && 137 <= 'F' ? 137 - 'A' + 10 : -1 ,
2902             138 >= '0' && 138 <= '9' ? 138 - '0' : 138 >= 'a' && 138 <= 'f' ? 138 - 'a' + 10
2903             : 138 >= 'A' && 138 <= 'F' ? 138 - 'A' + 10 : -1 ,
2904             139 >= '0' && 139 <= '9' ? 139 - '0' : 139 >= 'a' && 139 <= 'f' ? 139 - 'a' + 10
2905             : 139 >= 'A' && 139 <= 'F' ? 139 - 'A' + 10 : -1 ,
2906             140 >= '0' && 140 <= '9' ? 140 - '0' : 140 >= 'a' && 140 <= 'f' ? 140 - 'a' + 10
2907             : 140 >= 'A' && 140 <= 'F' ? 140 - 'A' + 10 : -1 ,
2908             141 >= '0' && 141 <= '9' ? 141 - '0' : 141 >= 'a' && 141 <= 'f' ? 141 - 'a' + 10
2909             : 141 >= 'A' && 141 <= 'F' ? 141 - 'A' + 10 : -1 ,
2910             142 >= '0' && 142 <= '9' ? 142 - '0' : 142 >= 'a' && 142 <= 'f' ? 142 - 'a' + 10
2911             : 142 >= 'A' && 142 <= 'F' ? 142 - 'A' + 10 : -1 ,
2912             143 >= '0' && 143 <= '9' ? 143 - '0' : 143 >= 'a' && 143 <= 'f' ? 143 - 'a' + 10
2913             : 143 >= 'A' && 143 <= 'F' ? 143 - 'A' + 10 : -1 ,
2914             144 >= '0' && 144 <= '9' ? 144 - '0' : 144 >= 'a' && 144 <= 'f' ? 144 - 'a' + 10
2915             : 144 >= 'A' && 144 <= 'F' ? 144 - 'A' + 10 : -1 ,
2916             145 >= '0' && 145 <= '9' ? 145 - '0' : 145 >= 'a' && 145 <= 'f' ? 145 - 'a' + 10
2917             : 145 >= 'A' && 145 <= 'F' ? 145 - 'A' + 10 : -1 ,
2918             146 >= '0' && 146 <= '9' ? 146 - '0' : 146 >= 'a' && 146 <= 'f' ? 146 - 'a' + 10
2919             : 146 >= 'A' && 146 <= 'F' ? 146 - 'A' + 10 : -1 ,
2920             147 >= '0' && 147 <= '9' ? 147 - '0' : 147 >= 'a' && 147 <= 'f' ? 147 - 'a' + 10
2921             : 147 >= 'A' && 147 <= 'F' ? 147 - 'A' + 10 : -1 ,
2922             148 >= '0' && 148 <= '9' ? 148 - '0' : 148 >= 'a' && 148 <= 'f' ? 148 - 'a' + 10
2923             : 148 >= 'A' && 148 <= 'F' ? 148 - 'A' + 10 : -1 ,
2924             149 >= '0' && 149 <= '9' ? 149 - '0' : 149 >= 'a' && 149 <= 'f' ? 149 - 'a' + 10
2925             : 149 >= 'A' && 149 <= 'F' ? 149 - 'A' + 10 : -1 ,
2926             150 >= '0' && 150 <= '9' ? 150 - '0' : 150 >= 'a' && 150 <= 'f' ? 150 - 'a' + 10
2927             : 150 >= 'A' && 150 <= 'F' ? 150 - 'A' + 10 : -1 ,
2928             151 >= '0' && 151 <= '9' ? 151 - '0' : 151 >= 'a' && 151 <= 'f' ? 151 - 'a' + 10
2929             : 151 >= 'A' && 151 <= 'F' ? 151 - 'A' + 10 : -1 ,
2930             152 >= '0' && 152 <= '9' ? 152 - '0' : 152 >= 'a' && 152 <= 'f' ? 152 - 'a' + 10
2931             : 152 >= 'A' && 152 <= 'F' ? 152 - 'A' + 10 : -1 ,
2932             153 >= '0' && 153 <= '9' ? 153 - '0' : 153 >= 'a' && 153 <= 'f' ? 153 - 'a' + 10
2933             : 153 >= 'A' && 153 <= 'F' ? 153 - 'A' + 10 : -1 ,
2934             154 >= '0' && 154 <= '9' ? 154 - '0' : 154 >= 'a' && 154 <= 'f' ? 154 - 'a' + 10
2935             : 154 >= 'A' && 154 <= 'F' ? 154 - 'A' + 10 : -1 ,
2936             155 >= '0' && 155 <= '9' ? 155 - '0' : 155 >= 'a' && 155 <= 'f' ? 155 - 'a' + 10
2937             : 155 >= 'A' && 155 <= 'F' ? 155 - 'A' + 10 : -1 ,
2938             156 >= '0' && 156 <= '9' ? 156 - '0' : 156 >= 'a' && 156 <= 'f' ? 156 - 'a' + 10
2939             : 156 >= 'A' && 156 <= 'F' ? 156 - 'A' + 10 : -1 ,
2940             157 >= '0' && 157 <= '9' ? 157 - '0' : 157 >= 'a' && 157 <= 'f' ? 157 - 'a' + 10
2941             : 157 >= 'A' && 157 <= 'F' ? 157 - 'A' + 10 : -1 ,
2942             158 >= '0' && 158 <= '9' ? 158 - '0' : 158 >= 'a' && 158 <= 'f' ? 158 - 'a' + 10
2943             : 158 >= 'A' && 158 <= 'F' ? 158 - 'A' + 10 : -1 ,
2944             159 >= '0' && 159 <= '9' ? 159 - '0' : 159 >= 'a' && 159 <= 'f' ? 159 - 'a' + 10
2945             : 159 >= 'A' && 159 <= 'F' ? 159 - 'A' + 10 : -1 ,
2946             160 >= '0' && 160 <= '9' ? 160 - '0' : 160 >= 'a' && 160 <= 'f' ? 160 - 'a' + 10
2947             : 160 >= 'A' && 160 <= 'F' ? 160 - 'A' + 10 : -1 ,
2948             161 >= '0' && 161 <= '9' ? 161 - '0' : 161 >= 'a' && 161 <= 'f' ? 161 - 'a' + 10
2949             : 161 >= 'A' && 161 <= 'F' ? 161 - 'A' + 10 : -1 ,
2950             162 >= '0' && 162 <= '9' ? 162 - '0' : 162 >= 'a' && 162 <= 'f' ? 162 - 'a' + 10
2951             : 162 >= 'A' && 162 <= 'F' ? 162 - 'A' + 10 : -1 ,
2952             163 >= '0' && 163 <= '9' ? 163 - '0' : 163 >= 'a' && 163 <= 'f' ? 163 - 'a' + 10
2953             : 163 >= 'A' && 163 <= 'F' ? 163 - 'A' + 10 : -1 ,
2954             164 >= '0' && 164 <= '9' ? 164 - '0' : 164 >= 'a' && 164 <= 'f' ? 164 - 'a' + 10
2955             : 164 >= 'A' && 164 <= 'F' ? 164 - 'A' + 10 : -1 ,
2956             165 >= '0' && 165 <= '9' ? 165 - '0' : 165 >= 'a' && 165 <= 'f' ? 165 - 'a' + 10
2957             : 165 >= 'A' && 165 <= 'F' ? 165 - 'A' + 10 : -1 ,
2958             166 >= '0' && 166 <= '9' ? 166 - '0' : 166 >= 'a' && 166 <= 'f' ? 166 - 'a' + 10
2959             : 166 >= 'A' && 166 <= 'F' ? 166 - 'A' + 10 : -1 ,
2960             167 >= '0' && 167 <= '9' ? 167 - '0' : 167 >= 'a' && 167 <= 'f' ? 167 - 'a' + 10
2961             : 167 >= 'A' && 167 <= 'F' ? 167 - 'A' + 10 : -1 ,
2962             168 >= '0' && 168 <= '9' ? 168 - '0' : 168 >= 'a' && 168 <= 'f' ? 168 - 'a' + 10
2963             : 168 >= 'A' && 168 <= 'F' ? 168 - 'A' + 10 : -1 ,
2964             169 >= '0' && 169 <= '9' ? 169 - '0' : 169 >= 'a' && 169 <= 'f' ? 169 - 'a' + 10
2965             : 169 >= 'A' && 169 <= 'F' ? 169 - 'A' + 10 : -1 ,
2966             170 >= '0' && 170 <= '9' ? 170 - '0' : 170 >= 'a' && 170 <= 'f' ? 170 - 'a' + 10
2967             : 170 >= 'A' && 170 <= 'F' ? 170 - 'A' + 10 : -1 ,
2968             171 >= '0' && 171 <= '9' ? 171 - '0' : 171 >= 'a' && 171 <= 'f' ? 171 - 'a' + 10
2969             : 171 >= 'A' && 171 <= 'F' ? 171 - 'A' + 10 : -1 ,
2970             172 >= '0' && 172 <= '9' ? 172 - '0' : 172 >= 'a' && 172 <= 'f' ? 172 - 'a' + 10
2971             : 172 >= 'A' && 172 <= 'F' ? 172 - 'A' + 10 : -1 ,
2972             173 >= '0' && 173 <= '9' ? 173 - '0' : 173 >= 'a' && 173 <= 'f' ? 173 - 'a' + 10
2973             : 173 >= 'A' && 173 <= 'F' ? 173 - 'A' + 10 : -1 ,
2974             174 >= '0' && 174 <= '9' ? 174 - '0' : 174 >= 'a' && 174 <= 'f' ? 174 - 'a' + 10
2975             : 174 >= 'A' && 174 <= 'F' ? 174 - 'A' + 10 : -1 ,
2976             175 >= '0' && 175 <= '9' ? 175 - '0' : 175 >= 'a' && 175 <= 'f' ? 175 - 'a' + 10
2977             : 175 >= 'A' && 175 <= 'F' ? 175 - 'A' + 10 : -1 ,
2978             176 >= '0' && 176 <= '9' ? 176 - '0' : 176 >= 'a' && 176 <= 'f' ? 176 - 'a' + 10
2979             : 176 >= 'A' && 176 <= 'F' ? 176 - 'A' + 10 : -1 ,
2980             177 >= '0' && 177 <= '9' ? 177 - '0' : 177 >= 'a' && 177 <= 'f' ? 177 - 'a' + 10
2981             : 177 >= 'A' && 177 <= 'F' ? 177 - 'A' + 10 : -1 ,
2982             178 >= '0' && 178 <= '9' ? 178 - '0' : 178 >= 'a' && 178 <= 'f' ? 178 - 'a' + 10
2983             : 178 >= 'A' && 178 <= 'F' ? 178 - 'A' + 10 : -1 ,
2984             179 >= '0' && 179 <= '9' ? 179 - '0' : 179 >= 'a' && 179 <= 'f' ? 179 - 'a' + 10
2985             : 179 >= 'A' && 179 <= 'F' ? 179 - 'A' + 10 : -1 ,
2986             180 >= '0' && 180 <= '9' ? 180 - '0' : 180 >= 'a' && 180 <= 'f' ? 180 - 'a' + 10
2987             : 180 >= 'A' && 180 <= 'F' ? 180 - 'A' + 10 : -1 ,
2988             181 >= '0' && 181 <= '9' ? 181 - '0' : 181 >= 'a' && 181 <= 'f' ? 181 - 'a' + 10
2989             : 181 >= 'A' && 181 <= 'F' ? 181 - 'A' + 10 : -1 ,
2990             182 >= '0' && 182 <= '9' ? 182 - '0' : 182 >= 'a' && 182 <= 'f' ? 182 - 'a' + 10
2991             : 182 >= 'A' && 182 <= 'F' ? 182 - 'A' + 10 : -1 ,
2992             183 >= '0' && 183 <= '9' ? 183 - '0' : 183 >= 'a' && 183 <= 'f' ? 183 - 'a' + 10
2993             : 183 >= 'A' && 183 <= 'F' ? 183 - 'A' + 10 : -1 ,
2994             184 >= '0' && 184 <= '9' ? 184 - '0' : 184 >= 'a' && 184 <= 'f' ? 184 - 'a' + 10
2995             : 184 >= 'A' && 184 <= 'F' ? 184 - 'A' + 10 : -1 ,
2996             185 >= '0' && 185 <= '9' ? 185 - '0' : 185 >= 'a' && 185 <= 'f' ? 185 - 'a' + 10
2997             : 185 >= 'A' && 185 <= 'F' ? 185 - 'A' + 10 : -1 ,
2998             186 >= '0' && 186 <= '9' ? 186 - '0' : 186 >= 'a' && 186 <= 'f' ? 186 - 'a' + 10
2999             : 186 >= 'A' && 186 <= 'F' ? 186 - 'A' + 10 : -1 ,
3000             187 >= '0' && 187 <= '9' ? 187 - '0' : 187 >= 'a' && 187 <= 'f' ? 187 - 'a' + 10
3001             : 187 >= 'A' && 187 <= 'F' ? 187 - 'A' + 10 : -1 ,
3002             188 >= '0' && 188 <= '9' ? 188 - '0' : 188 >= 'a' && 188 <= 'f' ? 188 - 'a' + 10
3003             : 188 >= 'A' && 188 <= 'F' ? 188 - 'A' + 10 : -1 ,
3004             189 >= '0' && 189 <= '9' ? 189 - '0' : 189 >= 'a' && 189 <= 'f' ? 189 - 'a' + 10
3005             : 189 >= 'A' && 189 <= 'F' ? 189 - 'A' + 10 : -1 ,
3006             190 >= '0' && 190 <= '9' ? 190 - '0' : 190 >= 'a' && 190 <= 'f' ? 190 - 'a' + 10
3007             : 190 >= 'A' && 190 <= 'F' ? 190 - 'A' + 10 : -1 ,
3008             191 >= '0' && 191 <= '9' ? 191 - '0' : 191 >= 'a' && 191 <= 'f' ? 191 - 'a' + 10
3009             : 191 >= 'A' && 191 <= 'F' ? 191 - 'A' + 10 : -1 ,
3010             192 >= '0' && 192 <= '9' ? 192 - '0' : 192 >= 'a' && 192 <= 'f' ? 192 - 'a' + 10
3011             : 192 >= 'A' && 192 <= 'F' ? 192 - 'A' + 10 : -1 ,
3012             193 >= '0' && 193 <= '9' ? 193 - '0' : 193 >= 'a' && 193 <= 'f' ? 193 - 'a' + 10
3013             : 193 >= 'A' && 193 <= 'F' ? 193 - 'A' + 10 : -1 ,
3014             194 >= '0' && 194 <= '9' ? 194 - '0' : 194 >= 'a' && 194 <= 'f' ? 194 - 'a' + 10
3015             : 194 >= 'A' && 194 <= 'F' ? 194 - 'A' + 10 : -1 ,
3016             195 >= '0' && 195 <= '9' ? 195 - '0' : 195 >= 'a' && 195 <= 'f' ? 195 - 'a' + 10
3017             : 195 >= 'A' && 195 <= 'F' ? 195 - 'A' + 10 : -1 ,
3018             196 >= '0' && 196 <= '9' ? 196 - '0' : 196 >= 'a' && 196 <= 'f' ? 196 - 'a' + 10
3019             : 196 >= 'A' && 196 <= 'F' ? 196 - 'A' + 10 : -1 ,
3020             197 >= '0' && 197 <= '9' ? 197 - '0' : 197 >= 'a' && 197 <= 'f' ? 197 - 'a' + 10
3021             : 197 >= 'A' && 197 <= 'F' ? 197 - 'A' + 10 : -1 ,
3022             198 >= '0' && 198 <= '9' ? 198 - '0' : 198 >= 'a' && 198 <= 'f' ? 198 - 'a' + 10
3023             : 198 >= 'A' && 198 <= 'F' ? 198 - 'A' + 10 : -1 ,
3024             199 >= '0' && 199 <= '9' ? 199 - '0' : 199 >= 'a' && 199 <= 'f' ? 199 - 'a' + 10
3025             : 199 >= 'A' && 199 <= 'F' ? 199 - 'A' + 10 : -1 ,
3026             200 >= '0' && 200 <= '9' ? 200 - '0' : 200 >= 'a' && 200 <= 'f' ? 200 - 'a' + 10
3027             : 200 >= 'A' && 200 <= 'F' ? 200 - 'A' + 10 : -1 ,
3028             201 >= '0' && 201 <= '9' ? 201 - '0' : 201 >= 'a' && 201 <= 'f' ? 201 - 'a' + 10
3029             : 201 >= 'A' && 201 <= 'F' ? 201 - 'A' + 10 : -1 ,
3030             202 >= '0' && 202 <= '9' ? 202 - '0' : 202 >= 'a' && 202 <= 'f' ? 202 - 'a' + 10
3031             : 202 >= 'A' && 202 <= 'F' ? 202 - 'A' + 10 : -1 ,
3032             203 >= '0' && 203 <= '9' ? 203 - '0' : 203 >= 'a' && 203 <= 'f' ? 203 - 'a' + 10
3033             : 203 >= 'A' && 203 <= 'F' ? 203 - 'A' + 10 : -1 ,
3034             204 >= '0' && 204 <= '9' ? 204 - '0' : 204 >= 'a' && 204 <= 'f' ? 204 - 'a' + 10
3035             : 204 >= 'A' && 204 <= 'F' ? 204 - 'A' + 10 : -1 ,
3036             205 >= '0' && 205 <= '9' ? 205 - '0' : 205 >= 'a' && 205 <= 'f' ? 205 - 'a' + 10
3037             : 205 >= 'A' && 205 <= 'F' ? 205 - 'A' + 10 : -1 ,
3038             206 >= '0' && 206 <= '9' ? 206 - '0' : 206 >= 'a' && 206 <= 'f' ? 206 - 'a' + 10
3039             : 206 >= 'A' && 206 <= 'F' ? 206 - 'A' + 10 : -1 ,
3040             207 >= '0' && 207 <= '9' ? 207 - '0' : 207 >= 'a' && 207 <= 'f' ? 207 - 'a' + 10
3041             : 207 >= 'A' && 207 <= 'F' ? 207 - 'A' + 10 : -1 ,
3042             208 >= '0' && 208 <= '9' ? 208 - '0' : 208 >= 'a' && 208 <= 'f' ? 208 - 'a' + 10
3043             : 208 >= 'A' && 208 <= 'F' ? 208 - 'A' + 10 : -1 ,
3044             209 >= '0' && 209 <= '9' ? 209 - '0' : 209 >= 'a' && 209 <= 'f' ? 209 - 'a' + 10
3045             : 209 >= 'A' && 209 <= 'F' ? 209 - 'A' + 10 : -1 ,
3046             210 >= '0' && 210 <= '9' ? 210 - '0' : 210 >= 'a' && 210 <= 'f' ? 210 - 'a' + 10
3047             : 210 >= 'A' && 210 <= 'F' ? 210 - 'A' + 10 : -1 ,
3048             211 >= '0' && 211 <= '9' ? 211 - '0' : 211 >= 'a' && 211 <= 'f' ? 211 - 'a' + 10
3049             : 211 >= 'A' && 211 <= 'F' ? 211 - 'A' + 10 : -1 ,
3050             212 >= '0' && 212 <= '9' ? 212 - '0' : 212 >= 'a' && 212 <= 'f' ? 212 - 'a' + 10
3051             : 212 >= 'A' && 212 <= 'F' ? 212 - 'A' + 10 : -1 ,
3052             213 >= '0' && 213 <= '9' ? 213 - '0' : 213 >= 'a' && 213 <= 'f' ? 213 - 'a' + 10
3053             : 213 >= 'A' && 213 <= 'F' ? 213 - 'A' + 10 : -1 ,
3054             214 >= '0' && 214 <= '9' ? 214 - '0' : 214 >= 'a' && 214 <= 'f' ? 214 - 'a' + 10
3055             : 214 >= 'A' && 214 <= 'F' ? 214 - 'A' + 10 : -1 ,
3056             215 >= '0' && 215 <= '9' ? 215 - '0' : 215 >= 'a' && 215 <= 'f' ? 215 - 'a' + 10
3057             : 215 >= 'A' && 215 <= 'F' ? 215 - 'A' + 10 : -1 ,
3058             216 >= '0' && 216 <= '9' ? 216 - '0' : 216 >= 'a' && 216 <= 'f' ? 216 - 'a' + 10
3059             : 216 >= 'A' && 216 <= 'F' ? 216 - 'A' + 10 : -1 ,
3060             217 >= '0' && 217 <= '9' ? 217 - '0' : 217 >= 'a' && 217 <= 'f' ? 217 - 'a' + 10
3061             : 217 >= 'A' && 217 <= 'F' ? 217 - 'A' + 10 : -1 ,
3062             218 >= '0' && 218 <= '9' ? 218 - '0' : 218 >= 'a' && 218 <= 'f' ? 218 - 'a' + 10
3063             : 218 >= 'A' && 218 <= 'F' ? 218 - 'A' + 10 : -1 ,
3064             219 >= '0' && 219 <= '9' ? 219 - '0' : 219 >= 'a' && 219 <= 'f' ? 219 - 'a' + 10
3065             : 219 >= 'A' && 219 <= 'F' ? 219 - 'A' + 10 : -1 ,
3066             220 >= '0' && 220 <= '9' ? 220 - '0' : 220 >= 'a' && 220 <= 'f' ? 220 - 'a' + 10
3067             : 220 >= 'A' && 220 <= 'F' ? 220 - 'A' + 10 : -1 ,
3068             221 >= '0' && 221 <= '9' ? 221 - '0' : 221 >= 'a' && 221 <= 'f' ? 221 - 'a' + 10
3069             : 221 >= 'A' && 221 <= 'F' ? 221 - 'A' + 10 : -1 ,
3070             222 >= '0' && 222 <= '9' ? 222 - '0' : 222 >= 'a' && 222 <= 'f' ? 222 - 'a' + 10
3071             : 222 >= 'A' && 222 <= 'F' ? 222 - 'A' + 10 : -1 ,
3072             223 >= '0' && 223 <= '9' ? 223 - '0' : 223 >= 'a' && 223 <= 'f' ? 223 - 'a' + 10
3073             : 223 >= 'A' && 223 <= 'F' ? 223 - 'A' + 10 : -1 ,
3074             224 >= '0' && 224 <= '9' ? 224 - '0' : 224 >= 'a' && 224 <= 'f' ? 224 - 'a' + 10
3075             : 224 >= 'A' && 224 <= 'F' ? 224 - 'A' + 10 : -1 ,
3076             225 >= '0' && 225 <= '9' ? 225 - '0' : 225 >= 'a' && 225 <= 'f' ? 225 - 'a' + 10
3077             : 225 >= 'A' && 225 <= 'F' ? 225 - 'A' + 10 : -1 ,
3078             226 >= '0' && 226 <= '9' ? 226 - '0' : 226 >= 'a' && 226 <= 'f' ? 226 - 'a' + 10
3079             : 226 >= 'A' && 226 <= 'F' ? 226 - 'A' + 10 : -1 ,
3080             227 >= '0' && 227 <= '9' ? 227 - '0' : 227 >= 'a' && 227 <= 'f' ? 227 - 'a' + 10
3081             : 227 >= 'A' && 227 <= 'F' ? 227 - 'A' + 10 : -1 ,
3082             228 >= '0' && 228 <= '9' ? 228 - '0' : 228 >= 'a' && 228 <= 'f' ? 228 - 'a' + 10
3083             : 228 >= 'A' && 228 <= 'F' ? 228 - 'A' + 10 : -1 ,
3084             229 >= '0' && 229 <= '9' ? 229 - '0' : 229 >= 'a' && 229 <= 'f' ? 229 - 'a' + 10
3085             : 229 >= 'A' && 229 <= 'F' ? 229 - 'A' + 10 : -1 ,
3086             230 >= '0' && 230 <= '9' ? 230 - '0' : 230 >= 'a' && 230 <= 'f' ? 230 - 'a' + 10
3087             : 230 >= 'A' && 230 <= 'F' ? 230 - 'A' + 10 : -1 ,
3088             231 >= '0' && 231 <= '9' ? 231 - '0' : 231 >= 'a' && 231 <= 'f' ? 231 - 'a' + 10
3089             : 231 >= 'A' && 231 <= 'F' ? 231 - 'A' + 10 : -1 ,
3090             232 >= '0' && 232 <= '9' ? 232 - '0' : 232 >= 'a' && 232 <= 'f' ? 232 - 'a' + 10
3091             : 232 >= 'A' && 232 <= 'F' ? 232 - 'A' + 10 : -1 ,
3092             233 >= '0' && 233 <= '9' ? 233 - '0' : 233 >= 'a' && 233 <= 'f' ? 233 - 'a' + 10
3093             : 233 >= 'A' && 233 <= 'F' ? 233 - 'A' + 10 : -1 ,
3094             234 >= '0' && 234 <= '9' ? 234 - '0' : 234 >= 'a' && 234 <= 'f' ? 234 - 'a' + 10
3095             : 234 >= 'A' && 234 <= 'F' ? 234 - 'A' + 10 : -1 ,
3096             235 >= '0' && 235 <= '9' ? 235 - '0' : 235 >= 'a' && 235 <= 'f' ? 235 - 'a' + 10
3097             : 235 >= 'A' && 235 <= 'F' ? 235 - 'A' + 10 : -1 ,
3098             236 >= '0' && 236 <= '9' ? 236 - '0' : 236 >= 'a' && 236 <= 'f' ? 236 - 'a' + 10
3099             : 236 >= 'A' && 236 <= 'F' ? 236 - 'A' + 10 : -1 ,
3100             237 >= '0' && 237 <= '9' ? 237 - '0' : 237 >= 'a' && 237 <= 'f' ? 237 - 'a' + 10
3101             : 237 >= 'A' && 237 <= 'F' ? 237 - 'A' + 10 : -1 ,
3102             238 >= '0' && 238 <= '9' ? 238 - '0' : 238 >= 'a' && 238 <= 'f' ? 238 - 'a' + 10
3103             : 238 >= 'A' && 238 <= 'F' ? 238 - 'A' + 10 : -1 ,
3104             239 >= '0' && 239 <= '9' ? 239 - '0' : 239 >= 'a' && 239 <= 'f' ? 239 - 'a' + 10
3105             : 239 >= 'A' && 239 <= 'F' ? 239 - 'A' + 10 : -1 ,
3106             240 >= '0' && 240 <= '9' ? 240 - '0' : 240 >= 'a' && 240 <= 'f' ? 240 - 'a' + 10
3107             : 240 >= 'A' && 240 <= 'F' ? 240 - 'A' + 10 : -1 ,
3108             241 >= '0' && 241 <= '9' ? 241 - '0' : 241 >= 'a' && 241 <= 'f' ? 241 - 'a' + 10
3109             : 241 >= 'A' && 241 <= 'F' ? 241 - 'A' + 10 : -1 ,
3110             242 >= '0' && 242 <= '9' ? 242 - '0' : 242 >= 'a' && 242 <= 'f' ? 242 - 'a' + 10
3111             : 242 >= 'A' && 242 <= 'F' ? 242 - 'A' + 10 : -1 ,
3112             243 >= '0' && 243 <= '9' ? 243 - '0' : 243 >= 'a' && 243 <= 'f' ? 243 - 'a' + 10
3113             : 243 >= 'A' && 243 <= 'F' ? 243 - 'A' + 10 : -1 ,
3114             244 >= '0' && 244 <= '9' ? 244 - '0' : 244 >= 'a' && 244 <= 'f' ? 244 - 'a' + 10
3115             : 244 >= 'A' && 244 <= 'F' ? 244 - 'A' + 10 : -1 ,
3116             245 >= '0' && 245 <= '9' ? 245 - '0' : 245 >= 'a' && 245 <= 'f' ? 245 - 'a' + 10
3117             : 245 >= 'A' && 245 <= 'F' ? 245 - 'A' + 10 : -1 ,
3118             246 >= '0' && 246 <= '9' ? 246 - '0' : 246 >= 'a' && 246 <= 'f' ? 246 - 'a' + 10
3119             : 246 >= 'A' && 246 <= 'F' ? 246 - 'A' + 10 : -1 ,
3120             247 >= '0' && 247 <= '9' ? 247 - '0' : 247 >= 'a' && 247 <= 'f' ? 247 - 'a' + 10
3121             : 247 >= 'A' && 247 <= 'F' ? 247 - 'A' + 10 : -1 ,
3122             248 >= '0' && 248 <= '9' ? 248 - '0' : 248 >= 'a' && 248 <= 'f' ? 248 - 'a' + 10
3123             : 248 >= 'A' && 248 <= 'F' ? 248 - 'A' + 10 : -1 ,
3124             249 >= '0' && 249 <= '9' ? 249 - '0' : 249 >= 'a' && 249 <= 'f' ? 249 - 'a' + 10
3125             : 249 >= 'A' && 249 <= 'F' ? 249 - 'A' + 10 : -1 ,
3126             250 >= '0' && 250 <= '9' ? 250 - '0' : 250 >= 'a' && 250 <= 'f' ? 250 - 'a' + 10
3127             : 250 >= 'A' && 250 <= 'F' ? 250 - 'A' + 10 : -1 ,
3128             251 >= '0' && 251 <= '9' ? 251 - '0' : 251 >= 'a' && 251 <= 'f' ? 251 - 'a' + 10
3129             : 251 >= 'A' && 251 <= 'F' ? 251 - 'A' + 10 : -1 ,
3130             252 >= '0' && 252 <= '9' ? 252 - '0' : 252 >= 'a' && 252 <= 'f' ? 252 - 'a' + 10
3131             : 252 >= 'A' && 252 <= 'F' ? 252 - 'A' + 10 : -1 ,
3132             253 >= '0' && 253 <= '9' ? 253 - '0' : 253 >= 'a' && 253 <= 'f' ? 253 - 'a' + 10
3133             : 253 >= 'A' && 253 <= 'F' ? 253 - 'A' + 10 : -1 ,
3134             254 >= '0' && 254 <= '9' ? 254 - '0' : 254 >= 'a' && 254 <= 'f' ? 254 - 'a' + 10
3135             : 254 >= 'A' && 254 <= 'F' ? 254 - 'A' + 10 : -1 ,
3136             255 >= '0' && 255 <= '9' ? 255 - '0' : 255 >= 'a' && 255 <= 'f' ? 255 - 'a' + 10
3137             : 255 >= 'A' && 255 <= 'F' ? 255 - 'A' + 10 : -1
3138             };
3139              
3140             static UV
3141 2144           decode_4hex (dec_t *dec)
3142             {
3143             signed char d1, d2, d3, d4;
3144 2144           unsigned char *cur = (unsigned char *)dec->cur;
3145              
3146 2144 100         d1 = decode_hexdigit [cur [0]]; if (UNLIKELY(d1 < 0)) ERR ("exactly four hexadecimal digits expected");
3147 2141 100         d2 = decode_hexdigit [cur [1]]; if (UNLIKELY(d2 < 0)) ERR ("exactly four hexadecimal digits expected");
3148 2139 100         d3 = decode_hexdigit [cur [2]]; if (UNLIKELY(d3 < 0)) ERR ("exactly four hexadecimal digits expected");
3149 2138 100         d4 = decode_hexdigit [cur [3]]; if (UNLIKELY(d4 < 0)) ERR ("exactly four hexadecimal digits expected");
3150              
3151 2137           dec->cur += 4;
3152              
3153 2137           return ((UV)d1) << 12
3154 2137           | ((UV)d2) << 8
3155 2137           | ((UV)d3) << 4
3156 2137           | ((UV)d4);
3157              
3158             fail:
3159 7           return (UV)-1;
3160             }
3161              
3162             static UV
3163 2506           decode_2hex (dec_t *dec)
3164             {
3165             signed char d1, d2;
3166 2506           unsigned char *cur = (unsigned char *)dec->cur;
3167              
3168 2506 50         d1 = decode_hexdigit [cur [0]]; if (UNLIKELY(d1 < 0)) ERR ("exactly two hexadecimal digits expected");
3169 2506 50         d2 = decode_hexdigit [cur [1]]; if (UNLIKELY(d2 < 0)) ERR ("exactly two hexadecimal digits expected");
3170 2506           dec->cur += 2;
3171 2506           return ((UV)d1) << 4
3172 2506           | ((UV)d2);
3173             fail:
3174 0           return (UV)-1;
3175             }
3176              
3177             static UV
3178 0           decode_3oct (dec_t *dec)
3179             {
3180             IV d1, d2, d3;
3181 0           unsigned char *cur = (unsigned char *)dec->cur;
3182              
3183 0 0         d1 = (IV)(cur[0] - '0'); if (d1 < 0 || d1 > 7) ERR ("exactly three octal digits expected");
    0          
3184 0 0         d2 = (IV)(cur[1] - '0'); if (d2 < 0 || d2 > 7) ERR ("exactly three octal digits expected");
    0          
3185 0 0         d3 = (IV)(cur[2] - '0'); if (d3 < 0 || d3 > 7) ERR ("exactly three octal digits expected");
    0          
3186 0           dec->cur += 3;
3187 0           return (d1 * 64) + (d2 * 8) + d3;
3188             fail:
3189 0           return (UV)-1;
3190             }
3191              
3192             static SV *
3193 6567           _decode_str (pTHX_ dec_t *dec, char endstr)
3194             {
3195 6567           SV *sv = 0;
3196 6567           int utf8 = 0;
3197 6567           char *dec_cur = dec->cur;
3198             unsigned char ch;
3199             assert(endstr == 0x27 || endstr == '"');
3200              
3201             do
3202             {
3203             char buf [SHORT_STRING_LEN + UTF8_MAXBYTES];
3204 6568           char *cur = buf;
3205              
3206             do
3207             {
3208 127954           ch = *(unsigned char *)dec_cur++;
3209              
3210 127954 100         if (UNLIKELY(ch == endstr))
3211             {
3212 6445 100         if (ch == 0x27 && !(dec->json.flags & F_ALLOW_SQUOTE)) {
    50          
3213 121           ERR("'\"' expected");
3214             }
3215 6445           --dec_cur;
3216 6445           break;
3217             }
3218 121509 100         else if (UNLIKELY(ch == '\\'))
3219             {
3220 5436           switch (*dec_cur)
3221             {
3222             case '\\':
3223             case '/':
3224 638           case '"': *cur++ = *dec_cur++; break;
3225              
3226 62           case 'b': ++dec_cur; *cur++ = '\010'; break;
3227 60           case 't': ++dec_cur; *cur++ = '\011'; break;
3228 259           case 'n': ++dec_cur; *cur++ = '\012'; break;
3229 50           case 'f': ++dec_cur; *cur++ = '\014'; break;
3230 46           case 'r': ++dec_cur; *cur++ = '\015'; break;
3231              
3232             case 'x':
3233             {
3234             UV c;
3235 2508 100         if (!(dec->json.flags & F_BINARY))
3236 2           ERR ("illegal hex character in non-binary string");
3237 2506           ++dec_cur;
3238 2506           dec->cur = dec_cur;
3239 2506           c = decode_2hex (dec);
3240 2506 50         if (c == (UV)-1)
3241 0           goto fail;
3242 2506           *cur++ = c;
3243 2506           dec_cur += 2;
3244 2506           break;
3245             }
3246             case '0': case '1': case '2': case '3':
3247             case '4': case '5': case '6': case '7':
3248             {
3249             UV c;
3250 1 50         if (!(dec->json.flags & F_BINARY))
3251 1           ERR ("illegal octal character in non-binary string");
3252 0           dec->cur = dec_cur;
3253 0           c = decode_3oct (dec);
3254 0 0         if (c == (UV)-1)
3255 0           goto fail;
3256 0           *cur++ = c;
3257 0           dec_cur += 3;
3258 0           break;
3259             }
3260             case 'u':
3261             {
3262             UV lo, hi;
3263 1802           ++dec_cur;
3264              
3265 1802           dec->cur = dec_cur;
3266 1802           hi = decode_4hex (dec);
3267 1802           dec_cur = dec->cur;
3268 1802 100         if (hi == (UV)-1)
3269 3           goto fail;
3270 1799 50         if (dec->json.flags & F_BINARY)
3271 0           ERR ("illegal unicode character in binary string");
3272              
3273             /* possibly a surrogate pair */
3274 1799 100         if (hi >= 0xd800) {
3275 372 100         if (hi < 0xdc00) {
3276 352 100         if (dec_cur [0] != '\\' || dec_cur [1] != 'u')
    100          
3277 10           ERR ("missing low surrogate character in surrogate pair");
3278              
3279 342           dec_cur += 2;
3280              
3281 342           dec->cur = dec_cur;
3282 342           lo = decode_4hex (dec);
3283 342           dec_cur = dec->cur;
3284 342 100         if (lo == (UV)-1)
3285 4           goto fail;
3286              
3287 338 100         if (lo < 0xdc00 || lo >= 0xe000)
    50          
3288 6           ERR ("surrogate pair expected");
3289              
3290 332           hi = (hi - 0xD800) * 0x400 + (lo - 0xDC00) + 0x10000;
3291 332 100         if (UNLIKELY(
    100          
    50          
    100          
3292             !(dec->json.flags & F_RELAXED)
3293             && (((hi & 0xfffe) == 0xfffe)
3294             || ((hi & 0xffff) == 0xffff)))) {
3295 332           WARNER_NONCHAR(hi);
3296             }
3297             }
3298 20 100         else if (UNLIKELY(hi < 0xe000)) {
3299 9           ERR ("missing high surrogate character in surrogate pair");
3300             }
3301             else
3302              
3303             /* check 66 noncharacters U+FDD0..U+FDEF, U+FFFE, U+FFFF
3304             and U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF, ... U+10FFFE, U+10FFFF (issue #74)
3305             and warn as in core.
3306             See http://www.unicode.org/versions/corrigendum9.html.
3307              
3308             https://www.rfc-editor.org/errata_search.php?rfc=7159&eid=3984
3309             The WG's consensus was to leave the full range present
3310             in the ABNF and add the interoperability guidance about
3311             values outside the Unicode accepted range.
3312              
3313             http://seriot.ch/parsing_json.html#25 According to the Unicode
3314             standard, illformed subsequences should be replaced by U+FFFD
3315             REPLACEMENT CHARACTER. (See Unicode PR #121: Recommended Practice
3316             for Replacement Characters). Several parsers use replacement
3317             characters, while other keep the escaped form or produce an
3318             non-Unicode character (see Section 5 - Parsing Contents). This
3319             values are not for interchange, only for application internal use.
3320             They are different from private use. Most parsers accept these.
3321             */
3322 11 100         if (UNLIKELY(
    100          
    100          
    100          
    100          
    50          
    100          
    100          
3323             !(dec->json.flags & F_RELAXED)
3324             && ((hi >= 0xfdd0 && hi <= 0xfdef)
3325             || (hi >= 0xfffe && hi <= 0xffff)))) {
3326 4           WARNER_NONCHAR(hi);
3327             }
3328             }
3329 1770 100         if (hi >= 0x80)
3330             {
3331 1093           utf8 = 1;
3332 1093           cur = (char*)encode_utf8 ((U8*)cur, hi);
3333             }
3334             else
3335 677           *cur++ = hi;
3336             }
3337 1770           break;
3338              
3339             default:
3340 10           --dec_cur;
3341 5401           ERR ("illegal backslash escape sequence in string");
3342             }
3343             }
3344 116073 100         else if (LIKELY(ch >= 0x20 && ch < 0x80)) {
    100          
3345 114885           *cur++ = ch;
3346             /* Ending ' already handled above with (ch == endstr) cid #165321 */
3347             }
3348 1188 100         else if (ch >= 0x80)
3349             {
3350             STRLEN clen;
3351              
3352 1171           --dec_cur;
3353              
3354 1171           decode_utf8 (aTHX_ (U8*)dec_cur, dec->end - dec_cur,
3355 1171           dec->json.flags & F_RELAXED, &clen);
3356 1171 100         if (clen == (STRLEN)-1)
3357 60           ERR ("malformed UTF-8 character in JSON string");
3358              
3359             do
3360 2942           *cur++ = *dec_cur++;
3361 2942 100         while (--clen);
3362              
3363 1111           utf8 = 1;
3364             }
3365 17 100         else if (dec->json.flags & F_RELAXED && ch == '\t') {
    50          
3366 1           *cur++ = ch;
3367             } else
3368             {
3369 16           --dec_cur;
3370              
3371 16 100         if (!ch)
3372 9           ERR ("unexpected end of string while parsing JSON string");
3373             else
3374 7           ERR ("invalid character encountered while parsing JSON string");
3375             }
3376             }
3377 121388 100         while (cur < buf + SHORT_STRING_LEN);
3378              
3379             {
3380 6447           STRLEN len = cur - buf;
3381              
3382 6447 100         if (sv)
3383             {
3384 1           STRLEN cur = SvCUR (sv);
3385              
3386 1 50         if (SvLEN (sv) <= cur + len)
3387 1 50         SvGROW (sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1);
    50          
3388              
3389 1           memcpy (SvPVX (sv) + SvCUR (sv), buf, len);
3390 1           SvCUR_set (sv, SvCUR (sv) + len);
3391             }
3392             else
3393 6446           sv = newSVpvn (buf, len);
3394             }
3395             }
3396 6447 100         while (*dec_cur != endstr);
3397              
3398 6446           ++dec_cur;
3399              
3400 6446 50         if (sv)
3401             {
3402 6446           SvPOK_only (sv);
3403 6446           *SvEND (sv) = 0;
3404              
3405 6446 100         if (utf8)
3406 6446           SvUTF8_on (sv);
3407             }
3408             else
3409 0           sv = newSVpvn ("", 0);
3410              
3411 6446           dec->cur = dec_cur;
3412 6446           return sv;
3413              
3414             fail:
3415 121           dec->cur = dec_cur;
3416 121           return 0;
3417             }
3418              
3419             INLINE SV *
3420 6283           decode_str (pTHX_ dec_t *dec)
3421             {
3422 6283           return _decode_str(aTHX_ dec, '"');
3423             }
3424              
3425             INLINE SV *
3426 3           decode_str_sq (pTHX_ dec_t *dec)
3427             {
3428 3           return _decode_str(aTHX_ dec, 0x27);
3429             }
3430              
3431             static SV *
3432 966           decode_num (pTHX_ dec_t *dec, SV *typesv)
3433             {
3434 966           int is_nv = 0;
3435 966           char *start = dec->cur;
3436              
3437             /* [minus] */
3438 966 100         if (*dec->cur == '-')
3439 57           ++dec->cur;
3440              
3441 966 100         if (*dec->cur == '0')
3442             {
3443 119           ++dec->cur;
3444 119 100         if (*dec->cur >= '0' && *dec->cur <= '9')
    100          
3445 6           ERR ("malformed number (leading zero must not be followed by another digit)");
3446             }
3447 847 100         else if (*dec->cur < '0' || *dec->cur > '9')
    100          
3448 7           ERR ("malformed number (no digits after initial minus)");
3449             else
3450             do
3451             {
3452 1239           ++dec->cur;
3453             }
3454 1239 100         while (*dec->cur >= '0' && *dec->cur <= '9');
    100          
3455              
3456             /* [frac] */
3457 953 100         if (*dec->cur == '.')
3458             {
3459 66           ++dec->cur;
3460              
3461 66 100         if (*dec->cur < '0' || *dec->cur > '9')
    100          
3462 8           ERR ("malformed number (no digits after decimal point)");
3463              
3464             do
3465             {
3466 255           ++dec->cur;
3467             }
3468 255 100         while (*dec->cur >= '0' && *dec->cur <= '9');
    100          
3469              
3470 58           is_nv = 1;
3471             }
3472              
3473             /* [exp] */
3474 945 100         if (*dec->cur == 'e' || *dec->cur == 'E')
    100          
3475             {
3476 61           ++dec->cur;
3477              
3478 61 100         if (*dec->cur == '-' || *dec->cur == '+')
    100          
3479 34           ++dec->cur;
3480              
3481 61 100         if (*dec->cur < '0' || *dec->cur > '9')
    100          
3482 17           ERR ("malformed number (no digits after exp sign)");
3483              
3484             do
3485             {
3486 221           ++dec->cur;
3487             }
3488 221 100         while (*dec->cur >= '0' && *dec->cur <= '9');
    100          
3489              
3490 44           is_nv = 1;
3491             }
3492              
3493 928 100         if (!is_nv)
3494             {
3495 847           int len = dec->cur - start;
3496              
3497 847 100         if (typesv)
3498 7           sv_setiv_mg (typesv, JSON_TYPE_INT);
3499              
3500             /* special case the rather common 1..5-digit-int case */
3501 847 100         if (*start == '-')
3502 28           switch (len)
3503             {
3504 16           case 2: return newSViv (-(IV)( start [1] - '0' * 1));
3505 5           case 3: return newSViv (-(IV)( start [1] * 10 + start [2] - '0' * 11));
3506 3           case 4: return newSViv (-(IV)( start [1] * 100 + start [2] * 10 + start [3] - '0' * 111));
3507 0           case 5: return newSViv (-(IV)( start [1] * 1000 + start [2] * 100 + start [3] * 10 + start [4] - '0' * 1111));
3508 4           case 6: return newSViv (-(IV)(start [1] * 10000 + start [2] * 1000 + start [3] * 100 + start [4] * 10 + start [5] - '0' * 11111));
3509             }
3510             else
3511 819           switch (len)
3512             {
3513 780           case 1: return newSViv ( start [0] - '0' * 1);
3514 6           case 2: return newSViv ( start [0] * 10 + start [1] - '0' * 11);
3515 7           case 3: return newSViv ( start [0] * 100 + start [1] * 10 + start [2] - '0' * 111);
3516 4           case 4: return newSViv ( start [0] * 1000 + start [1] * 100 + start [2] * 10 + start [3] - '0' * 1111);
3517 10           case 5: return newSViv ( start [0] * 10000 + start [1] * 1000 + start [2] * 100 + start [3] * 10 + start [4] - '0' * 11111);
3518             }
3519              
3520             {
3521             UV uv;
3522 16           int numtype = grok_number (start, len, &uv);
3523 16 100         if (numtype & IS_NUMBER_IN_UV) {
3524 10 100         if (numtype & IS_NUMBER_NEG)
3525             {
3526 2 50         if (uv <= (UV)(IV_MAX) + 1)
3527 10           return newSViv (-(IV)uv);
3528             }
3529             else
3530 8           return newSVuv (uv);
3531             }
3532             }
3533              
3534 6           len -= *start == '-' ? 1 : 0;
3535              
3536             /* does not fit into IV or UV, try NV */
3537 6 50         if ((sizeof (NV) == sizeof (double) && DBL_DIG >= len)
3538             #if defined (LDBL_DIG)
3539             || (sizeof (NV) == sizeof (long double) && LDBL_DIG >= len)
3540             #endif
3541             )
3542             /* fits into NV without loss of precision */
3543 0           return newSVnv (json_atof (start));
3544              
3545 6 100         if (dec->json.flags & F_ALLOW_BIGNUM) {
3546             SV *errsv;
3547 2           SV* pv = newSVpvs("require Math::BigInt && return Math::BigInt->new(\"");
3548 2           sv_catpvn(pv, start, dec->cur - start);
3549 2           sv_catpvs(pv, "\");");
3550 2           eval_sv(pv, G_SCALAR);
3551 2           SvREFCNT_dec(pv);
3552             /* rethrow current error */
3553 2 50         errsv = ERRSV;
3554 2 50         if (SvROK (errsv))
3555 0           croak (NULL);
3556 2 50         else if (SvTRUE (errsv))
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
3557 0           croak ("%" SVf, SVfARG (errsv));
3558             {
3559 2           dSP;
3560 2           SV *retval = SvREFCNT_inc(POPs);
3561 2           PUTBACK;
3562 2           return retval;
3563             }
3564             }
3565              
3566             /* everything else fails, convert it to a string */
3567 4           return newSVpvn (start, dec->cur - start);
3568             }
3569              
3570 81 100         if (typesv)
3571 4           sv_setiv_mg (typesv, JSON_TYPE_FLOAT);
3572              
3573 81 100         if (dec->json.flags & F_ALLOW_BIGNUM) {
3574             SV *errsv;
3575 2           SV* pv = newSVpvs("require Math::BigFloat && return Math::BigFloat->new(\"");
3576 2           sv_catpvn(pv, start, dec->cur - start);
3577 2           sv_catpvs(pv, "\");");
3578 2           eval_sv(pv, G_SCALAR);
3579 2           SvREFCNT_dec(pv);
3580             /* rethrow current error */
3581 2 50         errsv = ERRSV;
3582 2 50         if (SvROK (errsv))
3583 0           croak (NULL);
3584 2 50         else if (SvTRUE (errsv))
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
3585 0           croak ("%" SVf, SVfARG (errsv));
3586             {
3587 2           dSP;
3588 2           SV *retval = SvREFCNT_inc(POPs);
3589 2           PUTBACK;
3590 2           return retval;
3591             }
3592             }
3593              
3594             /* loss of precision here */
3595 79           return newSVnv (json_atof (start));
3596              
3597             fail:
3598 38           return 0;
3599             }
3600              
3601             static SV *
3602 4227           decode_av (pTHX_ dec_t *dec, SV *typesv)
3603             {
3604 4227           AV *av = newAV ();
3605 4227           AV *typeav = NULL;
3606             SV *typerv;
3607              
3608 4227 100         DEC_INC_DEPTH;
3609 4222           decode_ws (dec);
3610              
3611 4222 100         if (typesv)
3612             {
3613 5           typeav = newAV ();
3614 5           typerv = newRV_noinc ((SV *)typeav);
3615 5 50         SvSetMagicSV (typesv, typerv);
    50          
3616             }
3617              
3618 4222 100         if (*dec->cur == ']')
3619 29           ++dec->cur;
3620             else
3621             for (;;)
3622             {
3623             SV *value;
3624 6377           SV *value_typesv = NULL;
3625              
3626 6377 100         if (typesv)
3627             {
3628 13           value_typesv = newSV (0);
3629 13           av_push (typeav, value_typesv);
3630             }
3631              
3632 6377           value = decode_sv (aTHX_ dec, value_typesv);
3633 6377 100         if (!value)
3634 1506           goto fail;
3635              
3636 4871           av_push (av, value);
3637              
3638 4871           decode_ws (dec);
3639              
3640 4871 100         if (*dec->cur == ']')
3641             {
3642 2658           ++dec->cur;
3643 2658           break;
3644             }
3645            
3646 2213 100         if (*dec->cur != ',')
3647 27           ERR (", or ] expected while parsing array");
3648              
3649 2186           ++dec->cur;
3650              
3651 2186           decode_ws (dec);
3652              
3653 2186 100         if (*dec->cur == ']' && dec->json.flags & F_RELAXED)
    100          
3654             {
3655 2           ++dec->cur;
3656 2           break;
3657             }
3658 2184           }
3659              
3660 2689           DEC_DEC_DEPTH;
3661 2689           return newRV_noinc ((SV *)av);
3662              
3663             fail:
3664 1538           SvREFCNT_dec (av);
3665 1538           DEC_DEC_DEPTH;
3666 1538           return 0;
3667             }
3668              
3669             static SV *
3670 2713           decode_hv (pTHX_ dec_t *dec, SV *typesv)
3671             {
3672             SV *sv;
3673 2713           HV *hv = newHV ();
3674 2713           HV *typehv = NULL;
3675             SV *typerv;
3676 2713           int allow_squote = dec->json.flags & F_ALLOW_SQUOTE;
3677 2713           int allow_barekey = dec->json.flags & F_ALLOW_BAREKEY;
3678 2713           int allow_dupkeys = dec->json.flags & F_ALLOW_DUPKEYS;
3679 2713           char endstr = '"';
3680              
3681 2713 50         DEC_INC_DEPTH;
3682 2713           decode_ws (dec);
3683              
3684 2713 100         if (typesv)
3685             {
3686 2           typehv = newHV ();
3687 2           typerv = newRV_noinc ((SV *)typehv);
3688 2 50         SvSetMagicSV (typesv, typerv);
    50          
3689             }
3690              
3691 2713 100         if (*dec->cur == '}')
3692 17           ++dec->cur;
3693             else
3694             for (;;)
3695             {
3696 6609           int is_bare = allow_barekey;
3697              
3698 6609 100         if (UNLIKELY(allow_barekey
    100          
    100          
    50          
3699             && *dec->cur >= 'A' && *dec->cur <= 'z'))
3700             ;
3701 6603 100         else if (UNLIKELY(allow_squote)) {
3702 16 100         if (*dec->cur != '"' && *dec->cur != 0x27) {
    100          
3703 1           ERR ("'\"' or ''' expected");
3704             }
3705 15 100         else if (*dec->cur == 0x27)
3706 4           endstr = 0x27;
3707 15           is_bare=0;
3708 15           ++dec->cur;
3709             } else {
3710 6587 100         EXPECT_CH ('"');
3711 6563           is_bare=0;
3712             }
3713              
3714             /* heuristic: assume that */
3715             /* a) decode_str + hv_store_ent are abysmally slow. */
3716             /* b) most hash keys are short, simple ascii text. */
3717             /* => try to "fast-match" such strings to avoid */
3718             /* the overhead of decode_str + hv_store_ent. */
3719             {
3720             SV *value;
3721 6584           SV *value_typesv = NULL;
3722 6584           char *p = dec->cur;
3723 6584           char *e = p + 24; /* only try up to 24 bytes */
3724              
3725             for (;;)
3726             {
3727             /* the >= 0x80 is false on most architectures */
3728 52866 100         if (!is_bare &&
    100          
3729 52785 100         (p == e || *p < 0x20 || *(U8*)p >= 0x80 || *p == '\\'
    50          
    100          
3730 52578 100         || allow_squote))
3731             {
3732             /* slow path, back up and use decode_str */
3733             /* utf8 hash keys are handled here */
3734 281           SV *key = _decode_str (aTHX_ dec, endstr);
3735 281 100         if (!key)
3736 4           goto fail;
3737              
3738 277 100         if (!allow_dupkeys && UNLIKELY(hv_exists_ent (hv, key, 0))) {
    100          
3739 1           ERR ("Duplicate keys not allowed");
3740             }
3741 276 50         decode_ws (dec); EXPECT_CH (':');
3742 276           decode_ws (dec);
3743              
3744 276 50         if (typesv)
3745             {
3746 0           value_typesv = newSV (0);
3747 0           (void)hv_store_ent (typehv, key, value_typesv, 0);
3748             }
3749              
3750 276           value = decode_sv (aTHX_ dec, value_typesv);
3751 276 100         if (!value)
3752             {
3753 1           SvREFCNT_dec (key);
3754 1           goto fail;
3755             }
3756              
3757 275           (void)hv_store_ent (hv, key, value, 0);
3758 275           SvREFCNT_dec (key);
3759              
3760 275           break;
3761             }
3762 52585 100         else if (*p == endstr
3763 46288 100         || (is_bare &&
    100          
3764 17 100         (*p == ':' || *p == ' ' || *p == 0x0a
    50          
3765 16 50         || *p == 0x0d || *p == 0x09)))
    100          
3766             {
3767             /* fast path, got a simple key */
3768 6303           char *key = dec->cur;
3769 6303           U32 len = p - key;
3770             assert(p >= key && p - key < I32_MAX);
3771             #if PTRSIZE >= 8
3772             /* hv_store can only handle I32 len, which might overflow */
3773             /* perl5 just silently truncates it, cperl panics */
3774 6303 50         if (UNLIKELY(p - key > I32_MAX))
3775 0           ERR ("Hash key too large");
3776             #endif
3777 6303 100         if (!allow_dupkeys && UNLIKELY(hv_exists (hv, key, len))) {
    100          
3778 6           ERR ("Duplicate keys not allowed");
3779             }
3780              
3781 6297           dec->cur = p + 1;
3782 6297 100         decode_ws (dec); if (*p != ':') EXPECT_CH (':');
    100          
3783 6289           decode_ws (dec);
3784              
3785 6289 100         if (typesv)
3786             {
3787 9           value_typesv = newSV (0);
3788 9           (void)hv_store (typehv, key, len, value_typesv, 0);
3789             }
3790              
3791 6289           value = decode_sv (aTHX_ dec, value_typesv);
3792 6289 100         if (!value)
3793 776           goto fail;
3794              
3795             /* Note: not a utf8 hash key */
3796             #if PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION >= 9)
3797 5513           hv_common (hv, NULL, key, len, 0,
3798             HV_FETCH_ISSTORE|HV_FETCH_JUST_SV, value, 0);
3799             #else
3800             hv_store (hv, key, len, value, 0);
3801             #endif
3802 5513           break;
3803             }
3804              
3805 46282           ++p;
3806 46282           }
3807             }
3808              
3809 5788           decode_ws (dec);
3810              
3811 5788 100         if (*dec->cur == '}')
3812             {
3813 1869           ++dec->cur;
3814 1869           break;
3815             }
3816              
3817 3919 100         if (*dec->cur != ',')
3818 5           ERR (", or } expected while parsing object/hash");
3819              
3820 3914           ++dec->cur;
3821              
3822 3914           decode_ws (dec);
3823              
3824 3914 100         if (*dec->cur == '}' && dec->json.flags & F_RELAXED)
    100          
3825             {
3826 1           ++dec->cur;
3827 1           break;
3828             }
3829 3913           }
3830              
3831 1887           DEC_DEC_DEPTH;
3832 1887           sv = newRV_noinc ((SV *)hv);
3833              
3834             /* check filter callbacks */
3835 1887 100         if (dec->json.flags & F_HOOK)
3836             {
3837 14 100         if (dec->json.cb_sk_object && HvKEYS (hv) == 1)
    50          
    100          
3838             {
3839 7           HE *cb = NULL, *he;
3840              
3841 7           hv_iterinit (hv);
3842 7           he = hv_iternext (hv);
3843 7           hv_iterinit (hv);
3844              
3845             /* the next line creates a mortal sv each time it's called. */
3846             /* might want to optimise this for common cases. */
3847 7 50         if (LIKELY((long)he))
3848 7           cb = hv_fetch_ent (dec->json.cb_sk_object, hv_iterkeysv (he), 0, 0);
3849              
3850 7 100         if (cb)
3851             {
3852 6           dSP;
3853             I32 count;
3854              
3855 6 50         ENTER; SAVETMPS; SAVESTACK_POS (); PUSHMARK (SP);
    50          
3856 6 50         XPUSHs (HeVAL (he));
3857 6           sv_2mortal (sv);
3858              
3859 6           PUTBACK; count = call_sv (HeVAL (cb), G_ARRAY); SPAGAIN;
3860              
3861 6 100         if (count == 1)
3862             {
3863 4           sv = newSVsv (POPs);
3864 4 50         PUTBACK; FREETMPS; LEAVE;
3865 4           return sv;
3866             }
3867              
3868 2           SvREFCNT_inc (sv);
3869 2           SP -= count;
3870 2 50         PUTBACK; FREETMPS; LEAVE;
3871             }
3872             }
3873              
3874 10 100         if (dec->json.cb_object)
3875             {
3876 8           dSP;
3877             I32 count;
3878              
3879 8 50         ENTER; SAVETMPS; SAVESTACK_POS (); PUSHMARK (SP);
    50          
3880 8 50         XPUSHs (sv_2mortal (sv));
3881              
3882 8           PUTBACK; count = call_sv (dec->json.cb_object, G_ARRAY); SPAGAIN;
3883              
3884 8 100         if (count == 1)
3885             {
3886 3           sv = newSVsv (POPs);
3887 3 50         PUTBACK; FREETMPS; LEAVE;
3888 3           return sv;
3889             }
3890              
3891 5           SvREFCNT_inc (sv);
3892 5           SP -= count;
3893 5 50         PUTBACK; FREETMPS; LEAVE;
3894             }
3895             }
3896              
3897 1880           return sv;
3898              
3899             fail:
3900 826           SvREFCNT_dec (hv);
3901 826           DEC_DEC_DEPTH;
3902 826           return 0;
3903             }
3904              
3905             static SV *
3906 1           decode_tag (pTHX_ dec_t *dec)
3907             {
3908 1           SV *tag = 0;
3909 1           SV *val = 0;
3910              
3911 1 50         if (!(dec->json.flags & F_ALLOW_TAGS))
3912 0           ERR ("malformed JSON string, neither array, object, number, string or atom");
3913              
3914 1           ++dec->cur;
3915              
3916 1           decode_ws (dec);
3917              
3918 1           tag = decode_sv (aTHX_ dec, NULL);
3919 1 50         if (!tag)
3920 0           goto fail;
3921              
3922 1 50         if (!SvPOK (tag))
3923 0           ERR ("malformed JSON string, (tag) must be a string");
3924              
3925 1           decode_ws (dec);
3926              
3927 1 50         if (*dec->cur != ')')
3928 0           ERR (") expected after tag");
3929              
3930 1           ++dec->cur;
3931              
3932 1           decode_ws (dec);
3933              
3934 1           val = decode_sv (aTHX_ dec, NULL);
3935 1 50         if (!val)
3936 0           goto fail;
3937              
3938 1 50         if (!SvROK (val) || SvTYPE (SvRV (val)) != SVt_PVAV)
    50          
3939 0           ERR ("malformed JSON string, tag value must be an array");
3940              
3941             {
3942             dMY_CXT;
3943 1           AV *av = (AV *)SvRV (val);
3944 1           HVMAX_T i, len = av_len (av) + 1;
3945 1           HV *stash = gv_stashsv (tag, 0);
3946             SV *sv;
3947             GV *method;
3948 1           dSP;
3949              
3950 1 50         if (!stash)
3951 0           ERR ("cannot decode perl-object (package does not exist)");
3952              
3953 1           method = gv_fetchmethod_autoload (stash, "THAW", 0);
3954              
3955 1 50         if (!method)
3956 0           ERR ("cannot decode perl-object (package does not have a THAW method)");
3957              
3958 1 50         ENTER; SAVETMPS; SAVESTACK_POS (); PUSHMARK (SP);
    50          
3959 1 50         EXTEND (SP, len + 2);
    50          
3960             /* we re-bless the reference to get overload and other niceties right */
3961 1           PUSHs (tag);
3962 1           PUSHs (MY_CXT.sv_json);
3963              
3964 4 100         for (i = 0; i < len; ++i)
3965 3           PUSHs (*av_fetch (av, i, 1));
3966              
3967 1           PUTBACK;
3968 1           call_sv ((SV *)GvCV (method), G_SCALAR);
3969 1           SPAGAIN;
3970              
3971 1           SvREFCNT_dec (tag);
3972 1           SvREFCNT_dec (val);
3973 1           sv = SvREFCNT_inc (POPs);
3974              
3975 1           PUTBACK;
3976              
3977 1 50         FREETMPS; LEAVE;
3978              
3979 1           return sv;
3980             }
3981              
3982             fail:
3983 0           SvREFCNT_dec (tag);
3984 0           SvREFCNT_dec (val);
3985 0           return 0;
3986             }
3987              
3988             static SV *
3989 14384           decode_sv (pTHX_ dec_t *dec, SV *typesv)
3990             {
3991             /* the beauty of JSON: you need exactly one character lookahead */
3992             /* to parse everything. */
3993 14384           switch (*dec->cur)
3994             {
3995             case '"':
3996 6283           ++dec->cur;
3997 6283 100         if (typesv)
3998 5           sv_setiv_mg (typesv, JSON_TYPE_STRING);
3999 6283           return decode_str (aTHX_ dec);
4000             case 0x27:
4001 6 100         if (dec->json.flags & F_ALLOW_SQUOTE) {
4002 3           ++dec->cur;
4003 3 50         if (typesv)
4004 0           sv_setiv_mg (typesv, JSON_TYPE_STRING);
4005 3           return decode_str_sq (aTHX_ dec);
4006             }
4007 3           ERR ("malformed JSON string, neither tag, array, object, number, string or atom");
4008             break;
4009 4227           case '[': ++dec->cur; return decode_av (aTHX_ dec, typesv);
4010 2713           case '{': ++dec->cur; return decode_hv (aTHX_ dec, typesv);
4011 1           case '(': return decode_tag (aTHX_ dec);
4012              
4013             case '-':
4014             case '0': case '1': case '2': case '3': case '4':
4015             case '5': case '6': case '7': case '8': case '9':
4016 966           return decode_num (aTHX_ dec, typesv);
4017              
4018             case 't':
4019 31 100         if (dec->end - dec->cur >= 4 && memEQc(dec->cur, "true"))
    100          
4020             {
4021             dMY_CXT;
4022 27           dec->cur += 4;
4023 27 100         if (typesv)
4024 5           sv_setiv_mg (typesv, JSON_TYPE_BOOL);
4025 27 100         if (dec->json.flags & F_UNBLESSED_BOOL)
4026 4           return newSVsv (&PL_sv_yes);
4027 23           return newSVsv(MY_CXT.json_true);
4028             }
4029             else
4030 4           ERR ("'true' expected");
4031              
4032             break;
4033              
4034             case 'f':
4035 24 100         if (dec->end - dec->cur >= 5 && memEQc(dec->cur, "false"))
    100          
4036             {
4037             dMY_CXT;
4038 22           dec->cur += 5;
4039 22 100         if (typesv)
4040 5           sv_setiv_mg (typesv, JSON_TYPE_BOOL);
4041 22 100         if (dec->json.flags & F_UNBLESSED_BOOL)
4042 4           return newSVsv (&PL_sv_no);
4043 18           return newSVsv(MY_CXT.json_false);
4044             }
4045             else
4046 2           ERR ("'false' expected");
4047              
4048             break;
4049              
4050             case 'n':
4051 59 100         if (dec->end - dec->cur >= 4 && memEQc(dec->cur, "null"))
    100          
4052             {
4053 56           dec->cur += 4;
4054 56 100         if (typesv)
4055 3           sv_setiv_mg (typesv, JSON_TYPE_NULL);
4056 56           return newSVsv(&PL_sv_undef);
4057             }
4058             else
4059 3           ERR ("'null' expected");
4060              
4061             break;
4062              
4063             default:
4064 74           ERR ("malformed JSON string, neither tag, array, object, number, string or atom");
4065             break;
4066             }
4067              
4068             fail:
4069 86           return 0;
4070             }
4071              
4072             /* decode UTF32-LE/... to UTF-8:
4073             $utf8 = Encode::decode("UTF-32", $string); */
4074             static SV *
4075 8           decode_bom(pTHX_ const char* encoding, SV* string, STRLEN offset)
4076             {
4077 8           dSP;
4078             I32 items;
4079             PERL_UNUSED_ARG(offset);
4080              
4081             #ifndef HAVE_DECODE_BOM
4082             croak ("Cannot handle multibyte BOM yet");
4083             return string;
4084             #else
4085 8           ENTER;
4086             #if PERL_VERSION > 18
4087             /* on older perls (<5.20) this corrupts ax */
4088 8           Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT, newSVpvs("Encode"),
4089             NULL, NULL, NULL);
4090             #else
4091             if (!get_cvs("Encode::decode", GV_NOADD_NOINIT|GV_NO_SVGMAGIC))
4092             croak("Multibyte BOM needs to use Encode before");
4093             #endif
4094 8           LEAVE;
4095 8           ENTER;
4096 8 50         PUSHMARK(SP);
4097 8 50         XPUSHs(newSVpvn(encoding, strlen(encoding)));
4098 8 50         XPUSHs(string);
4099 8           PUTBACK;
4100             /* Calling Encode::Unicode::decode_xs would be faster, but we'd need the blessed
4101             enc hash from find_encoding() then. e.g. $Encode::Encoding{'UTF-16LE'}
4102             bless {Name=>UTF-16,size=>2,endian=>'',ucs2=>undef}, 'Encode::Unicode';
4103             And currenty we enjoy the simplicity of the BOM offset advance by
4104             endianness autodetection.
4105             */
4106 8           items = call_sv(MUTABLE_SV(get_cvs("Encode::decode",
4107             GV_NOADD_NOINIT|GV_NO_SVGMAGIC)), G_SCALAR);
4108 8           SPAGAIN;
4109 8 50         if (items >= 0 && SvPOK(TOPs)) {
    50          
4110 8           LEAVE;
4111 8           SvUTF8_on(TOPs);
4112 8           return POPs;
4113             } else {
4114 0           LEAVE;
4115 0           return string;
4116             }
4117             #endif
4118             }
4119              
4120             static SV *
4121 1442           decode_json (pTHX_ SV *string, JSON *json, STRLEN *offset_return, SV *typesv)
4122             {
4123             dec_t dec;
4124             SV *sv;
4125 1442           STRLEN len, offset = 0;
4126 1442           int converted = 0;
4127             /*dMY_CXT;*/
4128              
4129             /* work around bugs in 5.10 where manipulating magic values
4130             * makes perl ignore the magic in subsequent accesses.
4131             * also make a copy of non-PV values, to get them into a clean
4132             * state (SvPV should do that, but it's buggy, see below).
4133             * But breaks decode_prefix with offset.
4134             */
4135             /*SvGETMAGIC (string);*/
4136 1442 100         if (SvMAGICAL (string) || !SvPOK (string) || SvIsCOW_shared_hash(string))
    100          
    100          
    100          
4137 117           string = sv_2mortal (newSVsv (string));
4138              
4139 1442 100         SvUPGRADE (string, SVt_PV);
4140              
4141             /* work around a bug in perl 5.10, which causes SvCUR to fail an
4142             * assertion with -DDEBUGGING, although SvCUR is documented to
4143             * return the xpv_cur field which certainly exists after upgrading.
4144             * according to nicholas clark, calling SvPOK fixes this.
4145             * But it doesn't fix it, so try another workaround, call SvPV_nolen
4146             * and hope for the best.
4147             * Damnit, SvPV_nolen still trips over yet another assertion. This
4148             * assertion business is seriously broken, try yet another workaround
4149             * for the broken -DDEBUGGING.
4150             */
4151             {
4152             #ifdef DEBUGGING
4153             len = SvOK (string) ? sv_len (string) : 0;
4154             #else
4155 1442           len = SvCUR (string);
4156             #endif
4157              
4158 1442 100         if (UNLIKELY(len > json->max_size && json->max_size))
    100          
4159 1           croak ("attempted decode of JSON text of %lu bytes size, but max_size is set to %lu",
4160 1           (unsigned long)len, (unsigned long)json->max_size);
4161             }
4162              
4163             /* Detect BOM and possibly convert to UTF-8 and set UTF8 flag.
4164              
4165             https://tools.ietf.org/html/rfc7159#section-8.1
4166             JSON text SHALL be encoded in UTF-8, UTF-16, or UTF-32.
4167             Byte Order Mark - While section 8.1 states "Implementations MUST
4168             NOT add a byte order mark to the beginning of a JSON text",
4169             "implementations (...) MAY ignore the presence of a byte order
4170             mark rather than treating it as an error". */
4171 1441 100         if (UNLIKELY(len > 2 && SvPOK(string) && !json->incr_pos)) {
    50          
    100          
    100          
4172 1124           U8 *s = (U8*)SvPVX (string);
4173 1124 100         if (*s >= 0xEF) {
4174 12 50         if (len >= 3 && memEQc(s, UTF8BOM)) {
    100          
4175 5           converted = 1 + (json->flags & F_UTF8);
4176 5           json->flags |= F_UTF8;
4177 5           offset = 3;
4178 5           SvPV_set(string, SvPVX_mutable (string) + 3);
4179 5           SvCUR_set(string, len - 3);
4180 5           SvUTF8_on(string);
4181             /* omitting the endian name will skip the BOM in the result */
4182 7 50         } else if (len >= 4 && memEQc(s, UTF32BOM)) {
    100          
4183 2           string = decode_bom(aTHX_ "UTF-32", string, 4);
4184 2           converted = 1 + (json->flags & F_UTF8);
4185 2           json->flags |= F_UTF8;
4186 5 100         } else if (memEQc(s, UTF16BOM)) {
4187 2           string = decode_bom(aTHX_ "UTF-16", string, 2);
4188 2           converted = 1 + (json->flags & F_UTF8);
4189 2           json->flags |= F_UTF8;
4190 3 100         } else if (memEQc(s, UTF16BOM_BE)) {
4191 2           string = decode_bom(aTHX_ "UTF-16", string, 2);
4192 2           converted = 1 + (json->flags & F_UTF8);
4193 12           json->flags |= F_UTF8;
4194             }
4195 1112 100         } else if (UNLIKELY(len >= 4 && !*s && memEQc(s, UTF32BOM_BE))) {
    100          
    100          
    50          
4196 2           string = decode_bom(aTHX_ "UTF-32", string, 4);
4197 2           converted = 1 + (json->flags & F_UTF8);
4198 2           json->flags |= F_UTF8;
4199             }
4200             }
4201              
4202 1441 100         if (LIKELY(!converted)) {
4203 1428 100         if (DECODE_WANTS_OCTETS (json))
4204 751           sv_utf8_downgrade (string, 0);
4205             else
4206 677           sv_utf8_upgrade (string);
4207             }
4208              
4209             /* should basically be a NOP but needed for 5.6 with undef */
4210 1440 50         if (!SvPOK(string))
4211 0 0         SvGROW (string, SvCUR (string) + 1);
    0          
4212              
4213 1440           dec.json = *json;
4214 1440           dec.cur = SvPVX (string);
4215 1440           dec.end = SvEND (string);
4216 1440           dec.err = 0;
4217 1440           dec.depth = 0;
4218              
4219 1440 100         if (dec.json.cb_object || dec.json.cb_sk_object)
    100          
4220 14           dec.json.flags |= F_HOOK;
4221              
4222 1440           *dec.end = 0; /* this should basically be a nop, too, but make sure it's there */
4223              
4224 1440           decode_ws (&dec);
4225 1440           sv = decode_sv (aTHX_ &dec, typesv);
4226              
4227 1440 100         if (offset_return) {
4228 283 50         if (dec.cur < SvPVX (string) || dec.cur > SvEND (string))
    50          
4229 0           *offset_return = 0;
4230             else
4231 283           *offset_return = dec.cur - SvPVX (string);
4232             }
4233              
4234 1440 100         if (!(offset_return || !sv))
    100          
4235             {
4236             /* check for trailing garbage */
4237 839           decode_ws (&dec);
4238              
4239 839 100         if ((dec.end - dec.cur) || *dec.cur)
    50          
4240             {
4241 21           dec.err = "garbage after JSON object";
4242 21           SvREFCNT_dec (sv);
4243 21           sv = NULL;
4244             }
4245             }
4246             /* restore old utf8 string with BOM */
4247 1440 100         if (UNLIKELY(offset)) {
4248 5           SvPV_set(string, SvPVX_mutable (string) - offset);
4249 5           SvCUR_set(string, len);
4250             }
4251              
4252 1440 100         if (!sv)
4253             {
4254 343           SV *uni = sv_newmortal ();
4255              
4256             #if PERL_VERSION >= 8
4257             /* horrible hack to silence warning inside pv_uni_display */
4258             /* TODO: Can be omitted with newer perls */
4259 343           COP cop = *PL_curcop;
4260 343           cop.cop_warnings = pWARN_NONE;
4261 343           ENTER;
4262 343           SAVEVPTR (PL_curcop);
4263 343           PL_curcop = &cop;
4264 343           pv_uni_display (uni, (U8*)dec.cur, dec.end - dec.cur, 20, UNI_DISPLAY_QQ);
4265 343           LEAVE;
4266             #endif
4267 992 100         croak ("%s, at character offset %d (before \"%s\")",
4268             dec.err,
4269 343           (int)ptr_to_index (aTHX_ string, dec.cur-SvPVX(string)),
4270 306 50         dec.cur != dec.end ? SvPV_nolen (uni) : "(end of string)");
4271             }
4272              
4273 1097 100         if (!(dec.json.flags & F_ALLOW_NONREF) && json_nonref(aTHX_ sv))
    100          
4274 9           croak ("JSON text must be an object or array (but found number, string, true, false or null, use allow_nonref to allow this)");
4275              
4276 1088 100         if (UNLIKELY(converted && !(converted - 1))) /* with BOM, and UTF8 was not set */
    100          
4277 1           json->flags &= ~F_UTF8;
4278 1088           return sv_2mortal (sv);
4279             }
4280              
4281             /*/////////////////////////////////////////////////////////////////////////// */
4282             /* incremental parser */
4283              
4284             static void
4285 318           incr_parse (JSON *self)
4286             {
4287 318           const char *p = SvPVX (self->incr_text) + self->incr_pos;
4288              
4289             /* the state machine here is a bit convoluted and could be simplified a lot */
4290             /* but this would make it slower, so... */
4291              
4292             for (;;)
4293             {
4294             /*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 */
4295 327           switch (self->incr_mode)
4296             {
4297             /* only used for initial whitespace skipping */
4298             case INCR_M_WS:
4299             for (;;)
4300             {
4301 556 100         if (*p > 0x20)
4302             {
4303 278 100         if (*p == '#')
4304             {
4305 6           self->incr_mode = INCR_M_C0;
4306 6           goto incr_m_c;
4307             }
4308             else
4309             {
4310 272           self->incr_mode = INCR_M_JSON;
4311 272           goto incr_m_json;
4312             }
4313             }
4314 278 100         else if (!*p)
4315 42           goto interrupt;
4316              
4317 236           ++p;
4318 236           }
4319              
4320             /* skip a single char inside a string (for \\-processing) */
4321             case INCR_M_BS:
4322 0 0         if (!*p)
4323 0           goto interrupt;
4324              
4325 0           ++p;
4326 0           self->incr_mode = INCR_M_STR;
4327 0           goto incr_m_str;
4328              
4329             /* inside #-style comments */
4330             case INCR_M_C0:
4331             case INCR_M_C1:
4332             incr_m_c:
4333             for (;;)
4334             {
4335 45 100         if (*p == '\n')
4336             {
4337 9 100         self->incr_mode = self->incr_mode == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON;
4338 9           break;
4339             }
4340 36 50         else if (!*p)
4341 0           goto interrupt;
4342              
4343 36           ++p;
4344 36           }
4345              
4346 9           break;
4347              
4348             /* inside a string */
4349             case INCR_M_STR:
4350             incr_m_str:
4351             for (;;)
4352             {
4353 2085 100         if (*p == '"')
4354             {
4355 583           ++p;
4356 583           self->incr_mode = INCR_M_JSON;
4357              
4358 583 100         if (!self->incr_nest)
4359 15           goto interrupt;
4360              
4361 568           goto incr_m_json;
4362             }
4363 1502 100         else if (*p == '\\')
4364             {
4365 498           ++p; /* "virtually" consumes character after \ */
4366              
4367 498 50         if (!*p) /* if at end of string we have to switch modes */
4368             {
4369 0           self->incr_mode = INCR_M_BS;
4370 0           goto interrupt;
4371             }
4372             }
4373 1004 100         else if (!*p)
4374 2           goto interrupt;
4375              
4376 1500           ++p;
4377 1500           }
4378              
4379             /* after initial ws, outside string */
4380             case INCR_M_JSON:
4381             incr_m_json:
4382             for (;;)
4383             {
4384 3238           switch (*p++)
4385             {
4386             case 0:
4387 2           --p;
4388 2           goto interrupt;
4389              
4390             case 0x09:
4391             case 0x0a:
4392             case 0x0d:
4393             case 0x20:
4394 682 50         if (!self->incr_nest)
4395             {
4396 0           --p; /* do not eat the whitespace, let the next round do it */
4397 0           goto interrupt;
4398             }
4399 682           break;
4400              
4401             case '"':
4402 583           self->incr_mode = INCR_M_STR;
4403 583           goto incr_m_str;
4404              
4405             case '[':
4406             case '{':
4407             case '(':
4408 358 100         if (++self->incr_nest > (int)self->max_depth)
4409 1           croak (ERR_NESTING_EXCEEDED);
4410 357           break;
4411              
4412             case ']':
4413             case '}':
4414 355 100         if (--self->incr_nest <= 0)
4415 256           goto interrupt;
4416 99           break;
4417              
4418             case ')':
4419 0           --self->incr_nest;
4420 0           break;
4421              
4422             case '#':
4423 3           self->incr_mode = INCR_M_C1;
4424 3           goto incr_m_c;
4425             }
4426 2393           }
4427             }
4428 9           }
4429              
4430             interrupt:
4431 317           self->incr_pos = p - SvPVX (self->incr_text);
4432             /*printf ("interrupt<%.*s>\n", self->incr_pos, SvPVX(self->incr_text));//D */
4433             /*printf ("return pos %d mode %d nest %d\n", self->incr_pos, self->incr_mode, self->incr_nest);//D */
4434 317           }
4435              
4436             /*/////////////////////////////////////////////////////////////////////////// */
4437             /* XS interface functions */
4438              
4439             MODULE = Cpanel::JSON::XS PACKAGE = Cpanel::JSON::XS
4440              
4441             #if PERL_VERSION > 7
4442             # define NODEBUG_ON \
4443             CvNODEBUG_on (get_cv ("Cpanel::JSON::XS::incr_text", 0));
4444             #else
4445             # define NODEBUG_ON
4446             #endif
4447              
4448             BOOT:
4449             {
4450             HV *stash;
4451             MY_CXT_INIT;
4452 58           init_MY_CXT(aTHX_ &MY_CXT);
4453              
4454 58           stash = gv_stashpvs(JSON_TYPE_CLASS, GV_ADD);
4455 58           newCONSTSUB(stash, "JSON_TYPE_BOOL", newSViv(JSON_TYPE_BOOL));
4456 58           newCONSTSUB(stash, "JSON_TYPE_INT", newSViv(JSON_TYPE_INT));
4457 58           newCONSTSUB(stash, "JSON_TYPE_FLOAT", newSViv(JSON_TYPE_FLOAT));
4458 58           newCONSTSUB(stash, "JSON_TYPE_STRING", newSViv(JSON_TYPE_STRING));
4459 58           newCONSTSUB(stash, "JSON_TYPE_NULL", newSViv(JSON_TYPE_NULL));
4460 58           newCONSTSUB(stash, "JSON_TYPE_INT_OR_NULL", newSViv(JSON_TYPE_INT | JSON_TYPE_CAN_BE_NULL));
4461 58           newCONSTSUB(stash, "JSON_TYPE_BOOL_OR_NULL", newSViv(JSON_TYPE_BOOL | JSON_TYPE_CAN_BE_NULL));
4462 58           newCONSTSUB(stash, "JSON_TYPE_FLOAT_OR_NULL", newSViv(JSON_TYPE_FLOAT | JSON_TYPE_CAN_BE_NULL));
4463 58           newCONSTSUB(stash, "JSON_TYPE_STRING_OR_NULL", newSViv(JSON_TYPE_STRING | JSON_TYPE_CAN_BE_NULL));
4464 58           newCONSTSUB(stash, "JSON_TYPE_CAN_BE_NULL", newSViv(JSON_TYPE_CAN_BE_NULL));
4465 58           newCONSTSUB(stash, "JSON_TYPE_ARRAYOF_CLASS", newSVpvs(JSON_TYPE_ARRAYOF_CLASS));
4466 58           newCONSTSUB(stash, "JSON_TYPE_HASHOF_CLASS", newSVpvs(JSON_TYPE_HASHOF_CLASS));
4467 58           newCONSTSUB(stash, "JSON_TYPE_ANYOF_CLASS", newSVpvs(JSON_TYPE_ANYOF_CLASS));
4468              
4469 58           NODEBUG_ON; /* the debugger completely breaks lvalue subs */
4470             }
4471              
4472             PROTOTYPES: DISABLE
4473              
4474              
4475             #_if PERL_IMPLICIT_CONTEXT for embedding, but no ithreads, then CLONE is never
4476             # called
4477              
4478             #ifdef USE_ITHREADS
4479              
4480             void CLONE (...)
4481             PPCODE:
4482             MY_CXT_CLONE; /* possible declaration */
4483             init_MY_CXT(aTHX_ &MY_CXT);
4484             /* skip implicit PUTBACK, returning @_ to caller, more efficient*/
4485             return;
4486              
4487             #endif
4488              
4489             void END(...)
4490             PREINIT:
4491             dMY_CXT;
4492             SV * sv;
4493             PPCODE:
4494 58           sv = MY_CXT.sv_json;
4495 58           MY_CXT.sv_json = NULL;
4496 58           SvREFCNT_dec_NN(sv);
4497             /* skip implicit PUTBACK, returning @_ to caller, more efficient*/
4498 58           return;
4499              
4500             void new (char *klass)
4501             PPCODE:
4502             dMY_CXT;
4503 216           SV *pv = NEWSV (0, sizeof (JSON));
4504 216           SvPOK_only (pv);
4505 216           json_init ((JSON *)SvPVX (pv));
4506 216 50         XPUSHs (sv_2mortal (sv_bless (
    50          
4507             newRV_noinc (pv),
4508             strEQc (klass, "Cpanel::JSON::XS") ? JSON_STASH : gv_stashpv (klass, 1)
4509             )));
4510              
4511             void ascii (JSON *self, int enable = 1)
4512             ALIAS:
4513             ascii = F_ASCII
4514             latin1 = F_LATIN1
4515             binary = F_BINARY
4516             utf8 = F_UTF8
4517             indent = F_INDENT
4518             canonical = F_CANONICAL
4519             space_before = F_SPACE_BEFORE
4520             space_after = F_SPACE_AFTER
4521             pretty = F_PRETTY
4522             allow_nonref = F_ALLOW_NONREF
4523             shrink = F_SHRINK
4524             allow_blessed = F_ALLOW_BLESSED
4525             convert_blessed = F_CONV_BLESSED
4526             relaxed = SET_RELAXED
4527             allow_unknown = F_ALLOW_UNKNOWN
4528             allow_tags = F_ALLOW_TAGS
4529             allow_barekey = F_ALLOW_BAREKEY
4530             allow_singlequote = F_ALLOW_SQUOTE
4531             allow_bignum = F_ALLOW_BIGNUM
4532             escape_slash = F_ESCAPE_SLASH
4533             allow_stringify = F_ALLOW_STRINGIFY
4534             unblessed_bool = F_UNBLESSED_BOOL
4535             allow_dupkeys = F_ALLOW_DUPKEYS
4536             require_types = F_REQUIRE_TYPES
4537             type_all_string = F_TYPE_ALL_STRING
4538             PPCODE:
4539 297 100         if (enable)
4540 283           self->flags |= ix;
4541             else
4542 14           self->flags &= ~ix;
4543 297 50         XPUSHs (ST (0));
4544              
4545             void get_ascii (JSON *self)
4546             ALIAS:
4547             get_ascii = F_ASCII
4548             get_latin1 = F_LATIN1
4549             get_binary = F_BINARY
4550             get_utf8 = F_UTF8
4551             get_indent = F_INDENT
4552             get_canonical = F_CANONICAL
4553             get_space_before = F_SPACE_BEFORE
4554             get_space_after = F_SPACE_AFTER
4555             get_allow_nonref = F_ALLOW_NONREF
4556             get_shrink = F_SHRINK
4557             get_allow_blessed = F_ALLOW_BLESSED
4558             get_convert_blessed = F_CONV_BLESSED
4559             get_relaxed = F_RELAXED
4560             get_allow_unknown = F_ALLOW_UNKNOWN
4561             get_allow_tags = F_ALLOW_TAGS
4562             get_allow_barekey = F_ALLOW_BAREKEY
4563             get_allow_singlequote = F_ALLOW_SQUOTE
4564             get_allow_bignum = F_ALLOW_BIGNUM
4565             get_escape_slash = F_ESCAPE_SLASH
4566             get_allow_stringify = F_ALLOW_STRINGIFY
4567             get_unblessed_bool = F_UNBLESSED_BOOL
4568             get_allow_dupkeys = F_ALLOW_DUPKEYS
4569             get_require_types = F_REQUIRE_TYPES
4570             get_type_all_string = F_TYPE_ALL_STRING
4571             PPCODE:
4572 0 0         XPUSHs (boolSV (self->flags & ix));
    0          
4573              
4574             void indent_length (JSON *self, int val = INDENT_STEP)
4575             PPCODE:
4576 1 50         if (0 <= val && val <= 15) {
    50          
4577 1           self->indent_length = val;
4578             } else {
4579 0           warn("The acceptable range of indent_length() is 0 to 15.");
4580             }
4581 1 50         XPUSHs (ST (0));
4582              
4583             U32 get_indent_length (JSON *self)
4584             CODE:
4585 0           RETVAL = self->indent_length;
4586             OUTPUT:
4587             RETVAL
4588              
4589             void max_depth (JSON *self, U32 max_depth = 0x80000000UL)
4590             PPCODE:
4591 5           self->max_depth = max_depth;
4592 5 50         XPUSHs (ST (0));
4593              
4594             U32 get_max_depth (JSON *self)
4595             CODE:
4596 0           RETVAL = self->max_depth;
4597             OUTPUT:
4598             RETVAL
4599              
4600             void max_size (JSON *self, U32 max_size = 0)
4601             PPCODE:
4602 3           self->max_size = max_size;
4603 3 50         XPUSHs (ST (0));
4604              
4605             int get_max_size (JSON *self)
4606             CODE:
4607 0           RETVAL = self->max_size;
4608             OUTPUT:
4609             RETVAL
4610              
4611             void stringify_infnan (JSON *self, IV infnan_mode = 1)
4612             PPCODE:
4613 9 50         if (infnan_mode > 3 || infnan_mode < 0) {
    50          
4614 0           croak ("invalid stringify_infnan mode %d. Must be 0, 1, 2 or 3", (int)infnan_mode);
4615             }
4616 9           self->infnan_mode = (unsigned char)infnan_mode;
4617 9 50         XPUSHs (ST (0));
4618            
4619             int get_stringify_infnan (JSON *self)
4620             CODE:
4621 0           RETVAL = (int)self->infnan_mode;
4622             OUTPUT:
4623             RETVAL
4624              
4625             void sort_by (JSON *self, SV* cb = &PL_sv_yes)
4626             PPCODE:
4627             {
4628 3           SvREFCNT_dec (self->cb_sort_by);
4629 3 50         self->cb_sort_by = SvOK (cb) ? newSVsv (cb) : 0;
    0          
    0          
4630 3 50         if (self->cb_sort_by)
4631 3           self->flags |= F_CANONICAL;
4632              
4633 3 50         XPUSHs (ST (0));
4634             }
4635              
4636            
4637             void filter_json_object (JSON *self, SV *cb = &PL_sv_undef)
4638             PPCODE:
4639             {
4640 5           SvREFCNT_dec (self->cb_object);
4641 5 100         self->cb_object = SvOK (cb) ? newSVsv (cb) : 0;
    50          
    50          
4642              
4643 5 50         XPUSHs (ST (0));
4644             }
4645              
4646             void filter_json_single_key_object (JSON *self, SV *key, SV *cb = &PL_sv_undef)
4647             PPCODE:
4648             {
4649 6 100         if (!self->cb_sk_object)
4650 3           self->cb_sk_object = newHV ();
4651              
4652 6 100         if (SvOK (cb))
    50          
    50          
4653 5           (void)hv_store_ent (self->cb_sk_object, key, newSVsv (cb), 0);
4654             else
4655             {
4656 1           (void)hv_delete_ent (self->cb_sk_object, key, G_DISCARD, 0);
4657              
4658 1 50         if (!HvKEYS (self->cb_sk_object))
    50          
4659             {
4660 0           SvREFCNT_dec (self->cb_sk_object);
4661 0           self->cb_sk_object = 0;
4662             }
4663             }
4664              
4665 6 50         XPUSHs (ST (0));
4666             }
4667              
4668             void encode (JSON *self, SV *scalar, SV *typesv = &PL_sv_undef)
4669             PPCODE:
4670 1140           PUTBACK; scalar = encode_json (aTHX_ scalar, self, typesv); SPAGAIN;
4671 1111 50         XPUSHs (scalar);
4672              
4673             void decode (JSON *self, SV *jsonstr, SV *typesv = NULL)
4674             PPCODE:
4675 943           PUTBACK; jsonstr = decode_json (aTHX_ jsonstr, self, 0, typesv); SPAGAIN;
4676 646 50         XPUSHs (jsonstr);
4677              
4678             void decode_prefix (JSON *self, SV *jsonstr, SV *typesv = NULL)
4679             PPCODE:
4680             {
4681             SV *sv;
4682             STRLEN offset;
4683 12           PUTBACK; sv = decode_json (aTHX_ jsonstr, self, &offset, typesv); SPAGAIN;
4684 10 50         EXTEND (SP, 2);
4685 10           PUSHs (sv);
4686 10           PUSHs (sv_2mortal (newSVuv (ptr_to_index (aTHX_ jsonstr, offset))));
4687             }
4688              
4689             void incr_parse (JSON *self, SV *jsonstr = 0)
4690             PPCODE:
4691             {
4692 626 100         if (!self->incr_text)
4693 27           self->incr_text = newSVpvn ("", 0);
4694              
4695             /* if utf8-ness doesn't match the decoder, need to upgrade/downgrade */
4696 626 100         if (!DECODE_WANTS_OCTETS (self) == !SvUTF8 (self->incr_text)) {
4697 27 50         if (DECODE_WANTS_OCTETS (self))
4698             {
4699 0 0         if (self->incr_pos)
4700 0           self->incr_pos = utf8_length ((U8 *)SvPVX (self->incr_text),
4701             (U8 *)SvPVX (self->incr_text) + self->incr_pos);
4702              
4703 0           sv_utf8_downgrade (self->incr_text, 0);
4704             }
4705             else
4706             {
4707 27           sv_utf8_upgrade (self->incr_text);
4708              
4709 27 50         if (self->incr_pos)
4710 0           self->incr_pos = utf8_hop ((U8 *)SvPVX (self->incr_text), self->incr_pos)
4711 0           - (U8 *)SvPVX (self->incr_text);
4712             }
4713             }
4714              
4715             /* append data, if any */
4716 626 100         if (jsonstr)
4717             {
4718             /* make sure both strings have same encoding */
4719 321 100         if (SvUTF8 (jsonstr) != SvUTF8 (self->incr_text)) {
4720 319 50         if (SvUTF8 (jsonstr))
4721 0           sv_utf8_downgrade (jsonstr, 0);
4722             else
4723 319           sv_utf8_upgrade (jsonstr);
4724             }
4725              
4726             /* and then just blindly append */
4727             {
4728             STRLEN len;
4729 321 50         const char *str = SvPV (jsonstr, len);
4730 321           STRLEN cur = SvCUR (self->incr_text);
4731              
4732 321 100         if (SvLEN (self->incr_text) <= cur + len)
4733 147 50         SvGROW (self->incr_text, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1);
    50          
4734              
4735 321           Move (str, SvEND (self->incr_text), len, char);
4736 321           SvCUR_set (self->incr_text, SvCUR (self->incr_text) + len);
4737 321           *SvEND (self->incr_text) = 0; /* this should basically be a nop, too, but make sure it's there */
4738             }
4739             }
4740              
4741 626 50         if (GIMME_V != G_VOID)
    100          
4742             do
4743             {
4744             SV *sv;
4745             STRLEN offset;
4746             char *endp;
4747              
4748 319 100         if (!INCR_DONE (self))
    100          
4749             {
4750 318           incr_parse (self);
4751              
4752 317 100         if (UNLIKELY(self->incr_pos > self->max_size && self->max_size))
    100          
4753 1           croak ("attempted decode of JSON text of %lu bytes size, but max_size is set to %lu",
4754 1           (unsigned long)self->incr_pos, (unsigned long)self->max_size);
4755              
4756 316 100         if (!INCR_DONE (self))
    100          
4757             {
4758             /* as an optimisation, do not accumulate white space in the incr buffer */
4759 46 100         if (self->incr_mode == INCR_M_WS && self->incr_pos)
    100          
4760             {
4761 4           self->incr_pos = 0;
4762 4           SvCUR_set (self->incr_text, 0);
4763             }
4764              
4765 46           break;
4766             }
4767             }
4768              
4769 271           PUTBACK; sv = decode_json (aTHX_ self->incr_text, self, &offset, NULL); SPAGAIN;
4770 267 50         XPUSHs (sv);
4771              
4772 267           endp = SvPVX(self->incr_text) + offset;
4773 267           self->incr_pos -= offset;
4774 267           self->incr_nest = 0;
4775 267           self->incr_mode = 0;
4776             #if PERL_VERSION > 9
4777 267           sv_chop (self->incr_text, (const char* const)endp);
4778             #else
4779             sv_chop (self->incr_text, (char*)endp);
4780             #endif
4781             }
4782 267 50         while (GIMME_V == G_ARRAY);
    100          
4783             }
4784              
4785             #if PERL_VERSION > 6
4786              
4787             SV *incr_text (JSON *self)
4788             ATTRS: lvalue
4789             PPCODE:
4790             {
4791             PERL_UNUSED_VAR(RETVAL);
4792 290 50         if (UNLIKELY(self->incr_pos))
4793             {
4794             /* We might want to return a copy of the rest.
4795             But incr_parse already chops the start at the end, so this can
4796             only happen on concurrent accesses to incr_parse */
4797 0           croak ("incr_text can not be called when the incremental parser already started parsing");
4798             }
4799 290 100         ST(0) = self->incr_text ? self->incr_text : &PL_sv_undef;
4800 290           XSRETURN(1);
4801             }
4802              
4803             #else
4804              
4805             SV *incr_text (JSON *self)
4806             PPCODE:
4807             {
4808             if (UNLIKELY(self->incr_pos))
4809             croak ("incr_text can not be called when the incremental parser already started parsing");
4810              
4811             ST(0) = self->incr_text ? self->incr_text : &PL_sv_undef;
4812             XSRETURN(1);
4813             }
4814              
4815             #endif
4816              
4817             void incr_skip (JSON *self)
4818             CODE:
4819             {
4820 2 50         if (self->incr_pos)
4821             {
4822 2 50         sv_chop (self->incr_text, SvPV_nolen (self->incr_text) + self->incr_pos);
4823 2           self->incr_pos = 0;
4824 2           self->incr_nest = 0;
4825 2           self->incr_mode = 0;
4826             }
4827             }
4828              
4829             void incr_reset (JSON *self)
4830             CODE:
4831             {
4832 1 50         if (self->incr_text)
4833             {
4834 1           SvREFCNT_dec (self->incr_text);
4835             }
4836 1           self->incr_text = NULL;
4837 1           self->incr_pos = 0;
4838 1           self->incr_nest = 0;
4839 1           self->incr_mode = 0;
4840             }
4841              
4842             void DESTROY (JSON *self)
4843             CODE:
4844 216           SvREFCNT_dec (self->cb_sk_object);
4845 216           SvREFCNT_dec (self->cb_object);
4846 216           SvREFCNT_dec (self->cb_sort_by);
4847 216           SvREFCNT_dec (self->incr_text);
4848              
4849             PROTOTYPES: ENABLE
4850              
4851             void encode_json (SV *scalar, SV *typesv = &PL_sv_undef)
4852             ALIAS:
4853             _to_json = 0
4854             encode_json = F_UTF8
4855             PPCODE:
4856             {
4857             JSON json;
4858 215           json_init (&json);
4859 215           json.flags |= ix;
4860 215           PUTBACK; scalar = encode_json (aTHX_ scalar, &json, typesv); SPAGAIN;
4861 215 50         XPUSHs (scalar);
4862             }
4863              
4864             void decode_json (SV *jsonstr, SV *allow_nonref = NULL, SV *typesv = NULL)
4865             ALIAS:
4866             _from_json = 0
4867             decode_json = F_UTF8
4868             PPCODE:
4869             {
4870             JSON json;
4871 216           json_init (&json);
4872 216           json.flags |= ix;
4873 216 50         if (ix && allow_nonref)
    100          
4874 9           json.flags |= F_ALLOW_NONREF;
4875 216           PUTBACK; jsonstr = decode_json (aTHX_ jsonstr, &json, 0, typesv); SPAGAIN;
4876 165 50         XPUSHs (jsonstr);
4877             }
4878