JsonhPy 2.5__tar.gz → 2.6__tar.gz
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.
- {jsonhpy-2.5 → jsonhpy-2.6}/PKG-INFO +1 -1
- {jsonhpy-2.5 → jsonhpy-2.6}/pyproject.toml +1 -1
- {jsonhpy-2.5 → jsonhpy-2.6}/src/JsonhPy/JsonhPy.py +105 -97
- {jsonhpy-2.5 → jsonhpy-2.6}/src/JsonhPy.egg-info/PKG-INFO +1 -1
- {jsonhpy-2.5 → jsonhpy-2.6}/LICENSE.md +0 -0
- {jsonhpy-2.5 → jsonhpy-2.6}/README.md +0 -0
- {jsonhpy-2.5 → jsonhpy-2.6}/setup.cfg +0 -0
- {jsonhpy-2.5 → jsonhpy-2.6}/src/JsonhPy/__init__.py +0 -0
- {jsonhpy-2.5 → jsonhpy-2.6}/src/JsonhPy.egg-info/SOURCES.txt +0 -0
- {jsonhpy-2.5 → jsonhpy-2.6}/src/JsonhPy.egg-info/dependency_links.txt +0 -0
- {jsonhpy-2.5 → jsonhpy-2.6}/src/JsonhPy.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import math
|
|
2
2
|
from enum import Enum
|
|
3
|
-
from typing import Iterator, Iterable
|
|
3
|
+
from typing import Iterator, Iterable, cast
|
|
4
4
|
import json
|
|
5
5
|
|
|
6
6
|
class JsonhResult[T, E]:
|
|
@@ -8,28 +8,28 @@ class JsonhResult[T, E]:
|
|
|
8
8
|
value_or_none: T | None
|
|
9
9
|
error_or_none: E | None
|
|
10
10
|
|
|
11
|
-
def __init__(self, is_error: bool, value_or_none: T | None = None, error_or_none: E | None = None):
|
|
11
|
+
def __init__(self, is_error: bool, value_or_none: T | None = None, error_or_none: E | None = None) -> None:
|
|
12
12
|
self.is_error = is_error
|
|
13
13
|
self.value_or_none = value_or_none
|
|
14
14
|
self.error_or_none = error_or_none
|
|
15
15
|
|
|
16
16
|
@staticmethod
|
|
17
|
-
def from_value[
|
|
18
|
-
return JsonhResult(False, value, None)
|
|
17
|
+
def from_value[_T, _E](value: _T = None) -> "JsonhResult[_T, _E]": # type: ignore
|
|
18
|
+
return JsonhResult[_T, _E](False, value, None)
|
|
19
19
|
|
|
20
20
|
@staticmethod
|
|
21
|
-
def from_error[
|
|
22
|
-
return JsonhResult(True, None, error)
|
|
21
|
+
def from_error[_T, _E](error: _E = None) -> "JsonhResult[_T, _E]": # type: ignore
|
|
22
|
+
return JsonhResult[_T, _E](True, None, error)
|
|
23
23
|
|
|
24
24
|
def value(self) -> T:
|
|
25
25
|
if self.is_error:
|
|
26
26
|
raise RuntimeError(f"Result was error: {self.error_or_none}")
|
|
27
|
-
return self.value_or_none
|
|
27
|
+
return self.value_or_none # type: ignore
|
|
28
28
|
|
|
29
29
|
def error(self) -> E:
|
|
30
30
|
if not self.is_error:
|
|
31
31
|
raise RuntimeError(f"Result was value: {self.value_or_none}")
|
|
32
|
-
return self.error_or_none
|
|
32
|
+
return self.error_or_none # type: ignore
|
|
33
33
|
|
|
34
34
|
def __repr__(self) -> str:
|
|
35
35
|
if self.is_error:
|
|
@@ -39,7 +39,7 @@ class JsonhResult[T, E]:
|
|
|
39
39
|
class JsonhRef[T]:
|
|
40
40
|
ref: T
|
|
41
41
|
|
|
42
|
-
def __init__(self, ref: T):
|
|
42
|
+
def __init__(self, ref: T) -> None:
|
|
43
43
|
self.ref = ref
|
|
44
44
|
|
|
45
45
|
class JsonhVersion(Enum):
|
|
@@ -135,10 +135,13 @@ class JsonTokenType(Enum):
|
|
|
135
135
|
"""
|
|
136
136
|
|
|
137
137
|
class JsonhToken:
|
|
138
|
+
"""
|
|
139
|
+
A single JSONH token.
|
|
140
|
+
"""
|
|
138
141
|
json_type: JsonTokenType
|
|
139
142
|
value: str
|
|
140
143
|
|
|
141
|
-
def __init__(self, json_type: JsonTokenType, value: str = ""):
|
|
144
|
+
def __init__(self, json_type: JsonTokenType, value: str = "") -> None:
|
|
142
145
|
self.json_type = json_type
|
|
143
146
|
self.value = value
|
|
144
147
|
|
|
@@ -185,7 +188,7 @@ class JsonhNumberParser:
|
|
|
185
188
|
|
|
186
189
|
# Apply sign
|
|
187
190
|
if sign != 1:
|
|
188
|
-
number.value_or_none *= sign
|
|
191
|
+
number.value_or_none *= sign # type: ignore
|
|
189
192
|
return number
|
|
190
193
|
|
|
191
194
|
@staticmethod
|
|
@@ -306,7 +309,7 @@ class JsonhNumberParser:
|
|
|
306
309
|
return JsonhResult.from_value(integer)
|
|
307
310
|
|
|
308
311
|
@staticmethod
|
|
309
|
-
def _index_of_any(input: str, chars: Iterable[str]) ->
|
|
312
|
+
def _index_of_any(input: str, chars: Iterable[str]) -> int:
|
|
310
313
|
for i in range(0, len(input)):
|
|
311
314
|
char: str = input[i]
|
|
312
315
|
if char in chars:
|
|
@@ -317,7 +320,7 @@ class JsonhReaderOptions:
|
|
|
317
320
|
"""
|
|
318
321
|
Options for a JsonhReader.
|
|
319
322
|
"""
|
|
320
|
-
version: JsonhVersion.LATEST
|
|
323
|
+
version: JsonhVersion = JsonhVersion.LATEST
|
|
321
324
|
"""
|
|
322
325
|
Specifies the major version of the JSONH specification to use.
|
|
323
326
|
"""
|
|
@@ -363,7 +366,7 @@ class JsonhReaderOptions:
|
|
|
363
366
|
Only some tokens can be incomplete in this mode, so it should not be relied upon.
|
|
364
367
|
"""
|
|
365
368
|
|
|
366
|
-
def __init__(self, version: JsonhVersion = JsonhVersion.LATEST, parse_single_element: bool = False, max_depth: int = 64, incomplete_inputs: bool = False):
|
|
369
|
+
def __init__(self, version: JsonhVersion = JsonhVersion.LATEST, parse_single_element: bool = False, max_depth: int = 64, incomplete_inputs: bool = False) -> None:
|
|
367
370
|
"""
|
|
368
371
|
Constructs options for a JsonhReader.
|
|
369
372
|
"""
|
|
@@ -385,11 +388,14 @@ class JsonhReaderOptions:
|
|
|
385
388
|
return options_version.value >= given_version.value
|
|
386
389
|
|
|
387
390
|
class JsonhReader:
|
|
391
|
+
"""
|
|
392
|
+
A reader that reads JSONH tokens from a `str`.
|
|
393
|
+
"""
|
|
388
394
|
string: str
|
|
389
395
|
"""
|
|
390
396
|
The string to read characters from.
|
|
391
397
|
"""
|
|
392
|
-
|
|
398
|
+
string_index: int
|
|
393
399
|
"""
|
|
394
400
|
The index in the string.
|
|
395
401
|
"""
|
|
@@ -438,7 +444,7 @@ class JsonhReader:
|
|
|
438
444
|
Constructs a reader that reads JSONH from a string.
|
|
439
445
|
"""
|
|
440
446
|
self.string = string
|
|
441
|
-
self.
|
|
447
|
+
self.string_index = 0
|
|
442
448
|
self.options = options
|
|
443
449
|
self.char_counter = 0
|
|
444
450
|
self.depth = 0
|
|
@@ -466,12 +472,12 @@ class JsonhReader:
|
|
|
466
472
|
return True
|
|
467
473
|
# Array item
|
|
468
474
|
if current_property_name == None:
|
|
469
|
-
current_array: list[object] = current_elements[-1]
|
|
475
|
+
current_array: list[object] = cast(list[object], current_elements[-1])
|
|
470
476
|
current_array.append(element)
|
|
471
477
|
return False
|
|
472
478
|
# Object property
|
|
473
479
|
else:
|
|
474
|
-
current_object: dict[str, object] = current_elements[-1]
|
|
480
|
+
current_object: dict[str, object] = cast(dict[str, object], current_elements[-1])
|
|
475
481
|
current_object[current_property_name] = element
|
|
476
482
|
current_property_name = None
|
|
477
483
|
return False
|
|
@@ -495,40 +501,40 @@ class JsonhReader:
|
|
|
495
501
|
match token_result.value().json_type:
|
|
496
502
|
# Null
|
|
497
503
|
case JsonTokenType.NULL:
|
|
498
|
-
|
|
499
|
-
if submit_element(
|
|
500
|
-
return JsonhResult.from_value(
|
|
504
|
+
element_null: None = None
|
|
505
|
+
if submit_element(element_null):
|
|
506
|
+
return JsonhResult.from_value(element_null)
|
|
501
507
|
# True
|
|
502
508
|
case JsonTokenType.TRUE:
|
|
503
|
-
|
|
504
|
-
if submit_element(
|
|
505
|
-
return JsonhResult.from_value(
|
|
509
|
+
element_true: bool = True
|
|
510
|
+
if submit_element(element_true):
|
|
511
|
+
return JsonhResult.from_value(element_true)
|
|
506
512
|
# False
|
|
507
513
|
case JsonTokenType.FALSE:
|
|
508
|
-
|
|
509
|
-
if submit_element(
|
|
510
|
-
return JsonhResult.from_value(
|
|
514
|
+
element_false: bool = False
|
|
515
|
+
if submit_element(element_false):
|
|
516
|
+
return JsonhResult.from_value(element_false)
|
|
511
517
|
# String
|
|
512
518
|
case JsonTokenType.STRING:
|
|
513
|
-
|
|
514
|
-
if submit_element(
|
|
515
|
-
return JsonhResult.from_value(
|
|
519
|
+
element_string: str = token_result.value().value
|
|
520
|
+
if submit_element(element_string):
|
|
521
|
+
return JsonhResult.from_value(element_string)
|
|
516
522
|
# Number
|
|
517
523
|
case JsonTokenType.NUMBER:
|
|
518
|
-
result: JsonhResult[float] = JsonhNumberParser.parse(token_result.value().value)
|
|
524
|
+
result: JsonhResult[float, str] = JsonhNumberParser.parse(token_result.value().value)
|
|
519
525
|
if result.is_error:
|
|
520
526
|
return JsonhResult.from_error(result.error())
|
|
521
|
-
|
|
522
|
-
if submit_element(
|
|
523
|
-
return JsonhResult.from_value(
|
|
527
|
+
element_number: float = result.value()
|
|
528
|
+
if submit_element(element_number):
|
|
529
|
+
return JsonhResult.from_value(element_number)
|
|
524
530
|
# Start Object
|
|
525
531
|
case JsonTokenType.START_OBJECT:
|
|
526
|
-
|
|
527
|
-
start_element(
|
|
532
|
+
element_object: dict[str, object] = {}
|
|
533
|
+
start_element(element_object)
|
|
528
534
|
# Start Array
|
|
529
535
|
case JsonTokenType.START_ARRAY:
|
|
530
|
-
|
|
531
|
-
start_element(
|
|
536
|
+
element_array: list[object] = []
|
|
537
|
+
start_element(element_array)
|
|
532
538
|
# End Object/Array
|
|
533
539
|
case JsonTokenType.END_OBJECT | JsonTokenType.END_ARRAY:
|
|
534
540
|
# Nested element
|
|
@@ -547,6 +553,9 @@ class JsonhReader:
|
|
|
547
553
|
case _:
|
|
548
554
|
return JsonhResult.from_error("Token type not implemented")
|
|
549
555
|
|
|
556
|
+
# End of input
|
|
557
|
+
return JsonhResult.from_error("Expected token, got end of input")
|
|
558
|
+
|
|
550
559
|
next_element: JsonhResult[object, str] = parse_next_element()
|
|
551
560
|
|
|
552
561
|
# Ensure exactly one element
|
|
@@ -571,21 +580,21 @@ class JsonhReader:
|
|
|
571
580
|
|
|
572
581
|
def parse_next_element_as_json() -> JsonhResult[str, str]:
|
|
573
582
|
current_depth: int = 0
|
|
574
|
-
|
|
583
|
+
is_start_of_structure: bool = True
|
|
575
584
|
is_property_value: bool = False
|
|
576
585
|
|
|
577
586
|
result_builder: str = ""
|
|
578
587
|
|
|
579
588
|
for token_result in self.read_element():
|
|
580
589
|
# Check error
|
|
581
|
-
if
|
|
590
|
+
if token_result.is_error:
|
|
582
591
|
return JsonhResult.from_error(token_result.error())
|
|
583
592
|
token: JsonhToken = token_result.value()
|
|
584
593
|
|
|
585
594
|
# Add comments and indents
|
|
586
595
|
if not is_property_value:
|
|
587
596
|
# Add comma before property/item
|
|
588
|
-
if (token.json_type not in [JsonTokenType.NONE, JsonTokenType.COMMENT]) and (current_depth > 0) and (not
|
|
597
|
+
if (token.json_type not in [JsonTokenType.NONE, JsonTokenType.COMMENT]) and (current_depth > 0) and (not is_start_of_structure):
|
|
589
598
|
# Don't add trailing comma
|
|
590
599
|
if token.json_type not in [JsonTokenType.END_OBJECT, JsonTokenType.END_ARRAY]:
|
|
591
600
|
result_builder += ','
|
|
@@ -593,9 +602,9 @@ class JsonhReader:
|
|
|
593
602
|
# Apply indentation
|
|
594
603
|
if indent != None:
|
|
595
604
|
# Don't indent inside empty structures
|
|
596
|
-
if not (token.json_type in [JsonTokenType.END_OBJECT, JsonTokenType.END_ARRAY] and
|
|
605
|
+
if not (token.json_type in [JsonTokenType.END_OBJECT, JsonTokenType.END_ARRAY] and is_start_of_structure):
|
|
597
606
|
# Don't indent comment if not included
|
|
598
|
-
if
|
|
607
|
+
if not (token.json_type == JsonTokenType.COMMENT and (not include_comments)):
|
|
599
608
|
# Don't indent root elements
|
|
600
609
|
if current_depth > 0:
|
|
601
610
|
# Add newline before element
|
|
@@ -611,9 +620,9 @@ class JsonhReader:
|
|
|
611
620
|
result_builder += indent
|
|
612
621
|
# Track start of structure to avoid adding leading comma
|
|
613
622
|
if token.json_type not in [JsonTokenType.NONE, JsonTokenType.COMMENT]:
|
|
614
|
-
|
|
623
|
+
is_start_of_structure = False
|
|
615
624
|
if token.json_type in [JsonTokenType.START_OBJECT, JsonTokenType.START_ARRAY]:
|
|
616
|
-
|
|
625
|
+
is_start_of_structure = True
|
|
617
626
|
|
|
618
627
|
match token.json_type:
|
|
619
628
|
# Null
|
|
@@ -638,8 +647,8 @@ class JsonhReader:
|
|
|
638
647
|
return JsonhResult.from_value(result_builder)
|
|
639
648
|
# Number
|
|
640
649
|
case JsonTokenType.NUMBER:
|
|
641
|
-
result: JsonhResult[float] = JsonhNumberParser.parse(token_result.value().value)
|
|
642
|
-
if
|
|
650
|
+
result: JsonhResult[float, str] = JsonhNumberParser.parse(token_result.value().value)
|
|
651
|
+
if result.is_error:
|
|
643
652
|
return JsonhResult.from_error(result.error())
|
|
644
653
|
result_builder += str(result.value()).removesuffix(".0")
|
|
645
654
|
if current_depth == 0:
|
|
@@ -672,7 +681,7 @@ class JsonhReader:
|
|
|
672
681
|
result_builder += ' '
|
|
673
682
|
# Comment
|
|
674
683
|
case JsonTokenType.COMMENT:
|
|
675
|
-
if
|
|
684
|
+
if include_comments:
|
|
676
685
|
result_builder += "/*"
|
|
677
686
|
result_builder += token.value.replace("/*", "/ *").replace("*/", "* /")
|
|
678
687
|
result_builder += "*/"
|
|
@@ -745,7 +754,7 @@ class JsonhReader:
|
|
|
745
754
|
# Peek char
|
|
746
755
|
return self._peek() != None
|
|
747
756
|
|
|
748
|
-
def read_end_of_elements(self) -> Iterator[JsonhResult]:
|
|
757
|
+
def read_end_of_elements(self) -> Iterator[JsonhResult[JsonhToken, str]]:
|
|
749
758
|
"""
|
|
750
759
|
Reads comments and whitespace and errors if the reader contains another element.
|
|
751
760
|
"""
|
|
@@ -840,6 +849,7 @@ class JsonhReader:
|
|
|
840
849
|
return
|
|
841
850
|
# Missing closing brace
|
|
842
851
|
yield JsonhResult.from_error("Expected `}` to end object, got end of input")
|
|
852
|
+
return
|
|
843
853
|
|
|
844
854
|
# Closing brace
|
|
845
855
|
if next == '}':
|
|
@@ -964,14 +974,12 @@ class JsonhReader:
|
|
|
964
974
|
# Optional comma
|
|
965
975
|
self._read_one(',')
|
|
966
976
|
|
|
967
|
-
def _read_property_name(self
|
|
977
|
+
def _read_property_name(self) -> Iterator[JsonhResult[JsonhToken, str]]:
|
|
968
978
|
# String
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
return
|
|
974
|
-
string = string_token.value().value
|
|
979
|
+
string_token: JsonhResult[JsonhToken, str] = self._read_string()
|
|
980
|
+
if string_token.is_error:
|
|
981
|
+
yield string_token
|
|
982
|
+
return
|
|
975
983
|
|
|
976
984
|
# Comments & whitespace
|
|
977
985
|
for token in self._read_comments_and_whitespace():
|
|
@@ -986,7 +994,7 @@ class JsonhReader:
|
|
|
986
994
|
return
|
|
987
995
|
|
|
988
996
|
# End of property name
|
|
989
|
-
yield JsonhResult.from_value(JsonhToken(JsonTokenType.PROPERTY_NAME,
|
|
997
|
+
yield JsonhResult.from_value(JsonhToken(JsonTokenType.PROPERTY_NAME, string_token.value().value))
|
|
990
998
|
|
|
991
999
|
def _read_array(self) -> Iterator[JsonhResult[JsonhToken, str]]:
|
|
992
1000
|
# Opening bracket
|
|
@@ -1071,7 +1079,7 @@ class JsonhReader:
|
|
|
1071
1079
|
return self._read_quoteless_string("", is_verbatim)
|
|
1072
1080
|
|
|
1073
1081
|
# Count multiple quotes
|
|
1074
|
-
start_quote_counter = 1
|
|
1082
|
+
start_quote_counter: int = 1
|
|
1075
1083
|
while self._read_one(start_quote):
|
|
1076
1084
|
start_quote_counter += 1
|
|
1077
1085
|
|
|
@@ -1086,24 +1094,24 @@ class JsonhReader:
|
|
|
1086
1094
|
string_builder: str = ""
|
|
1087
1095
|
|
|
1088
1096
|
while True:
|
|
1089
|
-
|
|
1090
|
-
if
|
|
1097
|
+
next2: str | None = self._read()
|
|
1098
|
+
if next2 == None:
|
|
1091
1099
|
return JsonhResult.from_error("Expected end of string, got end of input")
|
|
1092
1100
|
|
|
1093
1101
|
# Partial end quote was actually part of string
|
|
1094
|
-
if
|
|
1102
|
+
if next2 != start_quote:
|
|
1095
1103
|
string_builder += start_quote * end_quote_counter
|
|
1096
1104
|
end_quote_counter = 0
|
|
1097
1105
|
|
|
1098
1106
|
# End quote
|
|
1099
|
-
if
|
|
1107
|
+
if next2 == start_quote:
|
|
1100
1108
|
end_quote_counter += 1
|
|
1101
1109
|
if end_quote_counter == start_quote_counter:
|
|
1102
1110
|
break
|
|
1103
1111
|
# Escape sequence
|
|
1104
|
-
elif
|
|
1112
|
+
elif next2 == '\\':
|
|
1105
1113
|
if is_verbatim:
|
|
1106
|
-
string_builder +=
|
|
1114
|
+
string_builder += next2
|
|
1107
1115
|
else:
|
|
1108
1116
|
escape_sequence_result: JsonhResult[str, str] = self._read_escape_sequence()
|
|
1109
1117
|
if escape_sequence_result.is_error:
|
|
@@ -1111,7 +1119,7 @@ class JsonhReader:
|
|
|
1111
1119
|
string_builder += escape_sequence_result.value()
|
|
1112
1120
|
# Literal character
|
|
1113
1121
|
else:
|
|
1114
|
-
string_builder +=
|
|
1122
|
+
string_builder += next2
|
|
1115
1123
|
|
|
1116
1124
|
# Condition: skip remaining steps unless started with multiple quotes
|
|
1117
1125
|
if start_quote_counter > 1:
|
|
@@ -1120,19 +1128,19 @@ class JsonhReader:
|
|
|
1120
1128
|
leading_whitespace_newline_counter: int = 0
|
|
1121
1129
|
index: int = 0
|
|
1122
1130
|
while index < len(string_builder):
|
|
1123
|
-
|
|
1131
|
+
next3: str = string_builder[index]
|
|
1124
1132
|
|
|
1125
1133
|
# Newline
|
|
1126
|
-
if
|
|
1134
|
+
if next3 in self._NEWLINE_CHARS:
|
|
1127
1135
|
# Join CR LF
|
|
1128
|
-
if
|
|
1136
|
+
if next3 == '\r' and index + 1 < len(string_builder) and string_builder[index + 1] == '\n':
|
|
1129
1137
|
index += 1
|
|
1130
1138
|
|
|
1131
1139
|
has_leading_whitespace_newline = True
|
|
1132
1140
|
leading_whitespace_newline_counter = index + 1
|
|
1133
1141
|
break
|
|
1134
1142
|
# Non-whitespace
|
|
1135
|
-
elif
|
|
1143
|
+
elif next3 not in self._WHITESPACE_CHARS:
|
|
1136
1144
|
break
|
|
1137
1145
|
|
|
1138
1146
|
index += 1
|
|
@@ -1145,19 +1153,19 @@ class JsonhReader:
|
|
|
1145
1153
|
trailing_whitespace_counter: int = 0
|
|
1146
1154
|
index: int = 0
|
|
1147
1155
|
while index < len(string_builder):
|
|
1148
|
-
|
|
1156
|
+
next4: str = string_builder[index]
|
|
1149
1157
|
|
|
1150
1158
|
# Newline
|
|
1151
|
-
if
|
|
1159
|
+
if next4 in self._NEWLINE_CHARS:
|
|
1152
1160
|
has_trailing_newline_whitespace = True
|
|
1153
1161
|
last_newline_index = index
|
|
1154
1162
|
trailing_whitespace_counter = 0
|
|
1155
1163
|
|
|
1156
1164
|
# Join CR LF
|
|
1157
|
-
if
|
|
1165
|
+
if next4 == '\r' and index + 1 < len(string_builder) and string_builder[index + 1] == '\n':
|
|
1158
1166
|
index += 1
|
|
1159
1167
|
# Whitespace
|
|
1160
|
-
elif
|
|
1168
|
+
elif next4 in self._WHITESPACE_CHARS:
|
|
1161
1169
|
trailing_whitespace_counter += 1
|
|
1162
1170
|
# Non-whitespace
|
|
1163
1171
|
else:
|
|
@@ -1181,14 +1189,14 @@ class JsonhReader:
|
|
|
1181
1189
|
line_leading_whitespace_counter: int = 0
|
|
1182
1190
|
index: int = 0
|
|
1183
1191
|
while index < len(string_builder):
|
|
1184
|
-
|
|
1192
|
+
next5: str = string_builder[index]
|
|
1185
1193
|
|
|
1186
1194
|
# Newline
|
|
1187
|
-
if
|
|
1195
|
+
if next5 in self._NEWLINE_CHARS:
|
|
1188
1196
|
is_line_leading_whitespace = True
|
|
1189
1197
|
line_leading_whitespace_counter = 0
|
|
1190
1198
|
# Whitespace
|
|
1191
|
-
elif
|
|
1199
|
+
elif next5 in self._WHITESPACE_CHARS:
|
|
1192
1200
|
if is_line_leading_whitespace:
|
|
1193
1201
|
# Increment line-leading whitespace
|
|
1194
1202
|
line_leading_whitespace_counter += 1
|
|
@@ -1232,7 +1240,7 @@ class JsonhReader:
|
|
|
1232
1240
|
if is_verbatim:
|
|
1233
1241
|
string_builder += next
|
|
1234
1242
|
else:
|
|
1235
|
-
escape_sequence_result: JsonhResult[str] = self._read_escape_sequence()
|
|
1243
|
+
escape_sequence_result: JsonhResult[str, str] = self._read_escape_sequence()
|
|
1236
1244
|
if escape_sequence_result.is_error:
|
|
1237
1245
|
return JsonhResult.from_error(escape_sequence_result.error())
|
|
1238
1246
|
string_builder += escape_sequence_result.value()
|
|
@@ -1338,9 +1346,9 @@ class JsonhReader:
|
|
|
1338
1346
|
has_leading_zero = False
|
|
1339
1347
|
|
|
1340
1348
|
# Read main number
|
|
1341
|
-
main_result: JsonhResult[None,
|
|
1349
|
+
main_result: JsonhResult[None, str] = self._read_number_no_exponent(number_builder, base_digits, has_base_specifier, has_leading_zero)
|
|
1342
1350
|
if main_result.is_error:
|
|
1343
|
-
number: JsonhResult[
|
|
1351
|
+
number: JsonhResult[JsonhToken, str] = JsonhResult.from_error(main_result.error())
|
|
1344
1352
|
partial_chars_read: str = number_builder.ref
|
|
1345
1353
|
return number, partial_chars_read
|
|
1346
1354
|
|
|
@@ -1353,16 +1361,16 @@ class JsonhReader:
|
|
|
1353
1361
|
|
|
1354
1362
|
# Missing digit between base specifier and exponent (e.g. `0xe+`)
|
|
1355
1363
|
if has_base_specifier and len(number_builder.ref) == 4:
|
|
1356
|
-
|
|
1364
|
+
number2: JsonhResult[JsonhToken, str] = JsonhResult.from_error("Missing digit between base specifier and exponent")
|
|
1357
1365
|
partial_chars_read: str = number_builder.ref
|
|
1358
|
-
return
|
|
1366
|
+
return number2, partial_chars_read
|
|
1359
1367
|
|
|
1360
1368
|
# Read exponent number
|
|
1361
|
-
exponent_result: JsonhResult[None,
|
|
1369
|
+
exponent_result: JsonhResult[None, str] = self._read_number_no_exponent(number_builder, base_digits)
|
|
1362
1370
|
if exponent_result.is_error:
|
|
1363
|
-
|
|
1371
|
+
number3: JsonhResult[JsonhToken, str] = JsonhResult.from_error(exponent_result.error())
|
|
1364
1372
|
partial_chars_read: str = number_builder.ref
|
|
1365
|
-
return
|
|
1373
|
+
return number3, partial_chars_read
|
|
1366
1374
|
# Exponent
|
|
1367
1375
|
else:
|
|
1368
1376
|
exponent_char: str | None = self._read_any('e', 'E')
|
|
@@ -1375,20 +1383,20 @@ class JsonhReader:
|
|
|
1375
1383
|
number_builder.ref += exponent_sign
|
|
1376
1384
|
|
|
1377
1385
|
# Read exponent number
|
|
1378
|
-
|
|
1379
|
-
if
|
|
1380
|
-
|
|
1386
|
+
exponent_result2: JsonhResult[None, str] = self._read_number_no_exponent(number_builder, base_digits)
|
|
1387
|
+
if exponent_result2.is_error:
|
|
1388
|
+
number4: JsonhResult[JsonhToken, str] = JsonhResult.from_error(exponent_result2.error())
|
|
1381
1389
|
partial_chars_read: str = number_builder.ref
|
|
1382
|
-
return
|
|
1390
|
+
return number4, partial_chars_read
|
|
1383
1391
|
|
|
1384
1392
|
# End of number
|
|
1385
|
-
|
|
1393
|
+
number5: JsonhResult[JsonhToken, str] = JsonhResult.from_value(JsonhToken(JsonTokenType.NUMBER, number_builder.ref))
|
|
1386
1394
|
partial_chars_read: str = ""
|
|
1387
|
-
return
|
|
1395
|
+
return number5, partial_chars_read
|
|
1388
1396
|
|
|
1389
|
-
def _read_number_no_exponent(self, number_builder: JsonhRef[str], base_digits: str, has_base_specifier: bool = False, has_leading_zero: bool = False) -> JsonhResult[None,
|
|
1397
|
+
def _read_number_no_exponent(self, number_builder: JsonhRef[str], base_digits: str, has_base_specifier: bool = False, has_leading_zero: bool = False) -> JsonhResult[None, str]:
|
|
1390
1398
|
# Leading underscore
|
|
1391
|
-
if (not has_base_specifier) and not
|
|
1399
|
+
if (not has_base_specifier) and (not has_leading_zero) and self._peek() == '_':
|
|
1392
1400
|
return JsonhResult.from_error("Leading `_` in number")
|
|
1393
1401
|
|
|
1394
1402
|
is_fraction: bool = False
|
|
@@ -1707,16 +1715,16 @@ class JsonhReader:
|
|
|
1707
1715
|
return code_point >= 0xDC00 and code_point <= 0xDFFF
|
|
1708
1716
|
|
|
1709
1717
|
def _peek(self) -> str | None:
|
|
1710
|
-
if self.
|
|
1718
|
+
if self.string_index >= len(self.string):
|
|
1711
1719
|
return None
|
|
1712
|
-
next: str = self.string[self.
|
|
1720
|
+
next: str = self.string[self.string_index]
|
|
1713
1721
|
return next
|
|
1714
1722
|
|
|
1715
1723
|
def _read(self) -> str | None:
|
|
1716
|
-
if self.
|
|
1724
|
+
if self.string_index >= len(self.string):
|
|
1717
1725
|
return None
|
|
1718
|
-
next: str = self.string[self.
|
|
1719
|
-
self.
|
|
1726
|
+
next: str = self.string[self.string_index]
|
|
1727
|
+
self.string_index += 1
|
|
1720
1728
|
self.char_counter += 1
|
|
1721
1729
|
return next
|
|
1722
1730
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|