yeptris 0.2.5.2-aarch64-linux → 0.3.0.1-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/lib/yeptris/json.rb +86 -35
- data/lib/yeptris/native.so +0 -0
- data/lib/yeptris.rb +1 -1
- data/libyeptris.so +0 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4639faf83e98440ebb4973f881db719fb6629ccbf7949f8bed6052e5be53184a
|
|
4
|
+
data.tar.gz: a0b7ed9983184783e89a590cc317b147c6eb41e39ab6801c41dd744391573020
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 775dd41728fd5171efb2a0e895498a7c2f98dc6cba9c68c0593c476d3b320c0a17e0f9d83efe69bae90b5cadcce53ab8c516d54eb0478065095aa6a2f37f802c
|
|
7
|
+
data.tar.gz: e11d2650357819532da00d1749b1fcfda1d948886f9d445b106b9eba22dab88ec4d688daab5bb0ca921500d9ca1eadf1fdec8ae8511a4287506c74822f53ba28
|
data/lib/yeptris/json.rb
CHANGED
|
@@ -54,6 +54,55 @@ module Yeptris
|
|
|
54
54
|
T_MAP_OPEN = 7
|
|
55
55
|
T_CLOSE = 8
|
|
56
56
|
|
|
57
|
+
# The tape keeps RAW string spans (escapes untouched — the C
|
|
58
|
+
# contract); the walk decodes them here. The hot path (no
|
|
59
|
+
# backslash) returns the slice untouched.
|
|
60
|
+
SIMPLE_ESCAPES = {
|
|
61
|
+
'"' => '"'.b, "\\" => "\\".b, "/" => "/".b, "b" => "\b".b, "f" => "\f".b,
|
|
62
|
+
"n" => "\n".b, "r" => "\r".b, "t" => "\t".b
|
|
63
|
+
}.freeze
|
|
64
|
+
|
|
65
|
+
def decode_span(src, off, len)
|
|
66
|
+
s = src.byteslice(off, len)
|
|
67
|
+
s.force_encoding(Encoding::UTF_8)
|
|
68
|
+
return s unless s.include?("\\")
|
|
69
|
+
|
|
70
|
+
b = s.b
|
|
71
|
+
out = +"".b
|
|
72
|
+
i = 0
|
|
73
|
+
n = b.bytesize
|
|
74
|
+
while i < n
|
|
75
|
+
c = b.getbyte(i)
|
|
76
|
+
if c != 0x5C || i + 1 >= n
|
|
77
|
+
out << c
|
|
78
|
+
i += 1
|
|
79
|
+
next
|
|
80
|
+
end
|
|
81
|
+
e = b.getbyte(i + 1)
|
|
82
|
+
if e != 0x75 # simple escape
|
|
83
|
+
ch = e.chr
|
|
84
|
+
out << (SIMPLE_ESCAPES[ch] || ch)
|
|
85
|
+
i += 2
|
|
86
|
+
next
|
|
87
|
+
end
|
|
88
|
+
cp = b.byteslice(i + 2, 4).to_i(16)
|
|
89
|
+
if cp >= 0xD800 && cp <= 0xDBFF && i + 12 <= n &&
|
|
90
|
+
b.getbyte(i + 6) == 0x5C && b.getbyte(i + 7) == 0x75
|
|
91
|
+
lo = b.byteslice(i + 8, 4).to_i(16)
|
|
92
|
+
if lo >= 0xDC00 && lo <= 0xDFFF
|
|
93
|
+
cp = 0x10000 + ((cp - 0xD800) << 10) + (lo - 0xDC00)
|
|
94
|
+
i += 12
|
|
95
|
+
else
|
|
96
|
+
i += 6
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
i += 6
|
|
100
|
+
end
|
|
101
|
+
out << [cp].pack("U").b
|
|
102
|
+
end
|
|
103
|
+
out.force_encoding(Encoding::UTF_8)
|
|
104
|
+
end
|
|
105
|
+
|
|
57
106
|
def tape_engine(source)
|
|
58
107
|
tape = ::Yeptris::FFI::JsonTape.new
|
|
59
108
|
rc = ::Yeptris::FFI.yeptris_parse_json_tape(source, source.bytesize, tape)
|
|
@@ -73,7 +122,7 @@ module Yeptris
|
|
|
73
122
|
lens = tape[:lens].read_bytes(n * 4).unpack("V*")
|
|
74
123
|
raw = tape[:vals].read_bytes(n * 8)
|
|
75
124
|
vals_i = raw.unpack("q<*")
|
|
76
|
-
vals_f = raw.unpack("E")
|
|
125
|
+
vals_f = raw.unpack("E*")
|
|
77
126
|
# any integer text beyond int64: every INT rebuilds from its span
|
|
78
127
|
# (exact Bignum; JSON.parse parity)
|
|
79
128
|
exact_ints = !tape[:int_min].zero?
|
|
@@ -97,8 +146,7 @@ module Yeptris
|
|
|
97
146
|
stack.pop
|
|
98
147
|
key_sets&.pop
|
|
99
148
|
when T_STR
|
|
100
|
-
text =
|
|
101
|
-
text.force_encoding(Encoding::UTF_8) unless utf8
|
|
149
|
+
text = lens[i] == 0 ? +"".force_encoding(Encoding::UTF_8) : decode_span(src, offs[i], lens[i])
|
|
102
150
|
if pending_key.nil? && !stack.empty? && stack.last.is_a?(Hash)
|
|
103
151
|
if key_sets && key_sets.last.key?(text)
|
|
104
152
|
raise ParseError, %(duplicate key "#{text}" in JSON object)
|
|
@@ -249,26 +297,15 @@ module Yeptris
|
|
|
249
297
|
# and null stay plain), Symbols become their name.
|
|
250
298
|
class DumpError < Error; end
|
|
251
299
|
|
|
252
|
-
ENTRY_BYTES = 12
|
|
253
|
-
MAP_ENTRY = [::Yeptris::FFI::BUILD_MAP, 0, 0, 0].pack("CCx2VV").freeze
|
|
254
|
-
SEQ_ENTRY = [::Yeptris::FFI::BUILD_SEQ, 0, 0, 0].pack("CCx2VV").freeze
|
|
255
|
-
END_ENTRY = [::Yeptris::FFI::BUILD_END, 0, 0, 0].pack("CCx2VV").freeze
|
|
256
|
-
CONT_ENTRY = { ::Yeptris::FFI::BUILD_MAP => MAP_ENTRY, ::Yeptris::FFI::BUILD_SEQ => SEQ_ENTRY,
|
|
257
|
-
::Yeptris::FFI::BUILD_END => END_ENTRY }.freeze
|
|
258
|
-
|
|
259
300
|
def dump(obj)
|
|
260
|
-
parts =
|
|
301
|
+
parts = String.new(encoding: Encoding::BINARY,
|
|
302
|
+
capacity: 12 * 16) # 12-byte entries, appended in place
|
|
261
303
|
blob = String.new(encoding: Encoding::BINARY)
|
|
262
304
|
off = [0]
|
|
263
|
-
|
|
264
|
-
parts << (o.zero? && len.zero? && style.zero? ? CONT_ENTRY[op] :
|
|
265
|
-
[op, style, o, len].pack("CCx2VV"))
|
|
266
|
-
end
|
|
267
|
-
place_obj(obj, emit, blob, off)
|
|
305
|
+
place_obj(obj, parts, blob, off)
|
|
268
306
|
doc = ::Yeptris::Document.create
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
rc = doc.build_entries(buf, parts.length, bblob, blob.bytesize)
|
|
307
|
+
# FFI passes String args BY REFERENCE — no MemoryPointer copies
|
|
308
|
+
rc = doc.build_entries(parts, parts.bytesize / 12, blob, blob.bytesize)
|
|
272
309
|
raise DumpError, "document_build failed: #{rc}" unless rc == ::Yeptris::FFI::OK
|
|
273
310
|
out = ::Yeptris::FFI::JSON_EX ? doc.serialize_json_compact : doc.serialize_json
|
|
274
311
|
# JSON.generate emits no trailing newline (the document writer does)
|
|
@@ -277,37 +314,51 @@ module Yeptris
|
|
|
277
314
|
doc&.free
|
|
278
315
|
end
|
|
279
316
|
|
|
280
|
-
|
|
317
|
+
F = ::Yeptris::FFI
|
|
318
|
+
MAP_E = [F::BUILD_MAP, 0, 0, 0].pack("CCx2VV").freeze
|
|
319
|
+
SEQ_E = [F::BUILD_SEQ, 0, 0, 0].pack("CCx2VV").freeze
|
|
320
|
+
END_E = [F::BUILD_END, 0, 0, 0].pack("CCx2VV").freeze
|
|
321
|
+
DQ = F::STYLE_DOUBLE_QUOTED
|
|
322
|
+
PL = F::STYLE_PLAIN
|
|
323
|
+
SC_DQ = [F::BUILD_SCALAR, DQ].pack("CCx2").freeze
|
|
324
|
+
SC_PL = [F::BUILD_SCALAR, PL].pack("CCx2").freeze
|
|
325
|
+
|
|
326
|
+
def place_obj(obj, parts, blob, off)
|
|
281
327
|
case obj
|
|
282
328
|
when Hash
|
|
283
|
-
|
|
329
|
+
parts << MAP_E
|
|
284
330
|
obj.each do |k, v|
|
|
285
331
|
key = k.is_a?(String) ? k : k.is_a?(Symbol) ? k.name : k.to_s
|
|
286
|
-
scalar_json(key,
|
|
287
|
-
place_obj(v,
|
|
332
|
+
scalar_json(key, SC_DQ, parts, blob, off)
|
|
333
|
+
place_obj(v, parts, blob, off)
|
|
288
334
|
end
|
|
289
|
-
|
|
335
|
+
parts << END_E
|
|
290
336
|
when Array
|
|
291
|
-
|
|
292
|
-
obj.each { |e| place_obj(e,
|
|
293
|
-
|
|
337
|
+
parts << SEQ_E
|
|
338
|
+
obj.each { |e| place_obj(e, parts, blob, off) }
|
|
339
|
+
parts << END_E
|
|
294
340
|
when String
|
|
295
|
-
scalar_json(obj,
|
|
341
|
+
scalar_json(obj, SC_DQ, parts, blob, off)
|
|
296
342
|
when Symbol
|
|
297
|
-
scalar_json(obj.name,
|
|
298
|
-
when Integer, Float
|
|
299
|
-
|
|
300
|
-
|
|
343
|
+
scalar_json(obj.name, SC_DQ, parts, blob, off)
|
|
344
|
+
when Integer, Float
|
|
345
|
+
scalar_json(obj.to_s, SC_PL, parts, blob, off)
|
|
346
|
+
when true
|
|
347
|
+
scalar_json("true", SC_PL, parts, blob, off)
|
|
348
|
+
when false
|
|
349
|
+
scalar_json("false", SC_PL, parts, blob, off)
|
|
350
|
+
when nil
|
|
351
|
+
scalar_json("null", SC_PL, parts, blob, off)
|
|
301
352
|
when Date, Time
|
|
302
|
-
scalar_json(obj.iso8601,
|
|
353
|
+
scalar_json(obj.iso8601, SC_DQ, parts, blob, off)
|
|
303
354
|
else
|
|
304
355
|
raise DumpError, "cannot dump #{obj.class}: unsupported object " \
|
|
305
356
|
"(JSON.generate calls to_json on custom types)"
|
|
306
357
|
end
|
|
307
358
|
end
|
|
308
359
|
|
|
309
|
-
def scalar_json(text,
|
|
310
|
-
|
|
360
|
+
def scalar_json(text, prefix, parts, blob, off)
|
|
361
|
+
parts << (prefix + [off[0], text.bytesize].pack("VV"))
|
|
311
362
|
blob << text
|
|
312
363
|
off[0] += text.bytesize
|
|
313
364
|
end
|
data/lib/yeptris/native.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
|
+
VERSION = "0.3.0.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
|
data/libyeptris.so
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yeptris
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0.1
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|