File Coverage

XS.xs
Criterion Covered Total %
statement 1577 1773 88.9
branch 1296 2004 64.6
condition n/a
subroutine n/a
pod n/a
total 2873 3777 76.0


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