json_mend 0.1.2 → 0.1.3
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/.rubocop.yml +5 -5
- data/lib/json_mend/parser.rb +36 -10
- data/lib/json_mend/version.rb +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: 96e37cada4ab9945473f6a49b1d57a24c7822dceb0e6402847d129827686202a
|
|
4
|
+
data.tar.gz: b497489826f674239f601203e237ee7358c7305475a2f1a43d37e465d04ce875
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 641ef79051d205ed61c16b9d6deb5f755d41bfb74f3958ac5b1910e2770ac3df2ccdf7e971ba6d44222e7a71de51078b3964da957b44bf70898db13a798ad239
|
|
7
|
+
data.tar.gz: 605ec12dc272c8b1ce7526c8dcf53748e148a58957e6eca9ebf13133ac7f56db46a56161db03227790ddf5c064a582440a3dc02d33bb117f808e536d910f55fe
|
data/.rubocop.yml
CHANGED
|
@@ -7,19 +7,19 @@ AllCops:
|
|
|
7
7
|
SuggestExtensions: false
|
|
8
8
|
|
|
9
9
|
Metrics/AbcSize:
|
|
10
|
-
Max:
|
|
10
|
+
Max: 65
|
|
11
11
|
|
|
12
12
|
Metrics/ClassLength:
|
|
13
|
-
Max:
|
|
13
|
+
Max: 820
|
|
14
14
|
|
|
15
15
|
Metrics/CyclomaticComplexity:
|
|
16
|
-
Max:
|
|
16
|
+
Max: 35
|
|
17
17
|
|
|
18
18
|
Metrics/MethodLength:
|
|
19
|
-
Max:
|
|
19
|
+
Max: 80
|
|
20
20
|
|
|
21
21
|
Metrics/PerceivedComplexity:
|
|
22
|
-
Max:
|
|
22
|
+
Max: 35
|
|
23
23
|
|
|
24
24
|
Metrics/BlockNesting:
|
|
25
25
|
Max: 5
|
data/lib/json_mend/parser.rb
CHANGED
|
@@ -222,8 +222,10 @@ module JsonMend
|
|
|
222
222
|
# Parses the key of an object, including the special logic for merging dangling arrays.
|
|
223
223
|
# Returns [key, was_array_merged_flag]
|
|
224
224
|
def parse_object_key(object)
|
|
225
|
+
char = peek_char
|
|
226
|
+
|
|
225
227
|
# First, check for and handle the dangling array merge logic.
|
|
226
|
-
if try_to_merge_dangling_array(object)
|
|
228
|
+
if char == '[' && try_to_merge_dangling_array(object)
|
|
227
229
|
return [nil, true, false] # Signal that an array was merged.
|
|
228
230
|
end
|
|
229
231
|
|
|
@@ -231,7 +233,7 @@ module JsonMend
|
|
|
231
233
|
@context.push(:object_key)
|
|
232
234
|
is_bracketed = false
|
|
233
235
|
|
|
234
|
-
if
|
|
236
|
+
if char == '['
|
|
235
237
|
@scanner.getch # Consume '['
|
|
236
238
|
arr = parse_array
|
|
237
239
|
key = arr.first.to_s
|
|
@@ -355,7 +357,7 @@ module JsonMend
|
|
|
355
357
|
char = prepare_string_parsing
|
|
356
358
|
|
|
357
359
|
# A valid string can only start with a valid quote or, in our case, with a literal
|
|
358
|
-
while !@scanner.eos? && !STRING_DELIMITERS.include?(char) && !char.match?(/[\p{L}0-9]/)
|
|
360
|
+
while !@scanner.eos? && !STRING_DELIMITERS.include?(char) && !char.match?(/[\p{L}0-9$_-]/)
|
|
359
361
|
return '' if TERMINATORS_STRING_GUESSED.include?(char)
|
|
360
362
|
|
|
361
363
|
@scanner.getch
|
|
@@ -434,7 +436,7 @@ module JsonMend
|
|
|
434
436
|
when '“'
|
|
435
437
|
lstring_delimiter = '“'
|
|
436
438
|
rstring_delimiter = '”'
|
|
437
|
-
when /[\p{L}0-9]/
|
|
439
|
+
when /[\p{L}0-9$_-]/
|
|
438
440
|
# Could be a boolean/null, but not if it's an object key.
|
|
439
441
|
if BOOLEAN_OR_NULL_CHARS.include?(char.downcase) && !current_context?(:object_key)
|
|
440
442
|
# parse_literal is non-destructive if it fails to match.
|
|
@@ -509,6 +511,17 @@ module JsonMend
|
|
|
509
511
|
unmatched_delimiter = false
|
|
510
512
|
# --- Main Parsing Loop ---
|
|
511
513
|
while !@scanner.eos? && char != rstring_delimiter
|
|
514
|
+
# Fast-path for unquoted keys (e.g. { key: val })
|
|
515
|
+
# consumes a chunk of valid identifier characters at once
|
|
516
|
+
if missing_quotes && current_context?(:object_key)
|
|
517
|
+
chunk = @scanner.scan(/[a-zA-Z0-9_$-]+/)
|
|
518
|
+
if chunk
|
|
519
|
+
string_parts << chunk
|
|
520
|
+
char = peek_char
|
|
521
|
+
next
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
|
|
512
525
|
break if context_termination_reached?(
|
|
513
526
|
char:,
|
|
514
527
|
missing_quotes:
|
|
@@ -1170,16 +1183,29 @@ module JsonMend
|
|
|
1170
1183
|
|
|
1171
1184
|
# Peeks the next character without advancing the scanner
|
|
1172
1185
|
def peek_char(offset = 0)
|
|
1173
|
-
|
|
1186
|
+
# Handle the common 0-offset case
|
|
1187
|
+
if offset.zero?
|
|
1188
|
+
# peek(1) returns the next BYTE, not character
|
|
1189
|
+
byte_str = @scanner.peek(1)
|
|
1190
|
+
return nil if byte_str.empty?
|
|
1191
|
+
|
|
1192
|
+
# Fast path: If it's a standard ASCII char (0-127), return it directly.
|
|
1193
|
+
# This avoids the regex overhead for standard JSON characters ({, [, ", etc).
|
|
1194
|
+
return byte_str if byte_str.getbyte(0) < 128
|
|
1195
|
+
|
|
1196
|
+
# Slow path: If it's a multibyte char (e.g. “), use regex to match the full character.
|
|
1197
|
+
return @scanner.check(/./m)
|
|
1198
|
+
end
|
|
1174
1199
|
|
|
1200
|
+
# For offsets > 0, we must scan to skip correctly (as characters can be variable width)
|
|
1175
1201
|
saved_pos = @scanner.pos
|
|
1176
|
-
|
|
1202
|
+
res = nil
|
|
1177
1203
|
(offset + 1).times do
|
|
1178
|
-
|
|
1179
|
-
break if
|
|
1204
|
+
res = @scanner.getch
|
|
1205
|
+
break if res.nil?
|
|
1180
1206
|
end
|
|
1181
1207
|
@scanner.pos = saved_pos
|
|
1182
|
-
|
|
1208
|
+
res
|
|
1183
1209
|
end
|
|
1184
1210
|
|
|
1185
1211
|
def current_context?(value)
|
|
@@ -1192,7 +1218,7 @@ module JsonMend
|
|
|
1192
1218
|
|
|
1193
1219
|
# Checks if the character signifies the start of a string or literal
|
|
1194
1220
|
def string_start?(char)
|
|
1195
|
-
STRING_DELIMITERS.include?(char) || char&.match?(
|
|
1221
|
+
STRING_DELIMITERS.include?(char) || char&.match?(/[\p{L}$_]/)
|
|
1196
1222
|
end
|
|
1197
1223
|
|
|
1198
1224
|
# Checks if the character signifies the start of a number
|
data/lib/json_mend/version.rb
CHANGED