JSON-SIMD

 view release on metacpan or  search on metacpan

SIMD.xs  view on Meta::CPAN


                    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::SIMD		PACKAGE = JSON::SIMD

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::SIMD"                , 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);

        simdjson_global_init();

        CvNODEBUG_on (get_cv ("JSON::SIMD::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::SIMD") ? JSON_STASH : gv_stashpv (klass, 1)
        )));
}

void boolean_values (JSON *self, SV *v_false = 0, SV *v_true = 0)
	PPCODE:
        self->flags   &= ~F_CORE_BOOLS;
        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 core_bools (JSON *self, int enable = 1)
	PPCODE:
        if (enable)
          {
            self->flags   |= F_CORE_BOOLS;
            self->v_false = newSVsv (&PL_sv_no);
            self->v_true  = newSVsv (&PL_sv_yes);
          }
        else
          {
            self->flags   &= ~F_CORE_BOOLS;
            self->v_false = 0;
            self->v_true  = 0;
          }
        XPUSHs (ST (0));

void get_core_bools (JSON *self)
	PPCODE:
{
        int result = self->flags & F_CORE_BOOLS;
#if PERL_VERSION_GE(5,36,0)
        if (self->v_false && self->v_true && SvIsBOOL(self->v_false) && SvIsBOOL(self->v_true))
          {
            result = F_CORE_BOOLS;
          }
#endif
        XPUSHs (boolSV (result));
}

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
        use_simdjson      = F_USE_SIMDJSON
        encode_core_bools = F_ENCODE_CORE_BOOLS
	PPCODE:
{
        if (enable)
          self->flags |=  ix;
        else
          self->flags &= ~ix;

        if (self->flags & F_USE_SIMDJSON && self->flags & F_ALLOW_TAGS)
          self->flags &= ~F_USE_SIMDJSON;
        if (self->flags & F_USE_SIMDJSON && self->flags & F_RELAXED)
          self->flags &= ~F_USE_SIMDJSON;

        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
        get_use_simdjson      = F_USE_SIMDJSON
        get_encode_core_bools = F_ENCODE_CORE_BOOLS
	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, 0); SPAGAIN;
        XPUSHs (jsonstr);

void decode_prefix (JSON *self, SV *jsonstr)
	PPCODE:
{
	SV *sv;
        STRLEN offset;
        PUTBACK; sv = decode_json (jsonstr, self, &offset, 0); SPAGAIN;
        EXTEND (SP, 2);
        PUSHs (sv);
        PUSHs (sv_2mortal (newSVuv (ptr_to_index (jsonstr, SvPV_nolen (jsonstr) + offset))));
}

void decode_at_pointer (JSON *self, SV *jsonstr, SV *path)
	PPCODE:
        PUTBACK; jsonstr = decode_json (jsonstr, self, 0, path); SPAGAIN;
        XPUSHs (jsonstr);

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",

SIMD.xs  view on Meta::CPAN

                    }
                }

              PUTBACK; sv = decode_json (self->incr_text, self, &offset, 0); 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_LIST);
}

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, 0); SPAGAIN;
        XPUSHs (jsonstr);
}

void simdjson_version ()
	PPCODE:
{
        SV *version_info;
        PUTBACK; version_info = simdjson_get_version(); SPAGAIN;
        XPUSHs (version_info);
}

void is_core_bool (SV *scalar)
	PPCODE:
{
#if PERL_VERSION_GE(5,36,0)
        XPUSHs( boolSV( SvIsBOOL( scalar )));
#else
        XPUSHs( boolSV( 0 ));
#endif
}



( run in 0.762 second using v1.01-cache-2.11-cpan-5511b514fd6 )