JSON-XS
view release on metacpan or search on metacpan
--self->incr_nest;
break;
case '#':
self->incr_mode = INCR_M_C1;
goto incr_m_c;
}
}
}
modechange:
;
}
interrupt:
self->incr_pos = p - SvPVX (self->incr_text);
//printf ("interrupt<%.*s>\n", self->incr_pos, SvPVX(self->incr_text));//D
//printf ("return pos %d mode %d nest %d\n", self->incr_pos, self->incr_mode, self->incr_nest);//D
}
/////////////////////////////////////////////////////////////////////////////
// XS interface functions
MODULE = JSON::XS PACKAGE = JSON::XS
BOOT:
{
int i;
for (i = 0; i < 256; ++i)
decode_hexdigit [i] =
i >= '0' && i <= '9' ? i - '0'
: i >= 'a' && i <= 'f' ? i - 'a' + 10
: i >= 'A' && i <= 'F' ? i - 'A' + 10
: -1;
json_stash = gv_stashpv ("JSON::XS" , 1);
bool_stash = gv_stashpv ("Types::Serialiser::Boolean", 1);
bool_false = get_bool ("Types::Serialiser::false");
bool_true = get_bool ("Types::Serialiser::true");
sv_json = newSVpv ("JSON", 0);
SvREADONLY_on (sv_json);
CvNODEBUG_on (get_cv ("JSON::XS::incr_text", 0)); /* the debugger completely breaks lvalue subs */
}
PROTOTYPES: DISABLE
void CLONE (...)
CODE:
// as long as these writes are atomic, the race should not matter
// as existing threads either already use 0, or use the old value,
// which is sitll correct for the initial thread.
json_stash = 0;
bool_stash = 0;
bool_false = 0;
bool_true = 0;
void new (char *klass)
PPCODE:
{
SV *pv = NEWSV (0, sizeof (JSON));
SvPOK_only (pv);
json_init ((JSON *)SvPVX (pv));
XPUSHs (sv_2mortal (sv_bless (
newRV_noinc (pv),
strEQ (klass, "JSON::XS") ? JSON_STASH : gv_stashpv (klass, 1)
)));
}
void boolean_values (JSON *self, SV *v_false = 0, SV *v_true = 0)
PPCODE:
self->v_false = newSVsv (v_false);
self->v_true = newSVsv (v_true);
XPUSHs (ST (0));
void get_boolean_values (JSON *self)
PPCODE:
if (self->v_false && self->v_true)
{
EXTEND (SP, 2);
PUSHs (self->v_false);
PUSHs (self->v_true);
}
void ascii (JSON *self, int enable = 1)
ALIAS:
ascii = F_ASCII
latin1 = F_LATIN1
utf8 = F_UTF8
indent = F_INDENT
canonical = F_CANONICAL
space_before = F_SPACE_BEFORE
space_after = F_SPACE_AFTER
pretty = F_PRETTY
allow_nonref = F_ALLOW_NONREF
shrink = F_SHRINK
allow_blessed = F_ALLOW_BLESSED
convert_blessed = F_CONV_BLESSED
relaxed = F_RELAXED
allow_unknown = F_ALLOW_UNKNOWN
allow_tags = F_ALLOW_TAGS
PPCODE:
{
if (enable)
self->flags |= ix;
else
self->flags &= ~ix;
XPUSHs (ST (0));
}
void get_ascii (JSON *self)
ALIAS:
get_ascii = F_ASCII
get_latin1 = F_LATIN1
get_utf8 = F_UTF8
get_indent = F_INDENT
get_canonical = F_CANONICAL
get_space_before = F_SPACE_BEFORE
get_space_after = F_SPACE_AFTER
get_allow_nonref = F_ALLOW_NONREF
get_shrink = F_SHRINK
get_allow_blessed = F_ALLOW_BLESSED
get_convert_blessed = F_CONV_BLESSED
get_relaxed = F_RELAXED
get_allow_unknown = F_ALLOW_UNKNOWN
get_allow_tags = F_ALLOW_TAGS
PPCODE:
XPUSHs (boolSV (self->flags & ix));
void max_depth (JSON *self, U32 max_depth = 0x80000000UL)
PPCODE:
self->max_depth = max_depth;
XPUSHs (ST (0));
U32 get_max_depth (JSON *self)
CODE:
RETVAL = self->max_depth;
OUTPUT:
RETVAL
void max_size (JSON *self, U32 max_size = 0)
PPCODE:
self->max_size = max_size;
XPUSHs (ST (0));
int get_max_size (JSON *self)
CODE:
RETVAL = self->max_size;
OUTPUT:
RETVAL
void filter_json_object (JSON *self, SV *cb = &PL_sv_undef)
PPCODE:
{
SvREFCNT_dec (self->cb_object);
self->cb_object = SvOK (cb) ? newSVsv (cb) : 0;
XPUSHs (ST (0));
}
void filter_json_single_key_object (JSON *self, SV *key, SV *cb = &PL_sv_undef)
PPCODE:
{
if (!self->cb_sk_object)
self->cb_sk_object = newHV ();
if (SvOK (cb))
hv_store_ent (self->cb_sk_object, key, newSVsv (cb), 0);
else
{
hv_delete_ent (self->cb_sk_object, key, G_DISCARD, 0);
if (!HvKEYS (self->cb_sk_object))
{
SvREFCNT_dec (self->cb_sk_object);
self->cb_sk_object = 0;
}
}
XPUSHs (ST (0));
}
void encode (JSON *self, SV *scalar)
PPCODE:
PUTBACK; scalar = encode_json (scalar, self); SPAGAIN;
XPUSHs (scalar);
void decode (JSON *self, SV *jsonstr)
PPCODE:
PUTBACK; jsonstr = decode_json (jsonstr, self, 0); SPAGAIN;
XPUSHs (jsonstr);
void decode_prefix (JSON *self, SV *jsonstr)
PPCODE:
{
SV *sv;
STRLEN offset;
PUTBACK; sv = decode_json (jsonstr, self, &offset); SPAGAIN;
EXTEND (SP, 2);
PUSHs (sv);
PUSHs (sv_2mortal (newSVuv (ptr_to_index (jsonstr, SvPV_nolen (jsonstr) + offset))));
}
void incr_parse (JSON *self, SV *jsonstr = 0)
PPCODE:
{
if (!self->incr_text)
self->incr_text = newSVpvn ("", 0);
/* if utf8-ness doesn't match the decoder, need to upgrade/downgrade */
if (!DECODE_WANTS_OCTETS (self) == !SvUTF8 (self->incr_text))
if (DECODE_WANTS_OCTETS (self))
{
if (self->incr_pos)
self->incr_pos = utf8_length ((U8 *)SvPVX (self->incr_text),
(U8 *)SvPVX (self->incr_text) + self->incr_pos);
sv_utf8_downgrade (self->incr_text, 0);
}
else
{
sv_utf8_upgrade (self->incr_text);
if (self->incr_pos)
self->incr_pos = utf8_hop ((U8 *)SvPVX (self->incr_text), self->incr_pos)
- (U8 *)SvPVX (self->incr_text);
}
// append data, if any
if (jsonstr)
{
/* make sure both strings have same encoding */
if (SvUTF8 (jsonstr) != SvUTF8 (self->incr_text))
if (SvUTF8 (jsonstr))
sv_utf8_downgrade (jsonstr, 0);
else
sv_utf8_upgrade (jsonstr);
/* and then just blindly append */
{
STRLEN len;
const char *str = SvPV (jsonstr, len);
STRLEN cur = SvCUR (self->incr_text);
if (SvLEN (self->incr_text) - cur <= len)
json_sv_grow (self->incr_text, cur, len);
Move (str, SvEND (self->incr_text), len, char);
SvCUR_set (self->incr_text, SvCUR (self->incr_text) + len);
*SvEND (self->incr_text) = 0; // this should basically be a nop, too, but make sure it's there
}
}
if (GIMME_V != G_VOID)
do
{
SV *sv;
STRLEN offset;
if (!INCR_DONE (self))
{
incr_parse (self);
if (self->incr_pos > self->max_size && self->max_size)
croak ("attempted decode of JSON text of %lu bytes size, but max_size is set to %lu",
}
}
PUTBACK; sv = decode_json (self->incr_text, self, &offset); SPAGAIN;
XPUSHs (sv);
self->incr_pos -= offset;
self->incr_nest = 0;
self->incr_mode = 0;
sv_chop (self->incr_text, SvPVX (self->incr_text) + offset);
}
while (GIMME_V == G_ARRAY);
}
SV *incr_text (JSON *self)
ATTRS: lvalue
CODE:
{
if (self->incr_pos)
croak ("incr_text can not be called when the incremental parser already started parsing");
RETVAL = self->incr_text ? SvREFCNT_inc (self->incr_text) : &PL_sv_undef;
}
OUTPUT:
RETVAL
void incr_skip (JSON *self)
CODE:
{
if (self->incr_pos)
{
sv_chop (self->incr_text, SvPV_nolen (self->incr_text) + self->incr_pos);
self->incr_pos = 0;
self->incr_nest = 0;
self->incr_mode = 0;
}
}
void incr_reset (JSON *self)
CODE:
{
SvREFCNT_dec (self->incr_text);
self->incr_text = 0;
self->incr_pos = 0;
self->incr_nest = 0;
self->incr_mode = 0;
}
void DESTROY (JSON *self)
CODE:
SvREFCNT_dec (self->v_false);
SvREFCNT_dec (self->v_true);
SvREFCNT_dec (self->cb_sk_object);
SvREFCNT_dec (self->cb_object);
SvREFCNT_dec (self->incr_text);
PROTOTYPES: ENABLE
void encode_json (SV *scalar)
PPCODE:
{
JSON json;
json_init (&json);
json.flags |= F_UTF8;
PUTBACK; scalar = encode_json (scalar, &json); SPAGAIN;
XPUSHs (scalar);
}
void decode_json (SV *jsonstr)
PPCODE:
{
JSON json;
json_init (&json);
json.flags |= F_UTF8;
PUTBACK; jsonstr = decode_json (jsonstr, &json, 0); SPAGAIN;
XPUSHs (jsonstr);
}
( run in 0.548 second using v1.01-cache-2.11-cpan-5511b514fd6 )