json 2.15.2 → 2.17.0
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/CHANGES.md +22 -0
- data/LEGAL +12 -0
- data/README.md +17 -1
- data/ext/json/ext/fbuffer/fbuffer.h +9 -58
- data/ext/json/ext/generator/extconf.rb +1 -1
- data/ext/json/ext/generator/generator.c +191 -187
- data/ext/json/ext/json.h +97 -0
- data/ext/json/ext/parser/extconf.rb +2 -1
- data/ext/json/ext/parser/parser.c +497 -388
- data/ext/json/ext/simd/simd.h +15 -12
- data/ext/json/ext/vendor/fpconv.c +2 -2
- data/ext/json/ext/vendor/ryu.h +819 -0
- data/lib/json/common.rb +28 -16
- data/lib/json/ext/generator/state.rb +4 -0
- data/lib/json/truffle_ruby/generator.rb +52 -19
- data/lib/json/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a35454680e80a622fb539155325b2f693e90b352aad3f24b7f9eafc5ca797963
|
|
4
|
+
data.tar.gz: 9eee4f7ce5348a1eb44100766d5a7b326a4e76691fbfd3db8a2410020fb75ec1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0771fad39331fe9d47dbd855a02f662053a79ff08679c8bc76855dcfd3edbcdb32746cc0db435e6ea14815eacdbe97bf1152b704eacb7ddf1423917eb2545923
|
|
7
|
+
data.tar.gz: 742dc87f4cc0306e613cfb65824aaee600aa53f0715135190ffaa4ca1f25aa6820a10b1860befcf90f3dcf6676bd5bb304f0e2858ec1e5933f66b089fca82e78
|
data/CHANGES.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
### Unreleased
|
|
4
4
|
|
|
5
|
+
### 2025-12-03 (2.17.0)
|
|
6
|
+
|
|
7
|
+
* Improve `JSON.load` and `JSON.unsafe_load` to allow passing options as second argument.
|
|
8
|
+
* Fix the parser to no longer ignore invalid escapes in strings.
|
|
9
|
+
Only `\"`, `\\`, `\b`, `\f`, `\n`, `\r`, `\t` and `\u` are valid JSON escapes.
|
|
10
|
+
* Fixed `JSON::Coder` to use the depth it was initialized with.
|
|
11
|
+
* On TruffleRuby, fix the generator to not call `to_json` on the return value of `as_json` for `Float::NAN`.
|
|
12
|
+
* Fixed handling of `state.depth`: when `to_json` changes `state.depth` but does not restore it, it is reset
|
|
13
|
+
automatically to its initial value.
|
|
14
|
+
In particular, when a `NestingError` is raised, `depth` is no longer equal to `max_nesting` after the call to
|
|
15
|
+
generate, and is reset to its initial value. Similarly when `to_json` raises an exception.
|
|
16
|
+
|
|
17
|
+
### 2025-11-07 (2.16.0)
|
|
18
|
+
|
|
19
|
+
* Deprecate `JSON::State#[]` and `JSON::State#[]=`. Consider using `JSON::Coder` instead.
|
|
20
|
+
* `JSON::Coder` now also yields to the block when encountering strings with invalid encoding.
|
|
21
|
+
* Fix GeneratorError messages to be UTF-8 encoded.
|
|
22
|
+
* Fix memory leak when `Exception` is raised, or `throw` is used during JSON generation.
|
|
23
|
+
* Optimized floating point number parsing by integrating the ryu algorithm (thanks to Josef Šimánek).
|
|
24
|
+
* Optimized numbers parsing using SWAR (thanks to Scott Myron).
|
|
25
|
+
* Optimized parsing of pretty printed documents using SWAR (thanks to Scott Myron).
|
|
26
|
+
|
|
5
27
|
### 2025-10-25 (2.15.2)
|
|
6
28
|
|
|
7
29
|
* Fix `JSON::Coder` to have one dedicated depth counter per invocation.
|
data/LEGAL
CHANGED
|
@@ -6,3 +6,15 @@
|
|
|
6
6
|
All the files in this distribution are covered under either the Ruby's
|
|
7
7
|
license (see the file COPYING) or public-domain except some files
|
|
8
8
|
mentioned below.
|
|
9
|
+
|
|
10
|
+
ext/json/ext/vendor/fpconv.h::
|
|
11
|
+
This file is adapted from https://github.com/night-shift/fpconv
|
|
12
|
+
It is licensed under Boost Software License 1.0.
|
|
13
|
+
|
|
14
|
+
ext/json/ext/vendor/jeaiii-ltoa.h::
|
|
15
|
+
This file is adapted from https://github.com/jeaiii/itoa
|
|
16
|
+
It is licensed under the MIT License
|
|
17
|
+
|
|
18
|
+
ext/json/ext/vendor/ryu.h::
|
|
19
|
+
This file is adapted from the Ryu algorithm by Ulf Adams https://github.com/ulfjack/ryu.
|
|
20
|
+
It is dual-licensed under Apache License 2.0 OR Boost Software License 1.0.
|
data/README.md
CHANGED
|
@@ -113,7 +113,23 @@ puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"
|
|
|
113
113
|
The provided block is called for all objects that don't have a native JSON equivalent, and
|
|
114
114
|
must return a Ruby object that has a native JSON equivalent.
|
|
115
115
|
|
|
116
|
-
It is also called for objects that do have a JSON equivalent, but are used as Hash keys, for instance `{ 1 => 2}
|
|
116
|
+
It is also called for objects that do have a JSON equivalent, but are used as Hash keys, for instance `{ 1 => 2}`,
|
|
117
|
+
as well as for strings that aren't valid UTF-8:
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
coder = JSON::Combining.new do |object, is_object_key|
|
|
121
|
+
case object
|
|
122
|
+
when String
|
|
123
|
+
if !string.valid_encoding? || string.encoding != Encoding::UTF_8
|
|
124
|
+
Base64.encode64(string)
|
|
125
|
+
else
|
|
126
|
+
string
|
|
127
|
+
end
|
|
128
|
+
else
|
|
129
|
+
object
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
```
|
|
117
133
|
|
|
118
134
|
## Combining JSON fragments
|
|
119
135
|
|
|
@@ -1,55 +1,9 @@
|
|
|
1
1
|
#ifndef _FBUFFER_H_
|
|
2
2
|
#define _FBUFFER_H_
|
|
3
3
|
|
|
4
|
-
#include "
|
|
5
|
-
#include "ruby/encoding.h"
|
|
4
|
+
#include "../json.h"
|
|
6
5
|
#include "../vendor/jeaiii-ltoa.h"
|
|
7
6
|
|
|
8
|
-
/* shims */
|
|
9
|
-
/* This is the fallback definition from Ruby 3.4 */
|
|
10
|
-
|
|
11
|
-
#ifndef RBIMPL_STDBOOL_H
|
|
12
|
-
#if defined(__cplusplus)
|
|
13
|
-
# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L)
|
|
14
|
-
# include <cstdbool>
|
|
15
|
-
# endif
|
|
16
|
-
#elif defined(HAVE_STDBOOL_H)
|
|
17
|
-
# include <stdbool.h>
|
|
18
|
-
#elif !defined(HAVE__BOOL)
|
|
19
|
-
typedef unsigned char _Bool;
|
|
20
|
-
# define bool _Bool
|
|
21
|
-
# define true ((_Bool)+1)
|
|
22
|
-
# define false ((_Bool)+0)
|
|
23
|
-
# define __bool_true_false_are_defined
|
|
24
|
-
#endif
|
|
25
|
-
#endif
|
|
26
|
-
|
|
27
|
-
#ifndef NOINLINE
|
|
28
|
-
#if defined(__has_attribute) && __has_attribute(noinline)
|
|
29
|
-
#define NOINLINE() __attribute__((noinline))
|
|
30
|
-
#else
|
|
31
|
-
#define NOINLINE()
|
|
32
|
-
#endif
|
|
33
|
-
#endif
|
|
34
|
-
|
|
35
|
-
#ifndef RB_UNLIKELY
|
|
36
|
-
#define RB_UNLIKELY(expr) expr
|
|
37
|
-
#endif
|
|
38
|
-
|
|
39
|
-
#ifndef RB_LIKELY
|
|
40
|
-
#define RB_LIKELY(expr) expr
|
|
41
|
-
#endif
|
|
42
|
-
|
|
43
|
-
#ifndef MAYBE_UNUSED
|
|
44
|
-
# define MAYBE_UNUSED(x) x
|
|
45
|
-
#endif
|
|
46
|
-
|
|
47
|
-
#ifdef RUBY_DEBUG
|
|
48
|
-
#ifndef JSON_DEBUG
|
|
49
|
-
#define JSON_DEBUG RUBY_DEBUG
|
|
50
|
-
#endif
|
|
51
|
-
#endif
|
|
52
|
-
|
|
53
7
|
enum fbuffer_type {
|
|
54
8
|
FBUFFER_HEAP_ALLOCATED = 0,
|
|
55
9
|
FBUFFER_STACK_ALLOCATED = 1,
|
|
@@ -60,7 +14,7 @@ typedef struct FBufferStruct {
|
|
|
60
14
|
unsigned long initial_length;
|
|
61
15
|
unsigned long len;
|
|
62
16
|
unsigned long capa;
|
|
63
|
-
#
|
|
17
|
+
#if JSON_DEBUG
|
|
64
18
|
unsigned long requested;
|
|
65
19
|
#endif
|
|
66
20
|
char *ptr;
|
|
@@ -91,14 +45,14 @@ static void fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *
|
|
|
91
45
|
fb->ptr = stack_buffer;
|
|
92
46
|
fb->capa = stack_buffer_size;
|
|
93
47
|
}
|
|
94
|
-
#
|
|
48
|
+
#if JSON_DEBUG
|
|
95
49
|
fb->requested = 0;
|
|
96
50
|
#endif
|
|
97
51
|
}
|
|
98
52
|
|
|
99
53
|
static inline void fbuffer_consumed(FBuffer *fb, unsigned long consumed)
|
|
100
54
|
{
|
|
101
|
-
#
|
|
55
|
+
#if JSON_DEBUG
|
|
102
56
|
if (consumed > fb->requested) {
|
|
103
57
|
rb_bug("fbuffer: Out of bound write");
|
|
104
58
|
}
|
|
@@ -168,7 +122,7 @@ static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested)
|
|
|
168
122
|
|
|
169
123
|
static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
|
|
170
124
|
{
|
|
171
|
-
#
|
|
125
|
+
#if JSON_DEBUG
|
|
172
126
|
fb->requested = requested;
|
|
173
127
|
#endif
|
|
174
128
|
|
|
@@ -194,7 +148,7 @@ static inline void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long
|
|
|
194
148
|
/* Appends a character into a buffer. The buffer needs to have sufficient capacity, via fbuffer_inc_capa(...). */
|
|
195
149
|
static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
|
|
196
150
|
{
|
|
197
|
-
#
|
|
151
|
+
#if JSON_DEBUG
|
|
198
152
|
if (fb->requested < 1) {
|
|
199
153
|
rb_bug("fbuffer: unreserved write");
|
|
200
154
|
}
|
|
@@ -220,7 +174,7 @@ static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat)
|
|
|
220
174
|
|
|
221
175
|
fbuffer_inc_capa(fb, repeat * len);
|
|
222
176
|
while (repeat) {
|
|
223
|
-
#
|
|
177
|
+
#if JSON_DEBUG
|
|
224
178
|
fb->requested = len;
|
|
225
179
|
#endif
|
|
226
180
|
fbuffer_append_reserved(fb, newstr, len);
|
|
@@ -283,14 +237,11 @@ static VALUE fbuffer_finalize(FBuffer *fb)
|
|
|
283
237
|
{
|
|
284
238
|
if (fb->io) {
|
|
285
239
|
fbuffer_flush(fb);
|
|
286
|
-
fbuffer_free(fb);
|
|
287
240
|
rb_io_flush(fb->io);
|
|
288
241
|
return fb->io;
|
|
289
242
|
} else {
|
|
290
|
-
|
|
291
|
-
fbuffer_free(fb);
|
|
292
|
-
return result;
|
|
243
|
+
return rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
|
|
293
244
|
}
|
|
294
245
|
}
|
|
295
246
|
|
|
296
|
-
#endif
|
|
247
|
+
#endif // _FBUFFER_H_
|
|
@@ -6,7 +6,7 @@ if RUBY_ENGINE == 'truffleruby'
|
|
|
6
6
|
else
|
|
7
7
|
append_cflags("-std=c99")
|
|
8
8
|
$defs << "-DJSON_GENERATOR"
|
|
9
|
-
$defs << "-DJSON_DEBUG" if ENV
|
|
9
|
+
$defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
|
|
10
10
|
|
|
11
11
|
if enable_config('generator-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
|
|
12
12
|
load __dir__ + "/../simd/conf.rb"
|