yeptris 0.6.16.2 → 0.6.17.1
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 +138 -99
- data/lib/yeptris.rb +1 -1
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e317e3324f6bd24065dec096878270922234973be2957c7c850fdb59dea214c6
|
|
4
|
+
data.tar.gz: e98c83679d4228d3b35ee70b527f3d10f916308090f35b17585aaa9679292726
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4861baa93673811f488bdb34f33826dd9a204eabda55f8b0a2064a2eee1e021e36c49bba8ee597d0ac832c5368bcf572d42adfee257325f46e334ad4e3e7d846
|
|
7
|
+
data.tar.gz: '08cd8dc7729a1a3eaac787d85e6fdea0bb9001e1bd449e2c31dc57ebc9c2d327ab505f62d6dc647f99dad1d356a3fab3efc6ac3e1c5429e70589581e5114d741'
|
|
@@ -25,102 +25,144 @@ static VALUE cr_key_str(const char* p, size_t len) {
|
|
|
25
25
|
return rb_enc_interned_str(p, (long)len, cr_utf8_enc);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
#include "cbor/sink.h"
|
|
28
29
|
#include "dom/dom.h"
|
|
29
30
|
#include "doc.h" /* the public YeptrisDocument wrapper: ->dom */
|
|
30
31
|
#include <yeptris/cbor.h>
|
|
31
32
|
#include <yeptris/dom.h>
|
|
32
33
|
#include <yeptris/resolve.h>
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
/* ---- the VALUE sink (#157): bytes -> VALUE in ONE pass ----
|
|
36
|
+
*
|
|
37
|
+
* The decode grammar drives; these callbacks build the same VALUEs
|
|
38
|
+
* the old DOM + cr_walk pair produced (verified by the binding's
|
|
39
|
+
* differential suite): nil/true/false by tag, ints via LL2NUM (the
|
|
40
|
+
* INT64_MIN text parity wart kept), floats via DBL2NUM (no
|
|
41
|
+
* text round trip), strings copied utf8 (byte strings today ride the
|
|
42
|
+
* same utf8 String), map keys interned (values never are).
|
|
43
|
+
*
|
|
44
|
+
* GC: the container stack is a Ruby array (every VALUE reachable);
|
|
45
|
+
* the input buffer is read directly, so decode runs with GC disabled
|
|
46
|
+
* (the caller's String may move otherwise — the #160 bus error). */
|
|
47
|
+
|
|
48
|
+
struct rv_ctx {
|
|
49
|
+
VALUE stack; /* [.., container, (pending-key)?] */
|
|
50
|
+
VALUE root; /* Qnil until the top item closes */
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
static VALUE rv_top(const struct rv_ctx* c) {
|
|
54
|
+
long n = RARRAY_LEN(c->stack);
|
|
55
|
+
return n > 0 ? rb_ary_entry(c->stack, n - 1) : Qnil;
|
|
40
56
|
}
|
|
41
57
|
|
|
42
|
-
static VALUE
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return Qnil;
|
|
48
|
-
case YEPTRIS_TAG_BOOL:
|
|
49
|
-
if (len == 1) { /* Psych: "y"/"n" stay Strings */
|
|
50
|
-
return rb_utf8_str_new(p, len);
|
|
51
|
-
}
|
|
52
|
-
return (len == 4 && memcmp(p, "true", 4) == 0) ? Qtrue : Qfalse;
|
|
53
|
-
case YEPTRIS_TAG_INT: {
|
|
54
|
-
char buf[32];
|
|
55
|
-
size_t cp = len < sizeof(buf) - 1 ? len : sizeof(buf) - 1;
|
|
56
|
-
memcpy(buf, p, cp);
|
|
57
|
-
buf[cp] = '\0';
|
|
58
|
-
char* end = NULL;
|
|
59
|
-
long long v = strtoll(buf, &end, 10);
|
|
60
|
-
if (end != buf && *end == '\0' && end == buf + len && v > INT64_MIN) {
|
|
61
|
-
return LL2NUM(v);
|
|
62
|
-
}
|
|
63
|
-
return rb_utf8_str_new(p, len); /* int_or_string's fallback */
|
|
58
|
+
static VALUE rv_attach(struct rv_ctx* c, VALUE v) {
|
|
59
|
+
VALUE top = rv_top(c);
|
|
60
|
+
if (RB_TYPE_P(top, T_ARRAY)) {
|
|
61
|
+
rb_ary_push(top, v);
|
|
62
|
+
return v;
|
|
64
63
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
memcpy(buf, p, cp);
|
|
69
|
-
buf[cp] = '\0';
|
|
70
|
-
char* end = NULL;
|
|
71
|
-
double v = strtod(buf, &end);
|
|
72
|
-
if (end != buf && end != buf + len) {
|
|
73
|
-
return rb_utf8_str_new(p, len); /* float_or_string's fallback */
|
|
74
|
-
}
|
|
75
|
-
return DBL2NUM(v);
|
|
64
|
+
if (RB_TYPE_P(top, T_HASH)) {
|
|
65
|
+
rb_ary_push(c->stack, v); /* becomes the pending key */
|
|
66
|
+
return v;
|
|
76
67
|
}
|
|
77
|
-
|
|
78
|
-
|
|
68
|
+
/* a pending key: pop it, land v in the map */
|
|
69
|
+
VALUE k = rb_ary_pop(c->stack);
|
|
70
|
+
VALUE map = rv_top(c);
|
|
71
|
+
if (RB_TYPE_P(map, T_HASH)) {
|
|
72
|
+
rb_hash_aset(map, k, v);
|
|
73
|
+
return v;
|
|
79
74
|
}
|
|
75
|
+
/* the stack emptied: v is the root */
|
|
76
|
+
c->root = v;
|
|
77
|
+
return v;
|
|
80
78
|
}
|
|
81
79
|
|
|
82
|
-
static
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
80
|
+
static int rv_text(void* ctx, const char* s, uint32_t n, uint8_t tag_id, int is_key,
|
|
81
|
+
const char* tag, uint32_t tag_len) {
|
|
82
|
+
(void)tag;
|
|
83
|
+
(void)tag_len;
|
|
84
|
+
struct rv_ctx* c = ctx;
|
|
85
|
+
VALUE v;
|
|
86
|
+
switch (tag_id) {
|
|
87
|
+
case YEPTRIS_TAG_NULL:
|
|
88
|
+
v = Qnil;
|
|
89
|
+
break;
|
|
90
|
+
case YEPTRIS_TAG_BOOL:
|
|
91
|
+
v = (n == 4 && memcmp(s, "true", 4) == 0) ? Qtrue : Qfalse;
|
|
92
|
+
break;
|
|
93
|
+
default: /* rendered text (diagnostics, simple(N), key ints) */
|
|
94
|
+
v = rb_utf8_str_new(s, (long)n);
|
|
95
|
+
break;
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (c != UINT32_MAX) {
|
|
115
|
-
c = d->nodes[c].next_sibling;
|
|
116
|
-
}
|
|
117
|
-
rb_hash_aset(h, k, v);
|
|
118
|
-
}
|
|
119
|
-
return h;
|
|
97
|
+
(void)is_key;
|
|
98
|
+
rv_attach(c, v);
|
|
99
|
+
return 1;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static int rv_int(void* ctx, int negative, uint64_t mag, int is_key, const char* tag,
|
|
103
|
+
uint32_t tag_len) {
|
|
104
|
+
(void)tag;
|
|
105
|
+
(void)tag_len;
|
|
106
|
+
struct rv_ctx* c = ctx;
|
|
107
|
+
VALUE v;
|
|
108
|
+
if (negative && mag == (uint64_t)1 << 63) {
|
|
109
|
+
/* parity: the DOM path's strtoll guard renders INT64_MIN a
|
|
110
|
+
* String today; the differential suite pins it */
|
|
111
|
+
v = rb_utf8_str_new("-9223372036854775808", 20);
|
|
112
|
+
} else {
|
|
113
|
+
v = LL2NUM(negative ? -(int64_t)mag : (int64_t)mag);
|
|
120
114
|
}
|
|
121
|
-
|
|
122
|
-
|
|
115
|
+
rv_attach(c, v);
|
|
116
|
+
return 1;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static int rv_float(void* ctx, double dv, int is_key, const char* tag, uint32_t tag_len) {
|
|
120
|
+
(void)is_key;
|
|
121
|
+
(void)tag;
|
|
122
|
+
(void)tag_len;
|
|
123
|
+
rv_attach(ctx, DBL2NUM(dv));
|
|
124
|
+
return 1;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static int rv_str(void* ctx, const unsigned char* p, uint32_t n, int borrowed, int is_key,
|
|
128
|
+
const char* tag, uint32_t tag_len) {
|
|
129
|
+
(void)borrowed;
|
|
130
|
+
(void)tag;
|
|
131
|
+
(void)tag_len;
|
|
132
|
+
struct rv_ctx* c = ctx;
|
|
133
|
+
VALUE v = is_key ? rb_enc_interned_str((const char*)p, (long)n, cr_utf8_enc)
|
|
134
|
+
: rb_utf8_str_new((const char*)p, (long)n);
|
|
135
|
+
rv_attach(c, v);
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
static int rv_bytes(void* ctx, const unsigned char* p, uint32_t n, int borrowed, int is_key,
|
|
140
|
+
const char* tag, uint32_t tag_len) {
|
|
141
|
+
/* parity: byte strings ride the same utf8 String today */
|
|
142
|
+
return rv_str(ctx, p, n, borrowed, is_key, tag, tag_len);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static int rv_open(void* ctx, int is_map, uint64_t cap, const char* tag, uint32_t tag_len) {
|
|
146
|
+
(void)tag;
|
|
147
|
+
(void)tag_len;
|
|
148
|
+
struct rv_ctx* c = ctx;
|
|
149
|
+
VALUE v;
|
|
150
|
+
if (is_map) {
|
|
151
|
+
v = (cap != UINT64_MAX && cap / 2 <= 4096) ? HASH_NEW_CAPA((long)(cap / 2))
|
|
152
|
+
: rb_hash_new();
|
|
153
|
+
} else {
|
|
154
|
+
v = (cap != UINT64_MAX && cap <= 8192) ? rb_ary_new_capa((long)cap) : rb_ary_new();
|
|
123
155
|
}
|
|
156
|
+
rb_ary_push(c->stack, v);
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
static int rv_close(void* ctx, int is_map) {
|
|
161
|
+
(void)is_map;
|
|
162
|
+
struct rv_ctx* c = ctx;
|
|
163
|
+
VALUE v = rb_ary_pop(c->stack);
|
|
164
|
+
rv_attach(c, v);
|
|
165
|
+
return 1;
|
|
124
166
|
}
|
|
125
167
|
|
|
126
168
|
VALUE yep_rb_cbor_load(const char* p, size_t len, int strict) {
|
|
@@ -128,27 +170,24 @@ VALUE yep_rb_cbor_load(const char* p, size_t len, int strict) {
|
|
|
128
170
|
cr_utf8_enc = rb_utf8_encoding();
|
|
129
171
|
}
|
|
130
172
|
YeptrisStatus st = YEPTRIS_OK;
|
|
131
|
-
/* the
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
* Same discipline as the JSON walk: GC off across decode+walk */
|
|
173
|
+
/* the decoder reads the caller's buffer directly; GC off across
|
|
174
|
+
* the pass (a compaction would move the String under p — the
|
|
175
|
+
* #160 bus error) */
|
|
135
176
|
VALUE gc_on = rb_gc_disable();
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
return Qundef;
|
|
147
|
-
}
|
|
148
|
-
VALUE v = (d->dcount > 0 && d->docs[0] != UINT32_MAX) ? cr_walk(d, d->docs[0]) : Qnil;
|
|
149
|
-
yeptris_document_free((YeptrisDocument)doc);
|
|
177
|
+
struct rv_ctx ctx;
|
|
178
|
+
ctx.stack = rb_ary_new();
|
|
179
|
+
ctx.root = Qnil;
|
|
180
|
+
static const yep_cbor_sink RV_SINK = {
|
|
181
|
+
NULL, rv_text, rv_int, rv_float, rv_str, rv_bytes, rv_open, rv_close,
|
|
182
|
+
};
|
|
183
|
+
yep_cbor_sink sink = RV_SINK;
|
|
184
|
+
sink.ctx = &ctx;
|
|
185
|
+
st = yep_cbor_decode_gen((const unsigned char*)p, len, strict, NULL, &sink);
|
|
150
186
|
if (RTEST(gc_on)) {
|
|
151
187
|
rb_gc_enable();
|
|
152
188
|
}
|
|
153
|
-
|
|
189
|
+
if (st != YEPTRIS_OK) {
|
|
190
|
+
return Qundef;
|
|
191
|
+
}
|
|
192
|
+
return ctx.root;
|
|
154
193
|
}
|
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.17.1".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
|