yeptris 0.6.48.0-aarch64-linux → 0.6.50.0-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/version.h +2 -2
- data/lib/yeptris/cbor.rb +32 -0
- data/lib/yeptris/ffi.rb +6 -0
- data/lib/yeptris.rb +1 -1
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- data/vendor/libyeptris/src/CMakeLists.txt +2 -1
- data/vendor/libyeptris/src/include/yeptris/cbor.h +24 -0
- data/vendor/libyeptris/src/include/yeptris/json.h +4 -2
- data/vendor/libyeptris/src/include/yeptris/tape.h +5 -0
- data/vendor/libyeptris/src/yeptris/cbor/decode.c +59 -9
- data/vendor/libyeptris/src/yeptris/cbor/encode.c +32 -31
- data/vendor/libyeptris/src/yeptris/cbor/encode_priv.h +32 -0
- data/vendor/libyeptris/src/yeptris/cbor/from_marshal.c +975 -0
- data/vendor/libyeptris/src/yeptris/emit/emit.c +49 -87
- data/vendor/libyeptris/src/yeptris/emit/style.c +43 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.c +123 -6
- data/vendor/libyeptris/src/yeptris/parse/engine.c +16 -2
- data/vendor/libyeptris/src/yeptris/parse/engine.h +6 -1
- data/vendor/libyeptris/src/yeptris/parse.c +6 -3
- data/vendor/libyeptris/src/yeptris/tape.c +70 -46
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '0782e25e15d541b7a7e5448f7c63e79e627a130946d131860133021262d15c28'
|
|
4
|
+
data.tar.gz: daf5279398e226c9ab663ab1482356938a675a7cdd84b0e872134e2f6651322f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 423942744e7c5fbaa2c7dc4cde3f088abaf4aaacb88e4095c9e0fd0af1e3bf9774024522fcaa34d97e511ddba3b62e30a53753ee127a50ee3727f2a08fa08ca2
|
|
7
|
+
data.tar.gz: 102f3c0f8f3baa9d78ea65a3124c24c632d8f2e8940835e63c28061c81cb5b16039be3ac8c58e1751943ba3d10ef8287ee245260eb81b8a0a5b3d3a3ee63527e
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
#define YEPTRIS_VERSION_MAJOR 0
|
|
13
13
|
#define YEPTRIS_VERSION_MINOR 6
|
|
14
|
-
#define YEPTRIS_VERSION_PATCH
|
|
15
|
-
#define YEPTRIS_VERSION_STRING "0.6.
|
|
14
|
+
#define YEPTRIS_VERSION_PATCH 50
|
|
15
|
+
#define YEPTRIS_VERSION_STRING "0.6.50"
|
|
16
16
|
|
|
17
17
|
#ifdef __cplusplus
|
|
18
18
|
extern "C" {
|
data/lib/yeptris/cbor.rb
CHANGED
|
@@ -77,6 +77,11 @@ module Yeptris
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def dump(obj, canonical: true)
|
|
80
|
+
# yeptris-ruby#322: the marshal face answers in one C call when
|
|
81
|
+
# the host has an exact spelling; nil routes to the tree walk
|
|
82
|
+
data = marshal_cbor_dump(obj, canonical)
|
|
83
|
+
return data if data
|
|
84
|
+
|
|
80
85
|
docs = build_documents([obj])
|
|
81
86
|
begin
|
|
82
87
|
encode_one(docs[0], canonical)
|
|
@@ -123,6 +128,33 @@ module Yeptris
|
|
|
123
128
|
take_buffer(::Yeptris::FFI.yeptris_cbor_encode(doc.c_ptr, opts, len_ptr), len_ptr)
|
|
124
129
|
end
|
|
125
130
|
|
|
131
|
+
# yeptris-ruby#322: Marshal.dump bytes -> one CBOR item in ONE C
|
|
132
|
+
# call (yeptris_cbor_from_marshal, engine 0.6.49+). Returns nil
|
|
133
|
+
# when the route is unavailable or the host's bytes have no exact
|
|
134
|
+
# fast-path spelling (UNSUPPORTED), and the caller keeps the
|
|
135
|
+
# YAMLTree walk, which is exact by construction. Marshal-undumpable
|
|
136
|
+
# hosts raise TypeError; nil lets that walk own the DumpError
|
|
137
|
+
# contract too.
|
|
138
|
+
def marshal_cbor_dump(obj, canonical)
|
|
139
|
+
return nil unless defined?(::Yeptris::FFI::MARSHAL_CBOR) &&
|
|
140
|
+
::Yeptris::FFI::MARSHAL_CBOR
|
|
141
|
+
m = Marshal.dump(obj)
|
|
142
|
+
out_p = ::FFI::MemoryPointer.new(:pointer)
|
|
143
|
+
olen_p = ::FFI::MemoryPointer.new(:size_t)
|
|
144
|
+
st = ::Yeptris::FFI.yeptris_cbor_from_marshal(
|
|
145
|
+
m, m.bytesize, canonical ? CANONICAL : 0, out_p, olen_p
|
|
146
|
+
)
|
|
147
|
+
return nil unless st == ::Yeptris::FFI::OK
|
|
148
|
+
buf = out_p.read_pointer
|
|
149
|
+
return nil if buf.null?
|
|
150
|
+
|
|
151
|
+
data = buf.read_bytes(::Yeptris::FFI.read_c_size_t(olen_p))
|
|
152
|
+
::Yeptris::FFI.yeptris_marshal_free(buf)
|
|
153
|
+
data.force_encoding(Encoding::BINARY)
|
|
154
|
+
rescue ::TypeError
|
|
155
|
+
nil
|
|
156
|
+
end
|
|
157
|
+
|
|
126
158
|
# The encode convenience contract: a malloc'd buffer plus its
|
|
127
159
|
# byte length — binary data, freed through the library's own free.
|
|
128
160
|
def take_buffer(ptr, len_ptr)
|
data/lib/yeptris/ffi.rb
CHANGED
|
@@ -303,6 +303,12 @@ module Yeptris
|
|
|
303
303
|
attach_function :yeptris_cbor_encode_sequence,
|
|
304
304
|
%i[pointer size_t uint32 pointer], :pointer
|
|
305
305
|
CBOR_EX = !(@missing ||= []).include?(:yeptris_cbor_decode)
|
|
306
|
+
# yeptris-ruby#322: Marshal.dump bytes -> one CBOR item in one C
|
|
307
|
+
# call (engine 0.6.49+); MARSHAL_CBOR goes false on older libraries
|
|
308
|
+
# and CBOR.dump keeps the YAMLTree walk
|
|
309
|
+
attach_function :yeptris_cbor_from_marshal,
|
|
310
|
+
%i[pointer size_t uint32 pointer pointer], :int
|
|
311
|
+
MARSHAL_CBOR = !(@missing ||= []).include?(:yeptris_cbor_from_marshal)
|
|
306
312
|
|
|
307
313
|
# Owned char* results (serialize*): one reader, freed exactly once.
|
|
308
314
|
# The release goes through yeptris_free (libyeptris's own
|
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.50.0".freeze
|
|
7
7
|
|
|
8
8
|
# Informational notices are OPT-IN (yeptris-ruby#217): consumers
|
|
9
9
|
# embed yeptris inside CLIs that assert clean stderr, and a
|
data/libyeptris.so
CHANGED
|
Binary file
|
|
@@ -58,7 +58,8 @@ set(YEPTRIS_SOURCES
|
|
|
58
58
|
)
|
|
59
59
|
|
|
60
60
|
if(YEPTRIS_WITH_CBOR)
|
|
61
|
-
list(APPEND YEPTRIS_SOURCES yeptris/cbor/decode.c yeptris/cbor/encode.c
|
|
61
|
+
list(APPEND YEPTRIS_SOURCES yeptris/cbor/decode.c yeptris/cbor/encode.c
|
|
62
|
+
yeptris/cbor/from_marshal.c)
|
|
62
63
|
endif()
|
|
63
64
|
|
|
64
65
|
# AOT SIMD TUs (TODO.impl/04): per-ISA compile flags; the TUs and the
|
|
@@ -94,6 +94,30 @@ YEPTRIS_API size_t yeptris_cbor_encode_into(YeptrisDocument doc, uint32_t opts,
|
|
|
94
94
|
* byte count. */
|
|
95
95
|
YEPTRIS_API void* yeptris_cbor_encode(YeptrisDocument doc, uint32_t opts, size_t* len);
|
|
96
96
|
|
|
97
|
+
/* The binding's dump face (yeptris-ruby#322): Ruby Marshal 4.8 bytes
|
|
98
|
+
* IN, ONE CBOR data item OUT, one C call — the CBOR twin of
|
|
99
|
+
* yeptris_json_from_marshal (marshal.h), walked in C with no Document
|
|
100
|
+
* and no per-node host crossings. opts: YEPTRIS_CBOR_CANONICAL sorts
|
|
101
|
+
* each map's pairs by encoded-key bytes; 0 keeps insertion order.
|
|
102
|
+
*
|
|
103
|
+
* Covers the host subset the per-node route spells: nil/bool/int/
|
|
104
|
+
* float/string/array/hash, symbols (as ":name" text), 'I' wrappers,
|
|
105
|
+
* shared-object links (duplicated bytes), bignums up to four 16-bit
|
|
106
|
+
* words (inside int64 as integers, past either end as preferred
|
|
107
|
+
* floats), and the per-node route's map-key spellings (strings,
|
|
108
|
+
* symbols, integers, floats, booleans). Anything else — objects,
|
|
109
|
+
* structs, user marshal, invalid-UTF-8 strings, non-finite float text,
|
|
110
|
+
* wider bignums, nil/array/hash map keys, cycles — returns
|
|
111
|
+
* YEPTRIS_ERROR_UNSUPPORTED and the binding keeps its per-node walk.
|
|
112
|
+
*
|
|
113
|
+
* The bytes are byte-identical to yeptris_cbor_encode over the
|
|
114
|
+
* document the per-node walk builds (pinned by test_cbor_marshal.cpp).
|
|
115
|
+
* *out is malloc'd, free with yeptris_marshal_free (or free) exactly
|
|
116
|
+
* once; on failure nothing is allocated. Trailing bytes after the
|
|
117
|
+
* root are UNSUPPORTED (the stream is exactly one value). */
|
|
118
|
+
YEPTRIS_API YeptrisStatus yeptris_cbor_from_marshal(const char* m, size_t m_len, uint32_t opts,
|
|
119
|
+
char** out, size_t* out_len);
|
|
120
|
+
|
|
97
121
|
#ifdef __cplusplus
|
|
98
122
|
}
|
|
99
123
|
#endif
|
|
@@ -31,11 +31,13 @@ YEPTRIS_API YeptrisDocument yeptris_parse_json(const char* data, size_t len, Yep
|
|
|
31
31
|
* collections, JSON escapes, shortest floats, null/true/false words).
|
|
32
32
|
* Returns a malloc'd NUL-terminated buffer (caller frees) with *len
|
|
33
33
|
* (may be NULL) set, or NULL on a NULL document / allocation
|
|
34
|
-
* failure / zero documents
|
|
34
|
+
* failure / zero documents / a document with no JSON spelling
|
|
35
|
+
* (unserializable). */
|
|
35
36
|
YEPTRIS_API char* yeptris_serialize_json(YeptrisDocument doc, size_t* len);
|
|
36
37
|
|
|
37
38
|
/* The compact variant: no padding spaces (JSON.generate's shape);
|
|
38
|
-
* compact == 0 is byte-identical to yeptris_serialize_json.
|
|
39
|
+
* compact == 0 is byte-identical to yeptris_serialize_json. Same
|
|
40
|
+
* NULL contract, the unserializable law included. */
|
|
39
41
|
YEPTRIS_API char* yeptris_serialize_json_ex(YeptrisDocument doc, size_t* len, int compact);
|
|
40
42
|
|
|
41
43
|
/* The pretty variant: JSON.pretty_generate's shape — one entry per
|
|
@@ -74,6 +74,11 @@ typedef struct yeptris_json_tape {
|
|
|
74
74
|
outlive the tape — same contract as the spans) */
|
|
75
75
|
size_t _srclen;
|
|
76
76
|
void* _block; /* the carved allocation base */
|
|
77
|
+
/* the >1024 simple-key verdict, settled DURING the lenient walk
|
|
78
|
+
* (one compare per map key) — the post-scan re-walk of the whole
|
|
79
|
+
* tape cost 16% of json-users parse (#739 profile, 2026-10-28) */
|
|
80
|
+
unsigned char _long_key_known;
|
|
81
|
+
unsigned char _long_key;
|
|
77
82
|
} yeptris_json_tape;
|
|
78
83
|
|
|
79
84
|
/* Parses strict JSON into the tape. Accepts scalar roots (a single
|
|
@@ -119,14 +119,36 @@ static int cbor_arg(yep_cdec* c, uint8_t ai, uint64_t* val) {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
static uint32_t cbor_u64dec(uint64_t v, char* buf) {
|
|
122
|
+
/* two digits per divide: the per-digit %10//10 loop was the decode
|
|
123
|
+
* lane's hottest formatter (the #742 profile) — one /100 plus a
|
|
124
|
+
* table load halves the divides; the reverse pass shrinks to the
|
|
125
|
+
* pair loop */
|
|
126
|
+
static const char PAIRS[] = "00010203040506070809"
|
|
127
|
+
"10111213141516171819"
|
|
128
|
+
"20212223242526272829"
|
|
129
|
+
"30313233343536373839"
|
|
130
|
+
"40414243444546474849"
|
|
131
|
+
"50515253545556575859"
|
|
132
|
+
"60616263646566676869"
|
|
133
|
+
"70717273747576777879"
|
|
134
|
+
"80818283848586878889"
|
|
135
|
+
"90919293949596979899";
|
|
122
136
|
char tmp[20];
|
|
123
137
|
uint32_t n = 0;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
v /=
|
|
127
|
-
|
|
138
|
+
while (v >= 100) {
|
|
139
|
+
uint32_t r = (uint32_t)(v % 100u);
|
|
140
|
+
v /= 100u;
|
|
141
|
+
tmp[n++] = PAIRS[r * 2u + 1u];
|
|
142
|
+
tmp[n++] = PAIRS[r * 2u];
|
|
143
|
+
}
|
|
144
|
+
if (v >= 10u) {
|
|
145
|
+
tmp[n++] = PAIRS[v * 2u + 1u];
|
|
146
|
+
tmp[n++] = PAIRS[v * 2u];
|
|
147
|
+
} else {
|
|
148
|
+
tmp[n++] = (char)('0' + (int)v);
|
|
149
|
+
}
|
|
128
150
|
for (uint32_t k = 0; k < n; k++) {
|
|
129
|
-
buf[k] = tmp[n -
|
|
151
|
+
buf[k] = tmp[n - 1u - k];
|
|
130
152
|
}
|
|
131
153
|
return n;
|
|
132
154
|
}
|
|
@@ -727,13 +749,41 @@ static int dom_sink_close(void* dp, int is_map) {
|
|
|
727
749
|
|
|
728
750
|
static int dom_sink_int(void* dp, int negative, uint64_t mag, int is_key, const char* tag,
|
|
729
751
|
uint32_t tag_len) {
|
|
730
|
-
|
|
752
|
+
/* the int path formats straight into the arena (the #742
|
|
753
|
+
* profile's 26% lane): no stack buffer, no second copy through
|
|
754
|
+
* the text sink — tail, format in place, commit */
|
|
755
|
+
(void)is_key;
|
|
756
|
+
yep_dom* d = dp;
|
|
757
|
+
yep_view tag_v;
|
|
758
|
+
const yep_view* tagp = NULL;
|
|
759
|
+
if (tag != NULL) {
|
|
760
|
+
char* tdst = yep_dom_str_tail(d, tag_len);
|
|
761
|
+
if (tdst == NULL) {
|
|
762
|
+
return 0;
|
|
763
|
+
}
|
|
764
|
+
memcpy(tdst, tag, tag_len);
|
|
765
|
+
yep_sview piece = yep_dom_str_commit(d, tag_len);
|
|
766
|
+
tag_v.p = d->str + (piece.off & YEP_SV_OFF);
|
|
767
|
+
tag_v.len = tag_len;
|
|
768
|
+
tagp = &tag_v;
|
|
769
|
+
}
|
|
770
|
+
uint32_t id = dom_open_node(d, YEP_DOM_SCALAR, tagp, NULL, 0, YEP_STYLE_PLAIN, 1, 0);
|
|
771
|
+
if (id == UINT32_MAX) {
|
|
772
|
+
return 0;
|
|
773
|
+
}
|
|
774
|
+
yep_dnode* node = &d->nodes[id];
|
|
775
|
+
char* dst = yep_dom_str_tail(d, 21); /* '-' plus twenty digits */
|
|
776
|
+
if (dst == NULL) {
|
|
777
|
+
return 0;
|
|
778
|
+
}
|
|
731
779
|
uint32_t n = 0;
|
|
732
780
|
if (negative) {
|
|
733
|
-
|
|
781
|
+
dst[n++] = '-';
|
|
734
782
|
}
|
|
735
|
-
n += cbor_u64dec(mag,
|
|
736
|
-
|
|
783
|
+
n += cbor_u64dec(mag, dst + n);
|
|
784
|
+
node->value = yep_dom_str_commit(d, n);
|
|
785
|
+
node->tag_id = YEPTRIS_TAG_INT;
|
|
786
|
+
return dom_place(d, id) == 0;
|
|
737
787
|
}
|
|
738
788
|
|
|
739
789
|
static int dom_sink_float(void* dp, double dv, int is_key, const char* tag, uint32_t tag_len) {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* - aliases (YAML input) are UNSUPPORTED: the CBOR model has none
|
|
26
26
|
*/
|
|
27
27
|
#include "cbor.h"
|
|
28
|
+
#include "encode_priv.h"
|
|
28
29
|
|
|
29
30
|
#include <math.h>
|
|
30
31
|
#include <stdlib.h>
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
|
|
41
42
|
/* ---- heads: minimal argument encoding (RFC 8949 s3) ----------------- */
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
size_t yep_cbor_arg_bytes(uint64_t arg) {
|
|
44
45
|
if (arg < 24)
|
|
45
46
|
return 1;
|
|
46
47
|
if (arg <= 0xFFull)
|
|
@@ -52,10 +53,10 @@ static size_t cbor_arg_bytes(uint64_t arg) {
|
|
|
52
53
|
return 9;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
void yep_cbor_put_head(uint8_t* out, size_t* pos, uint8_t mt, uint64_t arg) {
|
|
56
57
|
/* payload bytes -> additional info: 1->24, 2->25, 4->26, 8->27 */
|
|
57
58
|
static const uint8_t ai_of[9] = {0, 24, 25, 25, 26, 26, 26, 26, 27};
|
|
58
|
-
size_t n =
|
|
59
|
+
size_t n = yep_cbor_arg_bytes(arg) - 1;
|
|
59
60
|
out[(*pos)++] = (uint8_t)((mt << 5) | (n == 0 ? (uint8_t)arg : ai_of[n]));
|
|
60
61
|
for (size_t k = 0; k < n; k++) { /* network byte order */
|
|
61
62
|
out[(*pos)++] = (uint8_t)(arg >> (8 * (n - 1 - k)));
|
|
@@ -143,7 +144,7 @@ static uint16_t cbor_d2h(double d) {
|
|
|
143
144
|
return (uint16_t)(sign | m10);
|
|
144
145
|
}
|
|
145
146
|
|
|
146
|
-
|
|
147
|
+
uint8_t yep_cbor_float_width(double d) {
|
|
147
148
|
if (d != d) {
|
|
148
149
|
return 2; /* NaN: the canonical f9 7e00 (s4.2.2) */
|
|
149
150
|
}
|
|
@@ -157,7 +158,7 @@ static uint8_t cbor_float_width(double d) {
|
|
|
157
158
|
return 8;
|
|
158
159
|
}
|
|
159
160
|
|
|
160
|
-
|
|
161
|
+
void yep_cbor_put_float(uint8_t* out, size_t* pos, double d, uint8_t width) {
|
|
161
162
|
out[(*pos)++] = (uint8_t)((7 << 5) | (width == 2 ? 25 : width == 4 ? 26 : 27));
|
|
162
163
|
uint64_t bits = 0;
|
|
163
164
|
if (width == 2) {
|
|
@@ -221,7 +222,7 @@ static int cbor_scalar_number(const yep_view* v, cbor_num* out) {
|
|
|
221
222
|
}
|
|
222
223
|
out->mt = 7;
|
|
223
224
|
out->dval = dv;
|
|
224
|
-
out->fwidth =
|
|
225
|
+
out->fwidth = yep_cbor_float_width(dv);
|
|
225
226
|
return 1;
|
|
226
227
|
}
|
|
227
228
|
|
|
@@ -247,17 +248,17 @@ static int cbor_bool_value(const yep_view* v) {
|
|
|
247
248
|
/* The diagnostic round-trip (the 01 ledger): decode renders
|
|
248
249
|
* undefined/simple(N) as text; encode recognizes them back. The words
|
|
249
250
|
* are reserved — a literal "undefined" string encodes as the simple. */
|
|
250
|
-
|
|
251
|
-
if (
|
|
251
|
+
int yep_cbor_simple_of(const char* p, size_t len) {
|
|
252
|
+
if (len == 9 && memcmp(p, "undefined", 9) == 0) {
|
|
252
253
|
return 23;
|
|
253
254
|
}
|
|
254
|
-
if (
|
|
255
|
+
if (len > 9 && memcmp(p, "simple(", 7) == 0 && p[len - 1] == ')') {
|
|
255
256
|
uint64_t val = 0;
|
|
256
|
-
for (size_t i = 7; i + 1 <
|
|
257
|
-
if (
|
|
257
|
+
for (size_t i = 7; i + 1 < len; i++) {
|
|
258
|
+
if (p[i] < '0' || p[i] > '9') {
|
|
258
259
|
return -1;
|
|
259
260
|
}
|
|
260
|
-
val = val * 10 + (uint64_t)(
|
|
261
|
+
val = val * 10 + (uint64_t)(p[i] - '0');
|
|
261
262
|
if (val > 255) {
|
|
262
263
|
return -1;
|
|
263
264
|
}
|
|
@@ -337,7 +338,7 @@ static uint8_t* cbor_encode_key(const yep_dom* d, const yep_dnode* key, size_t*
|
|
|
337
338
|
goto bad;
|
|
338
339
|
}
|
|
339
340
|
for (int t = 0; t < ntags; t++) {
|
|
340
|
-
|
|
341
|
+
yep_cbor_put_head(buf, &pos, 6, tags[t]);
|
|
341
342
|
}
|
|
342
343
|
if (key->tag_id == YEPTRIS_TAG_INT || key->tag_id == YEPTRIS_TAG_FLOAT) {
|
|
343
344
|
cbor_num num;
|
|
@@ -345,13 +346,13 @@ static uint8_t* cbor_encode_key(const yep_dom* d, const yep_dnode* key, size_t*
|
|
|
345
346
|
goto bad;
|
|
346
347
|
}
|
|
347
348
|
if (num.mt != 7) {
|
|
348
|
-
|
|
349
|
+
yep_cbor_put_head(buf, &pos, num.mt, num.uval);
|
|
349
350
|
} else {
|
|
350
|
-
|
|
351
|
+
yep_cbor_put_float(buf, &pos, num.dval, num.fwidth);
|
|
351
352
|
}
|
|
352
353
|
} else { /* strings and diagnostics: a simple, else a text item */
|
|
353
354
|
if (key->tag.len == 0) {
|
|
354
|
-
int sv =
|
|
355
|
+
int sv = yep_cbor_simple_of(v.p, v.len);
|
|
355
356
|
if (sv >= 0) {
|
|
356
357
|
if (sv < 24) {
|
|
357
358
|
buf[pos++] = (uint8_t)(0xE0 | (uint8_t)sv);
|
|
@@ -363,7 +364,7 @@ static uint8_t* cbor_encode_key(const yep_dom* d, const yep_dnode* key, size_t*
|
|
|
363
364
|
return buf;
|
|
364
365
|
}
|
|
365
366
|
}
|
|
366
|
-
|
|
367
|
+
yep_cbor_put_head(
|
|
367
368
|
buf, &pos,
|
|
368
369
|
v.len == 0 || yep_utf8_validate((const unsigned char*)v.p, v.len, NULL) ? 3 : 2, v.len);
|
|
369
370
|
if (v.len > 0) {
|
|
@@ -498,7 +499,7 @@ static size_t cbor_size_scalar(cenc* e, const yep_dnode* n) {
|
|
|
498
499
|
return 0;
|
|
499
500
|
}
|
|
500
501
|
for (int t = 0; t < ntags; t++) {
|
|
501
|
-
sz +=
|
|
502
|
+
sz += yep_cbor_arg_bytes(tags[t]);
|
|
502
503
|
}
|
|
503
504
|
yep_view v = yep_dom_view(d, n->value);
|
|
504
505
|
switch (n->tag_id) {
|
|
@@ -510,19 +511,19 @@ static size_t cbor_size_scalar(cenc* e, const yep_dnode* n) {
|
|
|
510
511
|
e->status = YEPTRIS_ERROR_UNSUPPORTED;
|
|
511
512
|
return 0;
|
|
512
513
|
}
|
|
513
|
-
return sz + (num.mt == 7 ? (size_t)(1 + num.fwidth) :
|
|
514
|
+
return sz + (num.mt == 7 ? (size_t)(1 + num.fwidth) : yep_cbor_arg_bytes(num.uval));
|
|
514
515
|
}
|
|
515
516
|
case YEPTRIS_TAG_BOOL:
|
|
516
517
|
case YEPTRIS_TAG_NULL:
|
|
517
518
|
return sz + 1;
|
|
518
519
|
default: /* str: a recognized diagnostic, else a text item */
|
|
519
520
|
if (n->tag.len == 0) {
|
|
520
|
-
int sv =
|
|
521
|
+
int sv = yep_cbor_simple_of(v.p, v.len);
|
|
521
522
|
if (sv >= 0) {
|
|
522
523
|
return sz + ((uint32_t)sv < 24 ? 1 : 2);
|
|
523
524
|
}
|
|
524
525
|
}
|
|
525
|
-
return sz +
|
|
526
|
+
return sz + yep_cbor_arg_bytes(v.len) + v.len;
|
|
526
527
|
}
|
|
527
528
|
}
|
|
528
529
|
|
|
@@ -541,7 +542,7 @@ static size_t cbor_size_item(cenc* e, uint32_t id) {
|
|
|
541
542
|
return 0;
|
|
542
543
|
}
|
|
543
544
|
for (int t = 0; t < ntags; t++) {
|
|
544
|
-
sz +=
|
|
545
|
+
sz += yep_cbor_arg_bytes(tags[t]);
|
|
545
546
|
}
|
|
546
547
|
if (n->kind == YEP_DOM_ALIAS) {
|
|
547
548
|
e->failed = 1;
|
|
@@ -549,7 +550,7 @@ static size_t cbor_size_item(cenc* e, uint32_t id) {
|
|
|
549
550
|
return 0;
|
|
550
551
|
}
|
|
551
552
|
if (n->kind == YEP_DOM_SEQUENCE) {
|
|
552
|
-
sz +=
|
|
553
|
+
sz += yep_cbor_arg_bytes(n->count);
|
|
553
554
|
uint32_t c = n->first_child;
|
|
554
555
|
for (uint32_t k = 0; k < n->count && !e->failed; k++) {
|
|
555
556
|
sz += cbor_size_item(e, c);
|
|
@@ -559,7 +560,7 @@ static size_t cbor_size_item(cenc* e, uint32_t id) {
|
|
|
559
560
|
}
|
|
560
561
|
/* mapping */
|
|
561
562
|
uint32_t pairs = n->count / 2;
|
|
562
|
-
sz +=
|
|
563
|
+
sz += yep_cbor_arg_bytes(pairs);
|
|
563
564
|
/* hold the INDEX, not the pointer: sizing a child recurses into
|
|
564
565
|
* nested maps whose preps REALLOC e->maps (#152 — a held cmap*
|
|
565
566
|
* dangled and the next pair read walked freed memory; n>=11 of
|
|
@@ -610,9 +611,9 @@ static void cbor_write_scalar(cenc* e, const yep_dnode* n, uint8_t* out, size_t*
|
|
|
610
611
|
return; /* pass 1 already failed on this; unreachable */
|
|
611
612
|
}
|
|
612
613
|
if (num.mt == 7) {
|
|
613
|
-
|
|
614
|
+
yep_cbor_put_float(out, pos, num.dval, num.fwidth);
|
|
614
615
|
} else {
|
|
615
|
-
|
|
616
|
+
yep_cbor_put_head(out, pos, num.mt, num.uval);
|
|
616
617
|
}
|
|
617
618
|
return;
|
|
618
619
|
}
|
|
@@ -624,7 +625,7 @@ static void cbor_write_scalar(cenc* e, const yep_dnode* n, uint8_t* out, size_t*
|
|
|
624
625
|
return;
|
|
625
626
|
default:
|
|
626
627
|
if (n->tag.len == 0) {
|
|
627
|
-
int sv =
|
|
628
|
+
int sv = yep_cbor_simple_of(v.p, v.len);
|
|
628
629
|
if (sv >= 0) {
|
|
629
630
|
if (sv < 24) {
|
|
630
631
|
out[(*pos)++] = (uint8_t)(0xE0 | (uint8_t)sv);
|
|
@@ -638,7 +639,7 @@ static void cbor_write_scalar(cenc* e, const yep_dnode* n, uint8_t* out, size_t*
|
|
|
638
639
|
/* invalid UTF-8 can only have been a byte string (the 01
|
|
639
640
|
* ledger: both decode to tag-str scalars) — emit mt2 so the
|
|
640
641
|
* roundtrip re-decodes to the same bytes */
|
|
641
|
-
|
|
642
|
+
yep_cbor_put_head(
|
|
642
643
|
out, pos,
|
|
643
644
|
v.len == 0 || yep_utf8_validate((const unsigned char*)v.p, v.len, NULL) ? 3 : 2, v.len);
|
|
644
645
|
if (v.len > 0) { /* memcpy(_, NULL, 0) is UB (gcc UBSan) */
|
|
@@ -655,14 +656,14 @@ static void cbor_write_item(cenc* e, uint32_t id, uint8_t* out, size_t* pos) {
|
|
|
655
656
|
uint64_t tags[16];
|
|
656
657
|
int ntags = cbor_tag_chain(d, n, tags, 16);
|
|
657
658
|
for (int t = 0; t < ntags; t++) {
|
|
658
|
-
|
|
659
|
+
yep_cbor_put_head(out, pos, 6, tags[t]);
|
|
659
660
|
}
|
|
660
661
|
if (n->kind == YEP_DOM_SCALAR) {
|
|
661
662
|
cbor_write_scalar(e, n, out, pos);
|
|
662
663
|
return;
|
|
663
664
|
}
|
|
664
665
|
if (n->kind == YEP_DOM_SEQUENCE) {
|
|
665
|
-
|
|
666
|
+
yep_cbor_put_head(out, pos, 4, n->count);
|
|
666
667
|
uint32_t c = n->first_child;
|
|
667
668
|
for (uint32_t k = 0; k < n->count; k++) {
|
|
668
669
|
cbor_write_item(e, c, out, pos);
|
|
@@ -671,7 +672,7 @@ static void cbor_write_item(cenc* e, uint32_t id, uint8_t* out, size_t* pos) {
|
|
|
671
672
|
return;
|
|
672
673
|
}
|
|
673
674
|
uint32_t pairs = n->count / 2;
|
|
674
|
-
|
|
675
|
+
yep_cbor_put_head(out, pos, 5, pairs);
|
|
675
676
|
cmap* cm = NULL;
|
|
676
677
|
if (e->canonical && e->next_map < e->nmaps) {
|
|
677
678
|
cm = &e->maps[e->next_map++]; /* walk order == build order */
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/* encode_priv.h — the CBOR encoder's shared kernels (internal).
|
|
2
|
+
*
|
|
3
|
+
* encode.c owns the DOM walk; from_marshal.c (the binding dump face)
|
|
4
|
+
* appends the same item bytes from a Marshal stream. The minimal-head
|
|
5
|
+
* table, the preferred-float width rule and the reserved diagnostic
|
|
6
|
+
* words are ONE law each — both writers call them from here. */
|
|
7
|
+
|
|
8
|
+
#ifndef YEPTRIS_CBOR_ENCODE_PRIV_H
|
|
9
|
+
#define YEPTRIS_CBOR_ENCODE_PRIV_H
|
|
10
|
+
|
|
11
|
+
#include <stddef.h>
|
|
12
|
+
#include <stdint.h>
|
|
13
|
+
|
|
14
|
+
/* RFC 8949 s3: the encoded size of argument arg. */
|
|
15
|
+
size_t yep_cbor_arg_bytes(uint64_t arg);
|
|
16
|
+
|
|
17
|
+
/* RFC 8949 s3: one head (major type + minimally encoded argument). */
|
|
18
|
+
void yep_cbor_put_head(uint8_t* out, size_t* pos, uint8_t mt, uint64_t arg);
|
|
19
|
+
|
|
20
|
+
/* s4.2.2: the smallest of half/single/double that round-trips. */
|
|
21
|
+
uint8_t yep_cbor_float_width(double d);
|
|
22
|
+
|
|
23
|
+
/* s4.2.2: one float at the requested width (NaN canonicalizes). */
|
|
24
|
+
void yep_cbor_put_float(uint8_t* out, size_t* pos, double d, uint8_t width);
|
|
25
|
+
|
|
26
|
+
/* The diagnostic round-trip ledger: decode renders undefined and
|
|
27
|
+
* simple(N) as text, so the encoder recognizes those words back — with
|
|
28
|
+
* the >9-byte gate that leaves single-digit simple(N) as text. Returns
|
|
29
|
+
* the simple value, or -1 when the text is not a reserved word. */
|
|
30
|
+
int yep_cbor_simple_of(const char* p, size_t len);
|
|
31
|
+
|
|
32
|
+
#endif /* YEPTRIS_CBOR_ENCODE_PRIV_H */
|