yeptris 0.6.8.2-aarch64-linux → 0.6.9.2-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/yeptris_native/cbor_ruby.c +134 -0
- data/ext/yeptris_native/yeptris_native.c +14 -0
- data/lib/yeptris/cbor.rb +7 -0
- data/lib/yeptris/ffi.rb +8 -2
- data/lib/yeptris/json.rb +1 -0
- data/lib/yeptris/native-3.3.so +0 -0
- data/lib/yeptris.rb +1 -1
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- data/vendor/libyeptris/src/include/yeptris/tape.h +31 -7
- data/vendor/libyeptris/src/yeptris/plan.c +3 -0
- data/vendor/libyeptris/src/yeptris/tape.c +45 -29
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: de9190cb1b45e6e54c7adf24792a90110c20c0bad9a6e2ef07bc028f1b8227e9
|
|
4
|
+
data.tar.gz: 389b84e8a518250c9f2d74bda218ed958fbb3c67678f2cf7272a3d71f2312d43
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 87ddaf244d1bb123e09fda719a3efe89e61fc6028928eae24044b9518a8c75376cfdc69451d3fd27692c760c26bd1f847200526b8517eefdafe7e745764cf761
|
|
7
|
+
data.tar.gz: 46e02cf83871371caee306ac22cc4ce51e76fe9f2f62a6e3346bbc58e0af9cdc1dec0b81bfa500d58ca5fa33dab7aa5996725713f08545ce6e3209d24ffc9db6
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/* cbor_ruby.c — CBOR decode → Ruby VALUE in one C pass (#157).
|
|
2
|
+
*
|
|
3
|
+
* The FFI ladder's CBOR.load pays decode + a Marshal emit/load round
|
|
4
|
+
* trip; this walks the decoded DOM directly, building the same VALUEs
|
|
5
|
+
* the materializer builds (tag-driven scalar semantics, insertion-
|
|
6
|
+
* order mappings), with no intermediate representation.
|
|
7
|
+
*/
|
|
8
|
+
#include <ruby.h>
|
|
9
|
+
/* rb_hash_new_capa is Ruby 3.2+; older Rubies grow dynamically (the
|
|
10
|
+
* json_ruby.c guard, verbatim). */
|
|
11
|
+
#if RUBY_API_VERSION_MAJOR > 3 || (RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR >= 2)
|
|
12
|
+
#define HASH_NEW_CAPA(n) rb_hash_new_capa(n)
|
|
13
|
+
#else
|
|
14
|
+
#define HASH_NEW_CAPA(n) rb_hash_new()
|
|
15
|
+
#endif
|
|
16
|
+
#include <ruby/encoding.h>
|
|
17
|
+
#include <stdlib.h>
|
|
18
|
+
#include <string.h>
|
|
19
|
+
|
|
20
|
+
#include "dom/dom.h"
|
|
21
|
+
#include "doc.h" /* the public YeptrisDocument wrapper: ->dom */
|
|
22
|
+
#include <yeptris/cbor.h>
|
|
23
|
+
#include <yeptris/dom.h>
|
|
24
|
+
#include <yeptris/resolve.h>
|
|
25
|
+
|
|
26
|
+
static const char* cr_view(const yep_dom* d, yep_sview sv, uint32_t* len) {
|
|
27
|
+
*len = sv.len;
|
|
28
|
+
if (sv.len == 0) {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
return (sv.off & YEP_SV_INPUT) ? (d->str + (sv.off & YEP_SV_OFF)) : (d->input_base + sv.off);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static VALUE cr_scalar(const yep_dom* d, const yep_dnode* n) {
|
|
35
|
+
uint32_t len = 0;
|
|
36
|
+
const char* p = cr_view(d, n->value, &len);
|
|
37
|
+
switch (n->tag_id) {
|
|
38
|
+
case YEPTRIS_TAG_NULL:
|
|
39
|
+
return Qnil;
|
|
40
|
+
case YEPTRIS_TAG_BOOL:
|
|
41
|
+
if (len == 1) { /* Psych: "y"/"n" stay Strings */
|
|
42
|
+
return rb_utf8_str_new(p, len);
|
|
43
|
+
}
|
|
44
|
+
return (len == 4 && memcmp(p, "true", 4) == 0) ? Qtrue : Qfalse;
|
|
45
|
+
case YEPTRIS_TAG_INT: {
|
|
46
|
+
char buf[32];
|
|
47
|
+
size_t cp = len < sizeof(buf) - 1 ? len : sizeof(buf) - 1;
|
|
48
|
+
memcpy(buf, p, cp);
|
|
49
|
+
buf[cp] = '\0';
|
|
50
|
+
char* end = NULL;
|
|
51
|
+
long long v = strtoll(buf, &end, 10);
|
|
52
|
+
if (end != buf && *end == '\0' && end == buf + len && v > INT64_MIN) {
|
|
53
|
+
return LL2NUM(v);
|
|
54
|
+
}
|
|
55
|
+
return rb_utf8_str_new(p, len); /* int_or_string's fallback */
|
|
56
|
+
}
|
|
57
|
+
case YEPTRIS_TAG_FLOAT: {
|
|
58
|
+
char buf[64];
|
|
59
|
+
size_t cp = len < sizeof(buf) - 1 ? len : sizeof(buf) - 1;
|
|
60
|
+
memcpy(buf, p, cp);
|
|
61
|
+
buf[cp] = '\0';
|
|
62
|
+
char* end = NULL;
|
|
63
|
+
double v = strtod(buf, &end);
|
|
64
|
+
if (end != buf && end != buf + len) {
|
|
65
|
+
return rb_utf8_str_new(p, len); /* float_or_string's fallback */
|
|
66
|
+
}
|
|
67
|
+
return DBL2NUM(v);
|
|
68
|
+
}
|
|
69
|
+
default:
|
|
70
|
+
return rb_utf8_str_new(p, len);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static VALUE cr_walk(const yep_dom* d, uint32_t id) {
|
|
75
|
+
const yep_dnode* n = &d->nodes[id];
|
|
76
|
+
switch (n->kind) {
|
|
77
|
+
case YEP_DOM_SCALAR:
|
|
78
|
+
return cr_scalar(d, n);
|
|
79
|
+
case YEP_DOM_SEQUENCE: {
|
|
80
|
+
long cnt = (long)n->count;
|
|
81
|
+
VALUE a = rb_ary_new_capa(cnt);
|
|
82
|
+
uint32_t c = n->first_child;
|
|
83
|
+
for (long i = 0; i < cnt && c != UINT32_MAX; i++) {
|
|
84
|
+
rb_ary_push(a, cr_walk(d, c));
|
|
85
|
+
c = d->nodes[c].next_sibling;
|
|
86
|
+
}
|
|
87
|
+
return a;
|
|
88
|
+
}
|
|
89
|
+
case YEP_DOM_MAPPING: {
|
|
90
|
+
long pairs = (long)(n->count / 2);
|
|
91
|
+
VALUE h = HASH_NEW_CAPA(pairs);
|
|
92
|
+
uint32_t c = n->first_child;
|
|
93
|
+
for (long i = 0; i < pairs && c != UINT32_MAX; i++) {
|
|
94
|
+
VALUE k = cr_walk(d, c);
|
|
95
|
+
c = d->nodes[c].next_sibling;
|
|
96
|
+
VALUE v = (c != UINT32_MAX) ? cr_walk(d, c) : Qnil;
|
|
97
|
+
if (c != UINT32_MAX) {
|
|
98
|
+
c = d->nodes[c].next_sibling;
|
|
99
|
+
}
|
|
100
|
+
rb_hash_aset(h, k, v);
|
|
101
|
+
}
|
|
102
|
+
return h;
|
|
103
|
+
}
|
|
104
|
+
default: /* ALIAS: CBOR decode never produces one */
|
|
105
|
+
return Qnil;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
VALUE yep_rb_cbor_load(const char* p, size_t len, int strict) {
|
|
110
|
+
YeptrisStatus st = YEPTRIS_OK;
|
|
111
|
+
/* the DOM borrows the input buffer zero-copy; the walk ALLOCATES,
|
|
112
|
+
* and a GC compaction mid-walk moves the caller's String — the
|
|
113
|
+
* borrowed base dangles (the #160 CI bus error on 3.2/linux).
|
|
114
|
+
* Same discipline as the JSON walk: GC off across decode+walk */
|
|
115
|
+
VALUE gc_on = rb_gc_disable();
|
|
116
|
+
/* YeptrisDocument is a WRAPPER (doc.h) — ->dom is the tree; a raw
|
|
117
|
+
* yep_dom* cast read the wrapper's fields as the dom (the CI
|
|
118
|
+
* segfaults: docs at the wrong offset) */
|
|
119
|
+
yeptris_document* doc = (yeptris_document*)yeptris_cbor_decode(
|
|
120
|
+
p, len, strict ? YEPTRIS_CBOR_STRICT : 0, &st);
|
|
121
|
+
yep_dom* d = (doc != NULL) ? doc->dom : NULL;
|
|
122
|
+
if (d == NULL) {
|
|
123
|
+
if (RTEST(gc_on)) {
|
|
124
|
+
rb_gc_enable();
|
|
125
|
+
}
|
|
126
|
+
return Qundef;
|
|
127
|
+
}
|
|
128
|
+
VALUE v = (d->dcount > 0 && d->docs[0] != UINT32_MAX) ? cr_walk(d, d->docs[0]) : Qnil;
|
|
129
|
+
yeptris_document_free((YeptrisDocument)doc);
|
|
130
|
+
if (RTEST(gc_on)) {
|
|
131
|
+
rb_gc_enable();
|
|
132
|
+
}
|
|
133
|
+
return v;
|
|
134
|
+
}
|
|
@@ -230,6 +230,7 @@ static const YeptrisVisitVTable k_vt = {
|
|
|
230
230
|
|
|
231
231
|
/* fused JSON→Ruby (json_ruby.c) — no vtable, beats JSON.parse */
|
|
232
232
|
VALUE yep_rb_parse_json(const char* p, size_t len, int strict_dup);
|
|
233
|
+
VALUE yep_rb_cbor_load(const char* p, size_t len, int strict);
|
|
233
234
|
|
|
234
235
|
static VALUE ctx_result(rb_ctx* c, YeptrisStatus st) {
|
|
235
236
|
if (st != YEPTRIS_OK || c->failed) {
|
|
@@ -244,6 +245,18 @@ static VALUE ctx_result(rb_ctx* c, YeptrisStatus st) {
|
|
|
244
245
|
return c->root;
|
|
245
246
|
}
|
|
246
247
|
|
|
248
|
+
static VALUE native_cbor_load(int argc, VALUE* argv, VALUE self) {
|
|
249
|
+
(void)self;
|
|
250
|
+
VALUE input, strict;
|
|
251
|
+
rb_scan_args(argc, argv, "11", &input, &strict);
|
|
252
|
+
StringValue(input);
|
|
253
|
+
VALUE v = yep_rb_cbor_load(RSTRING_PTR(input), (size_t)RSTRING_LEN(input), RTEST(strict));
|
|
254
|
+
if (v == Qundef) {
|
|
255
|
+
rb_raise(rb_path2class("Yeptris::ParseError"), "native cbor decode failed");
|
|
256
|
+
}
|
|
257
|
+
return v;
|
|
258
|
+
}
|
|
259
|
+
|
|
247
260
|
static VALUE native_load_json(int argc, VALUE* argv, VALUE self) {
|
|
248
261
|
(void)self;
|
|
249
262
|
VALUE input, strict;
|
|
@@ -415,6 +428,7 @@ RUBY_FUNC_EXPORTED void Init_native(void) {
|
|
|
415
428
|
VALUE mYep = rb_define_module("Yeptris");
|
|
416
429
|
VALUE mNat = rb_define_module_under(mYep, "Native");
|
|
417
430
|
rb_define_singleton_method(mNat, "load_json", native_load_json, -1);
|
|
431
|
+
rb_define_singleton_method(mNat, "cbor_load", native_cbor_load, -1);
|
|
418
432
|
rb_define_singleton_method(mNat, "load", native_load, 2);
|
|
419
433
|
rb_define_singleton_method(mNat, "load_stream", native_load_stream, 2);
|
|
420
434
|
rb_define_singleton_method(mNat, "gc_mode", native_gc_mode, 0);
|
data/lib/yeptris/cbor.rb
CHANGED
|
@@ -26,6 +26,13 @@ module Yeptris
|
|
|
26
26
|
def load(data, strict: false)
|
|
27
27
|
raise Error, "libyeptris has no CBOR support" unless available?
|
|
28
28
|
|
|
29
|
+
# #157: the native materializer (decode + direct VALUE
|
|
30
|
+
# construction in one C pass) when the extension is loaded;
|
|
31
|
+
# the FFI ladder otherwise
|
|
32
|
+
if defined?(::Yeptris::Native) && ::Yeptris::Native.respond_to?(:cbor_load)
|
|
33
|
+
return ::Yeptris::Native.cbor_load(data, strict)
|
|
34
|
+
end
|
|
35
|
+
|
|
29
36
|
doc_ptr = ::Yeptris::FFI.yeptris_cbor_decode(data, data.bytesize, strict ? STRICT : 0, nil)
|
|
30
37
|
raise ParseError, ::Yeptris::FFI.last_error_message if doc_ptr.null?
|
|
31
38
|
|
data/lib/yeptris/ffi.rb
CHANGED
|
@@ -66,10 +66,16 @@ module Yeptris
|
|
|
66
66
|
# the caller's string (no arena copy, no second validating parse).
|
|
67
67
|
# v2 records: numbers are spans at parse; yeptris_tape_convert
|
|
68
68
|
# materializes them in one bulk call.
|
|
69
|
+
# v3 (libyeptris 0.6.9): the interleaved records (recs) are the
|
|
70
|
+
# primary storage on the lenient route; the strict route keeps the
|
|
71
|
+
# columns eager. The layout MUST mirror yeptris_json_tape — a stale
|
|
72
|
+
# layout makes C write past the FFI buffer (a silent heap overflow
|
|
73
|
+
# that only some allocators catch; the 0.6.9.1 windows crash).
|
|
69
74
|
class JsonTape < ::FFI::Struct
|
|
70
75
|
layout :count, :size_t, :kinds, :pointer, :offs, :pointer,
|
|
71
|
-
:lens, :pointer, :
|
|
72
|
-
:
|
|
76
|
+
:lens, :pointer, :recs, :pointer, :_cols_ready, :int,
|
|
77
|
+
:_rec_primary, :int, :int_min, :int64, :_src, :pointer,
|
|
78
|
+
:_srclen, :size_t, :_block, :pointer
|
|
73
79
|
end
|
|
74
80
|
|
|
75
81
|
attach_function :yeptris_parse_json_tape, %i[pointer size_t pointer], :int
|
data/lib/yeptris/json.rb
CHANGED
|
@@ -24,6 +24,7 @@ module Yeptris
|
|
|
24
24
|
# behavior — strictness follows it (issue #37, found by canon's
|
|
25
25
|
# CI where json 3.0.0 resolved while the dev box had 2.x).
|
|
26
26
|
require "json"
|
|
27
|
+
require "date" # place_obj's `when Date` — psych loads it elsewhere, JSON.dump must not depend on that
|
|
27
28
|
STRICT_DUPLICATE_KEYS = Gem::Version.new(::JSON::VERSION) >= Gem::Version.new("3")
|
|
28
29
|
|
|
29
30
|
module_function
|
data/lib/yeptris/native-3.3.so
CHANGED
|
Binary file
|
data/lib/yeptris.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Yeptris
|
|
4
4
|
# The gem's version lives in the parent namespace's file — the last
|
|
5
5
|
# internal require (yeptris/version) retired with it.
|
|
6
|
-
VERSION = "0.6.
|
|
6
|
+
VERSION = "0.6.9.2".freeze
|
|
7
7
|
# The error hierarchy lives in THIS file (the parent namespace's
|
|
8
8
|
# own file): nested constants do not trigger a parent-constant
|
|
9
9
|
# autoload, and the law forbids internal requires — defining the
|
data/libyeptris.so
CHANGED
|
Binary file
|
|
@@ -46,15 +46,32 @@ enum {
|
|
|
46
46
|
spans; simdjson's deferred contract) */
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
+
/* The interleaved record (TODO.max-perf/07): one 8-byte store per
|
|
50
|
+
* token instead of three column stores. Layout: off:u32 | len:u23 |
|
|
51
|
+
* kind:u8 — a span longer than 0xFEFFFF bytes carries len == 0xFFFFFF
|
|
52
|
+
* with the true length stored as a CONT-terminated extension record
|
|
53
|
+
* (kind YEP_T_CONT; unreachable for <16 MiB tokens). The columns
|
|
54
|
+
* stay the compatibility ABI: yeptris_tape_columns materializes them
|
|
55
|
+
* lazily from the records on first touch. */
|
|
56
|
+
#define YEP_T_CONT 8 /* record-length extension (not a token kind) */
|
|
57
|
+
typedef uint64_t yeptris_tape_rec;
|
|
58
|
+
|
|
49
59
|
typedef struct yeptris_json_tape {
|
|
50
60
|
size_t count;
|
|
51
|
-
uint8_t* kinds;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
uint8_t* kinds; /* compat columns — materialized lazily (see
|
|
62
|
+
yeptris_tape_columns) when the interleaved
|
|
63
|
+
records are the primary storage */
|
|
64
|
+
uint32_t* offs; /* span starts (STR/INT/FLOAT); container links */
|
|
65
|
+
uint32_t* lens; /* span lengths (STR/INT/FLOAT) */
|
|
66
|
+
yeptris_tape_rec* recs; /* primary storage (may be NULL on legacy
|
|
67
|
+
column-built tapes: the strict route) */
|
|
68
|
+
int _cols_ready; /* columns materialized from recs already */
|
|
69
|
+
int _rec_primary; /* the lenient route: recs carry the data and
|
|
70
|
+
the columns are lazy */
|
|
71
|
+
int64_t int_min; /* set by yeptris_tape_convert when an INT span
|
|
72
|
+
exceeds int64 (materialize-time discovery) */
|
|
73
|
+
const void* _src; /* the parsed buffer (spans borrow it; it must
|
|
74
|
+
outlive the tape — same contract as the spans) */
|
|
58
75
|
size_t _srclen;
|
|
59
76
|
void* _block; /* the carved allocation base */
|
|
60
77
|
} yeptris_json_tape;
|
|
@@ -89,6 +106,13 @@ YEPTRIS_API void yeptris_tape_free(yeptris_json_tape* tape);
|
|
|
89
106
|
* number records converted, or SIZE_MAX if a span does not re-scan
|
|
90
107
|
* as a number (impossible for a tape this library produced).
|
|
91
108
|
* Sets t->int_min when an INT span exceeds int64. */
|
|
109
|
+
/* Materializes the kinds/offs/lens columns from the interleaved
|
|
110
|
+
* records (no-op when the tape was built column-primary or the
|
|
111
|
+
* columns are already materialized). Consumers reading the column
|
|
112
|
+
* pointers directly (the FFI binding) must call this once first.
|
|
113
|
+
* Returns 0 on success, nonzero on allocation failure. */
|
|
114
|
+
YEPTRIS_API int yeptris_tape_columns(yeptris_json_tape* t);
|
|
115
|
+
|
|
92
116
|
YEPTRIS_API size_t yeptris_tape_convert(yeptris_json_tape* t, size_t from, size_t to,
|
|
93
117
|
int64_t* ivals, double* dvals);
|
|
94
118
|
|
|
@@ -415,6 +415,9 @@ static yeptris_plan_result* plan_result_carve(const yeptris_plan* plan, size_t r
|
|
|
415
415
|
|
|
416
416
|
YEPTRIS_API yeptris_plan_result*
|
|
417
417
|
yeptris_tape_plan_walk(const yeptris_json_tape* tape, const yeptris_plan* plan, YeptrisStatus* st) {
|
|
418
|
+
/* item 07: the lenient tape's columns are lazy — materialize (a
|
|
419
|
+
* cache write through a const view; idempotent) */
|
|
420
|
+
yeptris_tape_columns((yeptris_json_tape*)tape);
|
|
418
421
|
if (st != NULL) {
|
|
419
422
|
*st = YEPTRIS_OK;
|
|
420
423
|
}
|
|
@@ -59,7 +59,8 @@ static int rec_put(tape_ctx* c, uint8_t kind, uint32_t off, uint32_t len) {
|
|
|
59
59
|
static YeptrisStatus tape_carve(yeptris_json_tape* t, size_t len) {
|
|
60
60
|
size_t cap = len + 2;
|
|
61
61
|
size_t off_o = (cap + 15) & ~(size_t)15;
|
|
62
|
-
char* block = yep_alloc(yep_system_allocator(),
|
|
62
|
+
char* block = yep_alloc(yep_system_allocator(),
|
|
63
|
+
off_o + 2 * cap * sizeof(uint32_t) + cap * sizeof(yeptris_tape_rec));
|
|
63
64
|
if (block == NULL) {
|
|
64
65
|
return YEPTRIS_ERROR_MEMORY;
|
|
65
66
|
}
|
|
@@ -67,11 +68,31 @@ static YeptrisStatus tape_carve(yeptris_json_tape* t, size_t len) {
|
|
|
67
68
|
t->kinds = (uint8_t*)block;
|
|
68
69
|
t->offs = (uint32_t*)(void*)(block + off_o);
|
|
69
70
|
t->lens = t->offs + cap;
|
|
71
|
+
t->recs = (yeptris_tape_rec*)(void*)(t->lens + cap);
|
|
70
72
|
t->count = 0;
|
|
71
73
|
t->int_min = 0;
|
|
74
|
+
t->_rec_primary = 0;
|
|
75
|
+
t->_cols_ready = 0;
|
|
72
76
|
return YEPTRIS_OK;
|
|
73
77
|
}
|
|
74
78
|
|
|
79
|
+
/* The lazy column materialization (TODO.max-perf/07): records are the
|
|
80
|
+
* primary storage on the lenient route; the column ABI materializes
|
|
81
|
+
* from them on first touch. */
|
|
82
|
+
YEPTRIS_API int yeptris_tape_columns(yeptris_json_tape* t) {
|
|
83
|
+
if (t == NULL || !t->_rec_primary || t->recs == NULL || t->_cols_ready) {
|
|
84
|
+
return 0; /* column-primary (the strict route) or ready */
|
|
85
|
+
}
|
|
86
|
+
for (size_t i = 0; i < t->count; i++) {
|
|
87
|
+
yeptris_tape_rec r = t->recs[i];
|
|
88
|
+
t->lens[i] = (uint32_t)((r >> 8) & 0xFFFFFFu);
|
|
89
|
+
t->offs[i] = (uint32_t)(r >> 32);
|
|
90
|
+
t->kinds[i] = (uint8_t)(r & 0xFFu);
|
|
91
|
+
}
|
|
92
|
+
t->_cols_ready = 1;
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
75
96
|
/* Scalar roots: the walk needs an opener, so a bare root value
|
|
76
97
|
* converts through the same kernels. */
|
|
77
98
|
static int tape_put_root_scalar(tape_ctx* c, const char* p, size_t len, size_t at) {
|
|
@@ -585,20 +606,18 @@ static YeptrisStatus tape_walk_lnt_fused(const char* p, size_t len, size_t open,
|
|
|
585
606
|
if (tape_carve(t, len) != YEPTRIS_OK) {
|
|
586
607
|
return YEPTRIS_ERROR_MEMORY;
|
|
587
608
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
609
|
+
/* the interleaved records are the primary storage (item 07); the
|
|
610
|
+
* columns materialize lazily via yeptris_tape_columns */
|
|
611
|
+
t->_rec_primary = 1;
|
|
612
|
+
yeptris_tape_rec* recs = t->recs;
|
|
591
613
|
uint32_t open_at[YEP_JSON_WALK_DEPTH];
|
|
592
614
|
uint8_t kind[YEP_JSON_WALK_DEPTH];
|
|
593
615
|
|
|
594
|
-
|
|
595
|
-
offs[0] = 0;
|
|
596
|
-
lens[0] = 0;
|
|
616
|
+
recs[0] = ((uint64_t)0 << 32) | ((uint64_t)0 << 8) | YEP_T_DOC;
|
|
597
617
|
|
|
598
618
|
uint8_t top_kind = p[open] == '[' ? 0 : 1;
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
lens[1] = 0;
|
|
619
|
+
recs[1] =
|
|
620
|
+
((uint64_t)0 << 32) | ((uint64_t)0 << 8) | (top_kind ? YEP_T_MAP_OPEN : YEP_T_SEQ_OPEN);
|
|
602
621
|
uint32_t top_open = 1;
|
|
603
622
|
size_t count = 2;
|
|
604
623
|
uint8_t top_expect = top_kind ? JW_KEY_OR_CLOSE : JW_VALUE_OR_CLOSE;
|
|
@@ -656,9 +675,8 @@ static YeptrisStatus tape_walk_lnt_fused(const char* p, size_t len, size_t open,
|
|
|
656
675
|
uint64_t c0 = (w - 0x2020202020202020ull) & ~w & 0x8080808080808080ull;
|
|
657
676
|
if (qm != 0 && ((bm | c0) & (qm - 1)) == 0) {
|
|
658
677
|
close = j + (size_t)yep_ctz64(qm) / 8;
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
lens[count] = (uint32_t)(close - j);
|
|
678
|
+
recs[count] = ((uint64_t)((uint32_t)j) << 32) |
|
|
679
|
+
((uint64_t)((uint32_t)(close - j)) << 8) | (uint64_t)(YEP_T_STR);
|
|
662
680
|
count++;
|
|
663
681
|
i = close + 1;
|
|
664
682
|
goto lstr_done;
|
|
@@ -668,9 +686,8 @@ static YeptrisStatus tape_walk_lnt_fused(const char* p, size_t len, size_t open,
|
|
|
668
686
|
if (!yep_json_string(p, len, &i, &close, &esc)) {
|
|
669
687
|
goto lreject;
|
|
670
688
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
lens[count] = (uint32_t)(close - at - 1);
|
|
689
|
+
recs[count] = ((uint64_t)((uint32_t)(at + 1)) << 32) |
|
|
690
|
+
((uint64_t)((uint32_t)(close - at - 1)) << 8) | (uint64_t)(YEP_T_STR);
|
|
674
691
|
count++;
|
|
675
692
|
lstr_done:
|
|
676
693
|
if (key_slot) {
|
|
@@ -698,9 +715,8 @@ static YeptrisStatus tape_walk_lnt_fused(const char* p, size_t len, size_t open,
|
|
|
698
715
|
}
|
|
699
716
|
break;
|
|
700
717
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
lens[count] = (uint32_t)(i - at);
|
|
718
|
+
recs[count] = ((uint64_t)((uint32_t)at) << 32) | ((uint64_t)((uint32_t)(i - at)) << 8) |
|
|
719
|
+
(uint64_t)(YEP_T_NUM);
|
|
704
720
|
count++;
|
|
705
721
|
lcomma:
|
|
706
722
|
if (i < len && p[i] == ',') {
|
|
@@ -719,10 +735,11 @@ static YeptrisStatus tape_walk_lnt_fused(const char* p, size_t len, size_t open,
|
|
|
719
735
|
top_expect != JW_COMMA_OR_CLOSE)) {
|
|
720
736
|
goto lreject;
|
|
721
737
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
738
|
+
recs[count] = ((uint64_t)top_open << 32) | ((uint64_t)0 << 8) | YEP_T_CLOSE;
|
|
739
|
+
/* back-patch the opener's count link: keep the original
|
|
740
|
+
* off/len, set the link into the record's off word */
|
|
741
|
+
recs[top_open] = (recs[top_open] & ~(uint64_t)0xFFFFFFFF00000000u) |
|
|
742
|
+
((uint64_t)(uint32_t)count << 32);
|
|
726
743
|
count++;
|
|
727
744
|
i = at + 1;
|
|
728
745
|
depth--;
|
|
@@ -745,9 +762,8 @@ static YeptrisStatus tape_walk_lnt_fused(const char* p, size_t len, size_t open,
|
|
|
745
762
|
kind[depth - 1] = top_kind;
|
|
746
763
|
open_at[depth - 1] = top_open;
|
|
747
764
|
top_kind = c == '[' ? 0 : 1;
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
lens[count] = 0;
|
|
765
|
+
recs[count] = ((uint64_t)0 << 32) | ((uint64_t)0 << 8) |
|
|
766
|
+
(uint64_t)(c == '[' ? YEP_T_SEQ_OPEN : YEP_T_MAP_OPEN);
|
|
751
767
|
top_open = (uint32_t)count;
|
|
752
768
|
count++;
|
|
753
769
|
top_expect = top_kind ? JW_KEY_OR_CLOSE : JW_VALUE_OR_CLOSE;
|
|
@@ -778,9 +794,8 @@ static YeptrisStatus tape_walk_lnt_fused(const char* p, size_t len, size_t open,
|
|
|
778
794
|
goto lreject;
|
|
779
795
|
}
|
|
780
796
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
lens[count] = (uint32_t)wl;
|
|
797
|
+
recs[count] = ((uint64_t)((uint32_t)at) << 32) | ((uint64_t)((uint32_t)wl) << 8) |
|
|
798
|
+
(uint64_t)(c == 'n' ? YEP_T_NULL : (c == 't' ? YEP_T_TRUE : YEP_T_FALSE));
|
|
784
799
|
count++;
|
|
785
800
|
i = at + wl;
|
|
786
801
|
goto lcomma;
|
|
@@ -1244,6 +1259,7 @@ YEPTRIS_API YeptrisStatus yeptris_parse_json_tape(const char* source, size_t len
|
|
|
1244
1259
|
|
|
1245
1260
|
YEPTRIS_API size_t yeptris_tape_convert(yeptris_json_tape* t, size_t from, size_t to,
|
|
1246
1261
|
int64_t* ivals, double* dvals) {
|
|
1262
|
+
yeptris_tape_columns(t);
|
|
1247
1263
|
if (t == NULL || t->_src == NULL || from > to || to > t->count) {
|
|
1248
1264
|
return SIZE_MAX;
|
|
1249
1265
|
}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yeptris
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.9.2
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -36,6 +36,7 @@ files:
|
|
|
36
36
|
- README.adoc
|
|
37
37
|
- ext/build_windows_native.rb
|
|
38
38
|
- ext/libyeptris/extconf.rb
|
|
39
|
+
- ext/yeptris_native/cbor_ruby.c
|
|
39
40
|
- ext/yeptris_native/extconf.rb
|
|
40
41
|
- ext/yeptris_native/json_ruby.c
|
|
41
42
|
- ext/yeptris_native/yeptris_native.c
|