json 2.13.1 → 2.13.2
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 +4 -0
- data/ext/json/ext/parser/parser.c +49 -4
- data/ext/json/ext/simd/simd.h +47 -46
- data/lib/json/common.rb +18 -17
- data/lib/json/version.rb +1 -1
- 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: 71499860706a6f27871853ec88fe26d5bd6a53f85fba2e9764b9ef0aadc170d9
|
4
|
+
data.tar.gz: c07cd26190c4f36864490465890c162e1b9ce0ae1f262069e51c94d7cf74b117
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1c626d30c67e99c56d9f411b7944b6263261676567c02f6d57ba7566087743b26835d3c6c4c1636a0dc76cc2b8c4e2739a1130f286cd069406c38c66138df97
|
7
|
+
data.tar.gz: eb4fd62079fc730962359e4128f7abd36ca04c17b580506c3e8e3ebdd0e8e0c54c3cf75d1ae899dc53e13697bfa0c11c6c04277d701cfc83fa9ee611785ac85e
|
data/CHANGES.md
CHANGED
@@ -422,10 +422,12 @@ static void emit_parse_warning(const char *message, JSON_ParserState *state)
|
|
422
422
|
long line, column;
|
423
423
|
cursor_position(state, &line, &column);
|
424
424
|
|
425
|
-
|
425
|
+
VALUE warning = rb_sprintf("%s at line %ld column %ld", message, line, column);
|
426
|
+
rb_funcall(mJSON, rb_intern("deprecation_warning"), 1, warning);
|
426
427
|
}
|
427
428
|
|
428
429
|
#define PARSE_ERROR_FRAGMENT_LEN 32
|
430
|
+
|
429
431
|
#ifdef RBIMPL_ATTR_NORETURN
|
430
432
|
RBIMPL_ATTR_NORETURN()
|
431
433
|
#endif
|
@@ -830,21 +832,64 @@ static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig
|
|
830
832
|
return array;
|
831
833
|
}
|
832
834
|
|
835
|
+
static VALUE json_find_duplicated_key(size_t count, const VALUE *pairs)
|
836
|
+
{
|
837
|
+
VALUE set = rb_hash_new_capa(count / 2);
|
838
|
+
for (size_t index = 0; index < count; index += 2) {
|
839
|
+
size_t before = RHASH_SIZE(set);
|
840
|
+
VALUE key = pairs[index];
|
841
|
+
rb_hash_aset(set, key, Qtrue);
|
842
|
+
if (RHASH_SIZE(set) == before) {
|
843
|
+
if (RB_SYMBOL_P(key)) {
|
844
|
+
return rb_sym2str(key);
|
845
|
+
}
|
846
|
+
return key;
|
847
|
+
}
|
848
|
+
}
|
849
|
+
return Qfalse;
|
850
|
+
}
|
851
|
+
|
852
|
+
static void emit_duplicate_key_warning(JSON_ParserState *state, VALUE duplicate_key)
|
853
|
+
{
|
854
|
+
VALUE message = rb_sprintf(
|
855
|
+
"detected duplicate key %"PRIsVALUE" in JSON object. This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`",
|
856
|
+
rb_inspect(duplicate_key)
|
857
|
+
);
|
858
|
+
|
859
|
+
emit_parse_warning(RSTRING_PTR(message), state);
|
860
|
+
RB_GC_GUARD(message);
|
861
|
+
}
|
862
|
+
|
863
|
+
#ifdef RBIMPL_ATTR_NORETURN
|
864
|
+
RBIMPL_ATTR_NORETURN()
|
865
|
+
#endif
|
866
|
+
static void raise_duplicate_key_error(JSON_ParserState *state, VALUE duplicate_key)
|
867
|
+
{
|
868
|
+
VALUE message = rb_sprintf(
|
869
|
+
"duplicate key %"PRIsVALUE,
|
870
|
+
rb_inspect(duplicate_key)
|
871
|
+
);
|
872
|
+
|
873
|
+
raise_parse_error(RSTRING_PTR(message), state);
|
874
|
+
RB_GC_GUARD(message);
|
875
|
+
}
|
876
|
+
|
833
877
|
static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, size_t count)
|
834
878
|
{
|
835
879
|
size_t entries_count = count / 2;
|
836
880
|
VALUE object = rb_hash_new_capa(entries_count);
|
837
|
-
|
881
|
+
const VALUE *pairs = rvalue_stack_peek(state->stack, count);
|
882
|
+
rb_hash_bulk_insert(count, pairs, object);
|
838
883
|
|
839
884
|
if (RB_UNLIKELY(RHASH_SIZE(object) < entries_count)) {
|
840
885
|
switch (config->on_duplicate_key) {
|
841
886
|
case JSON_IGNORE:
|
842
887
|
break;
|
843
888
|
case JSON_DEPRECATED:
|
844
|
-
|
889
|
+
emit_duplicate_key_warning(state, json_find_duplicated_key(count, pairs));
|
845
890
|
break;
|
846
891
|
case JSON_RAISE:
|
847
|
-
|
892
|
+
raise_duplicate_key_error(state, json_find_duplicated_key(count, pairs));
|
848
893
|
break;
|
849
894
|
}
|
850
895
|
}
|
data/ext/json/ext/simd/simd.h
CHANGED
@@ -7,45 +7,45 @@ typedef enum {
|
|
7
7
|
#ifdef JSON_ENABLE_SIMD
|
8
8
|
|
9
9
|
#ifdef __clang__
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
# if __has_builtin(__builtin_ctzll)
|
11
|
+
# define HAVE_BUILTIN_CTZLL 1
|
12
|
+
# else
|
13
|
+
# define HAVE_BUILTIN_CTZLL 0
|
14
|
+
# endif
|
15
15
|
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
16
|
-
|
16
|
+
# define HAVE_BUILTIN_CTZLL 1
|
17
17
|
#else
|
18
|
-
|
18
|
+
# define HAVE_BUILTIN_CTZLL 0
|
19
19
|
#endif
|
20
20
|
|
21
21
|
static inline uint32_t trailing_zeros64(uint64_t input)
|
22
22
|
{
|
23
23
|
#if HAVE_BUILTIN_CTZLL
|
24
|
-
|
24
|
+
return __builtin_ctzll(input);
|
25
25
|
#else
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
uint32_t trailing_zeros = 0;
|
27
|
+
uint64_t temp = input;
|
28
|
+
while ((temp & 1) == 0 && temp > 0) {
|
29
|
+
trailing_zeros++;
|
30
|
+
temp >>= 1;
|
31
|
+
}
|
32
|
+
return trailing_zeros;
|
33
33
|
#endif
|
34
34
|
}
|
35
35
|
|
36
36
|
static inline int trailing_zeros(int input)
|
37
37
|
{
|
38
|
-
|
38
|
+
#if HAVE_BUILTIN_CTZLL
|
39
39
|
return __builtin_ctz(input);
|
40
|
-
|
40
|
+
#else
|
41
41
|
int trailing_zeros = 0;
|
42
42
|
int temp = input;
|
43
43
|
while ((temp & 1) == 0 && temp > 0) {
|
44
|
-
|
45
|
-
|
44
|
+
trailing_zeros++;
|
45
|
+
temp >>= 1;
|
46
46
|
}
|
47
47
|
return trailing_zeros;
|
48
|
-
|
48
|
+
#endif
|
49
49
|
}
|
50
50
|
|
51
51
|
#if (defined(__GNUC__ ) || defined(__clang__))
|
@@ -79,37 +79,38 @@ static inline FORCE_INLINE uint64_t neon_match_mask(uint8x16_t matches)
|
|
79
79
|
|
80
80
|
static inline FORCE_INLINE uint64_t compute_chunk_mask_neon(const char *ptr)
|
81
81
|
{
|
82
|
-
|
82
|
+
uint8x16_t chunk = vld1q_u8((const unsigned char *)ptr);
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
// Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33
|
85
|
+
// https://lemire.me/blog/2025/04/13/detect-control-characters-quotes-and-backslashes-efficiently-using-swar/
|
86
|
+
const uint8x16_t too_low_or_dbl_quote = vcltq_u8(veorq_u8(chunk, vdupq_n_u8(2)), vdupq_n_u8(33));
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
88
|
+
uint8x16_t has_backslash = vceqq_u8(chunk, vdupq_n_u8('\\'));
|
89
|
+
uint8x16_t needs_escape = vorrq_u8(too_low_or_dbl_quote, has_backslash);
|
90
|
+
return neon_match_mask(needs_escape);
|
91
91
|
}
|
92
92
|
|
93
93
|
static inline FORCE_INLINE int string_scan_simd_neon(const char **ptr, const char *end, uint64_t *mask)
|
94
94
|
{
|
95
95
|
while (*ptr + sizeof(uint8x16_t) <= end) {
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
96
|
+
uint64_t chunk_mask = compute_chunk_mask_neon(*ptr);
|
97
|
+
if (chunk_mask) {
|
98
|
+
*mask = chunk_mask;
|
99
|
+
return 1;
|
100
|
+
}
|
101
|
+
*ptr += sizeof(uint8x16_t);
|
102
102
|
}
|
103
103
|
return 0;
|
104
104
|
}
|
105
105
|
|
106
|
-
uint8x16x4_t load_uint8x16_4(const unsigned char *table)
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
106
|
+
static inline uint8x16x4_t load_uint8x16_4(const unsigned char *table)
|
107
|
+
{
|
108
|
+
uint8x16x4_t tab;
|
109
|
+
tab.val[0] = vld1q_u8(table);
|
110
|
+
tab.val[1] = vld1q_u8(table+16);
|
111
|
+
tab.val[2] = vld1q_u8(table+32);
|
112
|
+
tab.val[3] = vld1q_u8(table+48);
|
113
|
+
return tab;
|
113
114
|
}
|
114
115
|
|
115
116
|
#endif /* ARM Neon Support.*/
|
@@ -150,12 +151,12 @@ static inline TARGET_SSE2 FORCE_INLINE int compute_chunk_mask_sse2(const char *p
|
|
150
151
|
static inline TARGET_SSE2 FORCE_INLINE int string_scan_simd_sse2(const char **ptr, const char *end, int *mask)
|
151
152
|
{
|
152
153
|
while (*ptr + sizeof(__m128i) <= end) {
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
154
|
+
int chunk_mask = compute_chunk_mask_sse2(*ptr);
|
155
|
+
if (chunk_mask) {
|
156
|
+
*mask = chunk_mask;
|
157
|
+
return 1;
|
158
|
+
}
|
159
|
+
*ptr += sizeof(__m128i);
|
159
160
|
}
|
160
161
|
|
161
162
|
return 0;
|
data/lib/json/common.rb
CHANGED
@@ -48,7 +48,7 @@ module JSON
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
# TODO:
|
51
|
+
# TODO: extract :create_additions support to another gem for version 3.0
|
52
52
|
def create_additions_proc(opts)
|
53
53
|
if opts[:symbolize_names]
|
54
54
|
raise ArgumentError, "options :symbolize_names and :create_additions cannot be used in conjunction"
|
@@ -87,31 +87,32 @@ module JSON
|
|
87
87
|
opts
|
88
88
|
end
|
89
89
|
|
90
|
-
GEM_ROOT = File.expand_path("../../../", __FILE__) + "/"
|
91
90
|
def create_additions_warning
|
92
|
-
|
91
|
+
JSON.deprecation_warning "JSON.load implicit support for `create_additions: true` is deprecated " \
|
93
92
|
"and will be removed in 3.0, use JSON.unsafe_load or explicitly " \
|
94
93
|
"pass `create_additions: true`"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
95
97
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
if RUBY_VERSION >= "3.0"
|
106
|
-
warn(message, uplevel: uplevel - 1, category: :deprecated)
|
98
|
+
class << self
|
99
|
+
def deprecation_warning(message, uplevel = 3) # :nodoc:
|
100
|
+
gem_root = File.expand_path("../../../", __FILE__) + "/"
|
101
|
+
caller_locations(uplevel, 10).each do |frame|
|
102
|
+
if frame.path.nil? || frame.path.start_with?(gem_root) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c")
|
103
|
+
uplevel += 1
|
107
104
|
else
|
108
|
-
|
105
|
+
break
|
109
106
|
end
|
110
107
|
end
|
108
|
+
|
109
|
+
if RUBY_VERSION >= "3.0"
|
110
|
+
warn(message, uplevel: uplevel, category: :deprecated)
|
111
|
+
else
|
112
|
+
warn(message, uplevel: uplevel)
|
113
|
+
end
|
111
114
|
end
|
112
|
-
end
|
113
115
|
|
114
|
-
class << self
|
115
116
|
# :call-seq:
|
116
117
|
# JSON[object] -> new_array or new_string
|
117
118
|
#
|
data/lib/json/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.13.
|
4
|
+
version: 2.13.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-07-
|
10
|
+
date: 2025-07-28 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
description: This is a JSON implementation as a Ruby extension in C.
|
13
13
|
email: flori@ping.de
|