forked from weaselab/weaseljson
Compare commits
39
Commits
e8830e27e9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c44b0262bc | ||
|
|
814b24efba | ||
|
|
86b58e83cb | ||
|
|
cdff634057 | ||
|
|
16f5d3cd9d | ||
|
|
6beb538b61 | ||
|
|
6520039dc2 | ||
|
|
93203b14f5 | ||
|
|
09c0fb72ca | ||
|
|
70bb33eeaf | ||
|
|
42d37d1fd7 | ||
|
|
5e462f1477 | ||
|
|
f5ceb392c2 | ||
|
|
be92755cbf | ||
|
|
d281c35811 | ||
|
|
f6617a1558 | ||
|
|
ababd3a8fd | ||
|
|
681892107f | ||
|
|
e22bc039ae | ||
|
|
ceb16e5405 | ||
|
|
241c29073b | ||
|
|
abeaae7ed7 | ||
|
|
4bd1088018 | ||
|
|
82bdc8a080 | ||
|
|
6508616edc | ||
|
|
e5c970a605 | ||
|
|
96f61665bf | ||
|
|
34fc22a7c2 | ||
|
|
08b864d31b | ||
|
|
4ce2002663 | ||
|
|
df693ef4c9 | ||
|
|
e5cbaac401 | ||
|
|
e155e0bbf4 | ||
|
|
717f30099f | ||
|
|
1404ebdfbd | ||
|
|
38079cc278 | ||
|
|
ceb4bc1041 | ||
|
|
16f13c241c | ||
|
|
ab95fefb09 |
@@ -45,7 +45,7 @@ into the result, so it is non-movable.
|
|||||||
| `$ref` to `$defs`/`definitions` | the referenced named struct |
|
| `$ref` to `$defs`/`definitions` | the referenced named struct |
|
||||||
| recursive `$ref` | `std::unique_ptr<T>` (cycle broken) |
|
| recursive `$ref` | `std::unique_ptr<T>` (cycle broken) |
|
||||||
| `additionalProperties: false` | unknown keys rejected |
|
| `additionalProperties: false` | unknown keys rejected |
|
||||||
| `additionalProperties` absent / `true` | unknown keys' values skipped |
|
| `additionalProperties` absent / `true` | not supported (rejected at generation) |
|
||||||
|
|
||||||
## Schema violations (rejected at parse time)
|
## Schema violations (rejected at parse time)
|
||||||
|
|
||||||
@@ -55,15 +55,16 @@ into the result, so it is non-movable.
|
|||||||
- value not in a string `enum`
|
- value not in a string `enum`
|
||||||
- a number not representable in the target type (e.g. `1.5` for an `integer`)
|
- a number not representable in the target type (e.g. `1.5` for an `integer`)
|
||||||
- duplicate object keys
|
- duplicate object keys
|
||||||
- unknown key under `additionalProperties: false`
|
- unknown key in any object
|
||||||
|
|
||||||
## Not supported (rejected at generation time, no fallback)
|
## Not supported (rejected at generation time, no fallback)
|
||||||
|
|
||||||
`oneOf` / `anyOf` / `allOf` / `not` / `if`-`then`-`else`,
|
`oneOf` / `anyOf` / `allOf` / `not` / `if`-`then`-`else`,
|
||||||
`patternProperties`, `additionalProperties` with a schema (typed map),
|
`patternProperties`, `additionalProperties` absent or set to `true`,
|
||||||
`prefixItems` (tuples), `const`, `dependentSchemas`/`dependentRequired`,
|
`additionalProperties` with a schema (typed map), `prefixItems` (tuples),
|
||||||
union `type` lists other than `["T", "null"]`, non-string enums, and remote
|
`const`,
|
||||||
(`$ref` to other documents).
|
`dependentSchemas`/`dependentRequired`, union `type` lists other than
|
||||||
|
`["T", "null"]`, non-string enums, and remote (`$ref` to other documents).
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
"required": [
|
"required": [
|
||||||
"name"
|
"name"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -68,6 +68,15 @@ int main() {
|
|||||||
expectReject(json, "unknown key in strict root");
|
expectReject(json, "unknown key in strict root");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- invalid stack size is rejected without crashing ----
|
||||||
|
{
|
||||||
|
RootBuilder b(-1);
|
||||||
|
char buf[] = "null";
|
||||||
|
WeaselJsonStatus s = b.feed(buf, sizeof(buf) - 1);
|
||||||
|
CHECK(s == WeaselJson_REJECT);
|
||||||
|
printf("ok invalid stack size rejected, not crashed\n");
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string json = R"({
|
std::string json = R"({
|
||||||
"name": "Ada É",
|
"name": "Ada É",
|
||||||
@@ -184,6 +193,10 @@ int main() {
|
|||||||
expectReject(R"({"name":"x","age":1,"address":{"zip":5}})",
|
expectReject(R"({"name":"x","age":1,"address":{"zip":5}})",
|
||||||
"missing required nested 'city'");
|
"missing required nested 'city'");
|
||||||
expectReject(R"([1,2,3])", "array where object expected (root)");
|
expectReject(R"([1,2,3])", "array where object expected (root)");
|
||||||
|
expectReject("null", "null where object expected (root)");
|
||||||
|
expectReject("true", "boolean where object expected (root)");
|
||||||
|
expectReject("123", "number where object expected (root)");
|
||||||
|
expectReject(R"("hi")", "string where object expected (root)");
|
||||||
expectReject(R"({"name":"x","age":1,)", "truncated / invalid json");
|
expectReject(R"({"name":"x","age":1,)", "truncated / invalid json");
|
||||||
|
|
||||||
if (failures == 0) {
|
if (failures == 0) {
|
||||||
|
|||||||
@@ -61,6 +61,18 @@ static void expectReject(nullable_object::RootBuilder &b, std::string in,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void expectReject(nullable_array::RootBuilder &b, std::string in,
|
||||||
|
const char *what) {
|
||||||
|
WeaselJsonStatus s = parseStrided(b, in);
|
||||||
|
if (s == WeaselJson_REJECT) {
|
||||||
|
printf("ok reject: %s\n", what);
|
||||||
|
} else {
|
||||||
|
printf("FAIL expected reject (%s) got status %d for: %s\n", what, s,
|
||||||
|
in.c_str());
|
||||||
|
++failures;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// ---- nullable root object: valid document ----
|
// ---- nullable root object: valid document ----
|
||||||
{
|
{
|
||||||
@@ -149,6 +161,34 @@ int main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- nullable root object: scalar values rejected ----
|
||||||
|
{
|
||||||
|
nullable_object::RootBuilder b;
|
||||||
|
expectReject(b, "true", "boolean where nullable object expected (root)");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
nullable_object::RootBuilder b;
|
||||||
|
expectReject(b, "123", "number where nullable object expected (root)");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
nullable_object::RootBuilder b;
|
||||||
|
expectReject(b, R"("hi")", "string where nullable object expected (root)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- nullable root array: scalar values rejected ----
|
||||||
|
{
|
||||||
|
nullable_array::RootBuilder b;
|
||||||
|
expectReject(b, "true", "boolean where nullable array expected (root)");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
nullable_array::RootBuilder b;
|
||||||
|
expectReject(b, "123", "number where nullable array expected (root)");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
nullable_array::RootBuilder b;
|
||||||
|
expectReject(b, R"("hi")", "string where nullable array expected (root)");
|
||||||
|
}
|
||||||
|
|
||||||
if (failures == 0) {
|
if (failures == 0) {
|
||||||
printf("\nALL TESTS PASSED\n");
|
printf("\nALL TESTS PASSED\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import shutil
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import textwrap
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
SCRIPT = os.path.join(os.path.dirname(__file__), "weaseljson_schemagen.py")
|
SCRIPT = os.path.join(os.path.dirname(__file__), "weaseljson_schemagen.py")
|
||||||
@@ -31,6 +32,7 @@ class SchemagenEnumTest(unittest.TestCase):
|
|||||||
def test_colliding_enum_values_deduplicate(self):
|
def test_colliding_enum_values_deduplicate(self):
|
||||||
schema = {
|
schema = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
"properties": {"role": {"enum": ["foo-bar", "foo_bar"]}},
|
"properties": {"role": {"enum": ["foo-bar", "foo_bar"]}},
|
||||||
}
|
}
|
||||||
rc, stdout, stderr = self.run_schemagen(schema)
|
rc, stdout, stderr = self.run_schemagen(schema)
|
||||||
@@ -44,6 +46,7 @@ class SchemagenEnumTest(unittest.TestCase):
|
|||||||
def test_distinct_enum_values_generate(self):
|
def test_distinct_enum_values_generate(self):
|
||||||
schema = {
|
schema = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
"properties": {"role": {"enum": ["admin", "user", "guest"]}},
|
"properties": {"role": {"enum": ["admin", "user", "guest"]}},
|
||||||
}
|
}
|
||||||
rc, stdout, stderr = self.run_schemagen(schema)
|
rc, stdout, stderr = self.run_schemagen(schema)
|
||||||
@@ -79,7 +82,7 @@ class SchemagenKeywordTest(unittest.TestCase):
|
|||||||
"module",
|
"module",
|
||||||
"import",
|
"import",
|
||||||
]
|
]
|
||||||
schema = {"type": "object", "properties": {}}
|
schema = {"type": "object", "additionalProperties": False, "properties": {}}
|
||||||
for kw in keywords:
|
for kw in keywords:
|
||||||
schema["properties"][kw] = {"type": "string"}
|
schema["properties"][kw] = {"type": "string"}
|
||||||
rc, stdout, stderr = self.run_schemagen(schema)
|
rc, stdout, stderr = self.run_schemagen(schema)
|
||||||
@@ -163,11 +166,18 @@ class SchemagenCollisionTest(unittest.TestCase):
|
|||||||
def test_kind_enum_does_not_duplicate_arr0(self):
|
def test_kind_enum_does_not_duplicate_arr0(self):
|
||||||
schema = {
|
schema = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
"properties": {
|
"properties": {
|
||||||
"arr": {"type": "array", "items": {"type": "string"}},
|
"arr": {"type": "array", "items": {"type": "string"}},
|
||||||
"obj": {"$ref": "#/$defs/Arr0"},
|
"obj": {"$ref": "#/$defs/Arr0"},
|
||||||
},
|
},
|
||||||
"$defs": {"Arr0": {"type": "object", "properties": {}}},
|
"$defs": {
|
||||||
|
"Arr0": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {},
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
out = self.generate_and_compile(schema)
|
out = self.generate_and_compile(schema)
|
||||||
self.assertIn("struct Arr0", out)
|
self.assertIn("struct Arr0", out)
|
||||||
@@ -178,21 +188,677 @@ class SchemagenCollisionTest(unittest.TestCase):
|
|||||||
self.assertIn("Arr1", enumerators)
|
self.assertIn("Arr1", enumerators)
|
||||||
self.assertEqual(len(enumerators), len(set(enumerators)))
|
self.assertEqual(len(enumerators), len(set(enumerators)))
|
||||||
|
|
||||||
def test_skip_is_reserved(self):
|
def test_skip_user_type_is_allowed(self):
|
||||||
schema = {
|
schema = {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {"$ref": "#/$defs/Skip"},
|
"items": {"$ref": "#/$defs/Skip"},
|
||||||
"$defs": {"Skip": {"type": "object", "properties": {}}},
|
"$defs": {
|
||||||
|
"Skip": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {},
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
out = self.generate_and_compile(schema)
|
out = self.generate_and_compile(schema)
|
||||||
self.assertIn("struct Skip1", out)
|
self.assertIn("struct Skip", out)
|
||||||
|
self.assertNotIn("struct Skip1", out)
|
||||||
m = re.search(r"enum class Kind : uint8_t \{([^}]+)\}", out)
|
m = re.search(r"enum class Kind : uint8_t \{([^}]+)\}", out)
|
||||||
self.assertIsNotNone(m)
|
self.assertIsNotNone(m)
|
||||||
enumerators = [e.strip() for e in m.group(1).split(",")]
|
enumerators = [e.strip() for e in m.group(1).split(",")]
|
||||||
self.assertIn("Skip", enumerators)
|
self.assertIn("Skip", enumerators)
|
||||||
self.assertIn("Skip1", enumerators)
|
self.assertIn("Arr0", enumerators)
|
||||||
self.assertEqual(len(enumerators), len(set(enumerators)))
|
self.assertEqual(len(enumerators), len(set(enumerators)))
|
||||||
|
|
||||||
|
def test_non_object_defs_reused_across_refs(self):
|
||||||
|
"""Regression test for issue #17: enum and array $defs must be reused."""
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {
|
||||||
|
"role1": {"$ref": "#/$defs/Role"},
|
||||||
|
"role2": {"$ref": "#/$defs/Role"},
|
||||||
|
"roles1": {"$ref": "#/$defs/Roles"},
|
||||||
|
"roles2": {"$ref": "#/$defs/Roles"},
|
||||||
|
},
|
||||||
|
"$defs": {
|
||||||
|
"Role": {"enum": ["admin", "user"]},
|
||||||
|
"Roles": {"type": "array", "items": {"$ref": "#/$defs/Role"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
out = self.generate_and_compile(schema)
|
||||||
|
# Exactly one Role enum is generated.
|
||||||
|
self.assertIn("enum class Role : int { admin, user };", out)
|
||||||
|
self.assertNotIn("enum class Role1 : int", out)
|
||||||
|
self.assertNotIn("enum class Role2 : int", out)
|
||||||
|
# The array of enum is represented by a single kind.
|
||||||
|
m = re.search(r"enum class Kind : uint8_t \{([^}]+)\}", out)
|
||||||
|
self.assertIsNotNone(m)
|
||||||
|
enumerators = [e.strip() for e in m.group(1).split(",")]
|
||||||
|
self.assertEqual(enumerators.count("Arr0"), 1)
|
||||||
|
# All four fields use the same C++ types.
|
||||||
|
self.assertIn("std::optional<Role> role1;", out)
|
||||||
|
self.assertIn("std::optional<Role> role2;", out)
|
||||||
|
self.assertIn("std::optional<std::vector<Role>> roles1;", out)
|
||||||
|
self.assertIn("std::optional<std::vector<Role>> roles2;", out)
|
||||||
|
|
||||||
|
|
||||||
|
class SchemagenAdditionalPropertiesTest(unittest.TestCase):
|
||||||
|
def run_schemagen(self, schema, args=None):
|
||||||
|
"""Run schemagen on a schema dict. Returns (returncode, stdout, stderr)."""
|
||||||
|
with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as fp:
|
||||||
|
json.dump(schema, fp)
|
||||||
|
schema_path = fp.name
|
||||||
|
try:
|
||||||
|
cmd = [sys.executable, SCRIPT, schema_path]
|
||||||
|
if args:
|
||||||
|
cmd.extend(args)
|
||||||
|
result = subprocess.run(cmd, capture_output=True, text=True, check=False)
|
||||||
|
return result.returncode, result.stdout, result.stderr
|
||||||
|
finally:
|
||||||
|
os.unlink(schema_path)
|
||||||
|
|
||||||
|
def test_additional_properties_true_rejected(self):
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": True,
|
||||||
|
"properties": {"name": {"type": "string"}},
|
||||||
|
}
|
||||||
|
rc, stdout, stderr = self.run_schemagen(schema)
|
||||||
|
self.assertNotEqual(rc, 0)
|
||||||
|
self.assertIn("additionalProperties: true is not supported", stderr)
|
||||||
|
|
||||||
|
def test_additional_properties_absent_rejected(self):
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {"name": {"type": "string"}},
|
||||||
|
}
|
||||||
|
rc, stdout, stderr = self.run_schemagen(schema)
|
||||||
|
self.assertNotEqual(rc, 0)
|
||||||
|
self.assertIn("additionalProperties is required for object schemas", stderr)
|
||||||
|
|
||||||
|
def test_additional_properties_false_accepted(self):
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {"name": {"type": "string"}},
|
||||||
|
}
|
||||||
|
rc, stdout, stderr = self.run_schemagen(schema)
|
||||||
|
self.assertEqual(rc, 0, msg=stderr)
|
||||||
|
|
||||||
|
|
||||||
|
class SchemagenCyclicArrayTest(unittest.TestCase):
|
||||||
|
"""Regression tests for issue #33: cyclic array $ref targets."""
|
||||||
|
|
||||||
|
def run_schemagen(self, schema, args=None):
|
||||||
|
"""Run schemagen on a schema dict. Returns (returncode, stdout, stderr)."""
|
||||||
|
with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as fp:
|
||||||
|
json.dump(schema, fp)
|
||||||
|
schema_path = fp.name
|
||||||
|
try:
|
||||||
|
cmd = [sys.executable, SCRIPT, schema_path]
|
||||||
|
if args:
|
||||||
|
cmd.extend(args)
|
||||||
|
result = subprocess.run(cmd, capture_output=True, text=True, check=False)
|
||||||
|
return result.returncode, result.stdout, result.stderr
|
||||||
|
finally:
|
||||||
|
os.unlink(schema_path)
|
||||||
|
|
||||||
|
def test_direct_self_referential_array_rejected(self):
|
||||||
|
schema = {
|
||||||
|
"type": "array",
|
||||||
|
"items": {"$ref": "#/$defs/Node"},
|
||||||
|
"$defs": {
|
||||||
|
"Node": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {"$ref": "#/$defs/Node"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rc, stdout, stderr = self.run_schemagen(schema)
|
||||||
|
self.assertNotEqual(rc, 0)
|
||||||
|
self.assertIn("recursive array type is not supported", stderr)
|
||||||
|
self.assertIn("Node", stderr)
|
||||||
|
|
||||||
|
def test_object_field_to_self_referential_array_rejected(self):
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {"items": {"$ref": "#/$defs/Items"}},
|
||||||
|
"$defs": {
|
||||||
|
"Items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {"$ref": "#/$defs/Items"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rc, stdout, stderr = self.run_schemagen(schema)
|
||||||
|
self.assertNotEqual(rc, 0)
|
||||||
|
self.assertIn("recursive array type is not supported", stderr)
|
||||||
|
self.assertIn("Items", stderr)
|
||||||
|
|
||||||
|
def test_chain_of_array_refs_rejected(self):
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {"x": {"$ref": "#/$defs/A"}},
|
||||||
|
"$defs": {
|
||||||
|
"A": {"type": "array", "items": {"$ref": "#/$defs/B"}},
|
||||||
|
"B": {"type": "array", "items": {"$ref": "#/$defs/A"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rc, stdout, stderr = self.run_schemagen(schema)
|
||||||
|
self.assertNotEqual(rc, 0)
|
||||||
|
self.assertIn("recursive array type is not supported", stderr)
|
||||||
|
|
||||||
|
def test_non_recursive_array_refs_still_allowed(self):
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {"roles": {"$ref": "#/$defs/Roles"}},
|
||||||
|
"$defs": {
|
||||||
|
"Role": {"enum": ["admin", "user"]},
|
||||||
|
"Roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {"$ref": "#/$defs/Role"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rc, stdout, stderr = self.run_schemagen(schema)
|
||||||
|
self.assertEqual(rc, 0, msg=stderr)
|
||||||
|
self.assertIn("std::optional<std::vector<Role>> roles;", stdout)
|
||||||
|
|
||||||
|
|
||||||
|
class SchemagenCyclicNullableObjectTest(unittest.TestCase):
|
||||||
|
"""Regression tests for issue #14: nullable cyclic $ref targets."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.repo_root = os.path.dirname(
|
||||||
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
)
|
||||||
|
self.include_dir = os.path.join(self.repo_root, "include")
|
||||||
|
self.lib_src = os.path.join(self.repo_root, "src", "lib.cpp")
|
||||||
|
self.compiler = shutil.which("c++")
|
||||||
|
|
||||||
|
def _compile_harness(self, tmpdir, schema, harness):
|
||||||
|
schema_path = os.path.join(tmpdir, "schema.json")
|
||||||
|
with open(schema_path, "w") as fp:
|
||||||
|
json.dump(schema, fp)
|
||||||
|
header_path = os.path.join(tmpdir, "gen.h")
|
||||||
|
result = subprocess.run(
|
||||||
|
[
|
||||||
|
sys.executable,
|
||||||
|
SCRIPT,
|
||||||
|
schema_path,
|
||||||
|
"-o",
|
||||||
|
header_path,
|
||||||
|
"--namespace",
|
||||||
|
"test_schema",
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(result.returncode, 0, msg=result.stderr)
|
||||||
|
|
||||||
|
lib_obj = os.path.join(tmpdir, "lib.o")
|
||||||
|
comp_lib = subprocess.run(
|
||||||
|
[
|
||||||
|
self.compiler,
|
||||||
|
"-std=c++20",
|
||||||
|
"-I",
|
||||||
|
self.include_dir,
|
||||||
|
"-I",
|
||||||
|
os.path.join(self.repo_root, "third_party", "include"),
|
||||||
|
"-I",
|
||||||
|
os.path.join(self.repo_root, "third_party", "valgrind"),
|
||||||
|
"-c",
|
||||||
|
self.lib_src,
|
||||||
|
"-o",
|
||||||
|
lib_obj,
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(comp_lib.returncode, 0, msg=comp_lib.stderr)
|
||||||
|
|
||||||
|
cpp_path = os.path.join(tmpdir, "test.cpp")
|
||||||
|
with open(cpp_path, "w") as fp:
|
||||||
|
fp.write(harness)
|
||||||
|
|
||||||
|
exe_path = os.path.join(tmpdir, "test")
|
||||||
|
comp = subprocess.run(
|
||||||
|
[
|
||||||
|
self.compiler,
|
||||||
|
"-std=c++20",
|
||||||
|
"-I",
|
||||||
|
self.include_dir,
|
||||||
|
"-I",
|
||||||
|
tmpdir,
|
||||||
|
lib_obj,
|
||||||
|
cpp_path,
|
||||||
|
"-o",
|
||||||
|
exe_path,
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(comp.returncode, 0, msg=comp.stderr)
|
||||||
|
run = subprocess.run([exe_path], capture_output=True, text=True, check=False)
|
||||||
|
self.assertEqual(run.returncode, 0, msg=run.stdout + run.stderr)
|
||||||
|
|
||||||
|
def test_self_referential_nullable_object_accepts_nested_null(self):
|
||||||
|
"""A nullable object $def must stay nullable on recursive $refs."""
|
||||||
|
if not self.compiler:
|
||||||
|
self.skipTest("C++ compiler not available")
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {"self": {"$ref": "#/$defs/Self"}},
|
||||||
|
"$defs": {
|
||||||
|
"Self": {
|
||||||
|
"type": ["object", "null"],
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {"self": {"$ref": "#/$defs/Self"}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
harness = textwrap.dedent(
|
||||||
|
"""
|
||||||
|
#include "gen.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
struct Case { const char *s; WeaselJsonStatus expected; };
|
||||||
|
int main() {
|
||||||
|
Case cases[] = {
|
||||||
|
{ R"({"self": null})", WeaselJson_OK },
|
||||||
|
{ R"({"self": {"self": null}})", WeaselJson_OK },
|
||||||
|
{ R"({"self": {"self": {}}})", WeaselJson_OK },
|
||||||
|
};
|
||||||
|
for (const auto &c : cases) {
|
||||||
|
test_schema::RootBuilder b;
|
||||||
|
char buf[256];
|
||||||
|
std::strncpy(buf, c.s, sizeof(buf) - 1);
|
||||||
|
buf[sizeof(buf) - 1] = '\\0';
|
||||||
|
WeaselJsonStatus st = b.feed(buf, std::strlen(buf));
|
||||||
|
st = b.finish();
|
||||||
|
if (st != c.expected) {
|
||||||
|
std::printf("case %s expected %d got %d\\n", c.s, c.expected, st);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
self._compile_harness(tmpdir, schema, harness)
|
||||||
|
|
||||||
|
|
||||||
|
class SchemagenIntegerBoundaryTest(unittest.TestCase):
|
||||||
|
"""Regression tests for issue #19: integer slot parsing near int64 boundaries."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.repo_root = os.path.dirname(
|
||||||
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
)
|
||||||
|
self.include_dir = os.path.join(self.repo_root, "include")
|
||||||
|
self.lib_src = os.path.join(self.repo_root, "src", "lib.cpp")
|
||||||
|
self.compiler = shutil.which("c++")
|
||||||
|
|
||||||
|
def _compile_harness(self, tmpdir, schema, harness):
|
||||||
|
schema_path = os.path.join(tmpdir, "schema.json")
|
||||||
|
with open(schema_path, "w") as fp:
|
||||||
|
json.dump(schema, fp)
|
||||||
|
header_path = os.path.join(tmpdir, "gen.h")
|
||||||
|
result = subprocess.run(
|
||||||
|
[
|
||||||
|
sys.executable,
|
||||||
|
SCRIPT,
|
||||||
|
schema_path,
|
||||||
|
"-o",
|
||||||
|
header_path,
|
||||||
|
"--namespace",
|
||||||
|
"test_schema",
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(result.returncode, 0, msg=result.stderr)
|
||||||
|
|
||||||
|
lib_obj = os.path.join(tmpdir, "lib.o")
|
||||||
|
comp_lib = subprocess.run(
|
||||||
|
[
|
||||||
|
self.compiler,
|
||||||
|
"-std=c++20",
|
||||||
|
"-I",
|
||||||
|
self.include_dir,
|
||||||
|
"-I",
|
||||||
|
os.path.join(self.repo_root, "third_party", "include"),
|
||||||
|
"-I",
|
||||||
|
os.path.join(self.repo_root, "third_party", "valgrind"),
|
||||||
|
"-c",
|
||||||
|
self.lib_src,
|
||||||
|
"-o",
|
||||||
|
lib_obj,
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(comp_lib.returncode, 0, msg=comp_lib.stderr)
|
||||||
|
|
||||||
|
cpp_path = os.path.join(tmpdir, "test.cpp")
|
||||||
|
with open(cpp_path, "w") as fp:
|
||||||
|
fp.write(harness)
|
||||||
|
|
||||||
|
exe_path = os.path.join(tmpdir, "test")
|
||||||
|
comp = subprocess.run(
|
||||||
|
[
|
||||||
|
self.compiler,
|
||||||
|
"-std=c++20",
|
||||||
|
"-I",
|
||||||
|
self.include_dir,
|
||||||
|
"-I",
|
||||||
|
tmpdir,
|
||||||
|
lib_obj,
|
||||||
|
cpp_path,
|
||||||
|
"-o",
|
||||||
|
exe_path,
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(comp.returncode, 0, msg=comp.stderr)
|
||||||
|
run = subprocess.run([exe_path], capture_output=True, text=True, check=False)
|
||||||
|
self.assertEqual(run.returncode, 0, msg=run.stdout + run.stderr)
|
||||||
|
|
||||||
|
def _build_cases_array(self, name, entries):
|
||||||
|
lines = [
|
||||||
|
f" struct {name}Case {{ const char *s; WeaselJsonStatus expected; long long v; }};"
|
||||||
|
]
|
||||||
|
lines.append(f" {name}Case {name}_cases[] = {{")
|
||||||
|
for s, exp, v in entries:
|
||||||
|
val = f"{v}LL" if isinstance(v, int) else v
|
||||||
|
lines.append(f' {{ R"({s})", {exp}, {val} }},')
|
||||||
|
lines.append(" };")
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
def test_integer_boundary_root(self):
|
||||||
|
if not self.compiler:
|
||||||
|
self.skipTest("C++ compiler not available")
|
||||||
|
cases = [
|
||||||
|
("9223372036854775807.0", "WeaselJson_OK", 9223372036854775807),
|
||||||
|
("9223372036854775807", "WeaselJson_OK", 9223372036854775807),
|
||||||
|
("9223372036854775806.0", "WeaselJson_OK", 9223372036854775806),
|
||||||
|
("9223372036854775808", "WeaselJson_REJECT", 0),
|
||||||
|
("-9223372036854775808", "WeaselJson_OK", "-9223372036854775807LL - 1"),
|
||||||
|
("-9223372036854775808.0", "WeaselJson_OK", "-9223372036854775807LL - 1"),
|
||||||
|
("-9223372036854775809", "WeaselJson_REJECT", 0),
|
||||||
|
("1e3", "WeaselJson_OK", 1000),
|
||||||
|
("2.0", "WeaselJson_OK", 2),
|
||||||
|
("0.001", "WeaselJson_REJECT", 0),
|
||||||
|
("1e-3", "WeaselJson_REJECT", 0),
|
||||||
|
("1000e-3", "WeaselJson_OK", 1),
|
||||||
|
("100.0e-2", "WeaselJson_OK", 1),
|
||||||
|
("0.0001e4", "WeaselJson_OK", 1),
|
||||||
|
("0.001e3", "WeaselJson_OK", 1),
|
||||||
|
("123.0", "WeaselJson_OK", 123),
|
||||||
|
("9e18", "WeaselJson_OK", 9000000000000000000),
|
||||||
|
("10e18", "WeaselJson_REJECT", 0),
|
||||||
|
# Issue #56: zero written with a negative exponent must be accepted.
|
||||||
|
("0e-1", "WeaselJson_OK", 0),
|
||||||
|
("0e-2", "WeaselJson_OK", 0),
|
||||||
|
("0.0e-2", "WeaselJson_OK", 0),
|
||||||
|
("-0e-2", "WeaselJson_OK", 0),
|
||||||
|
("0e-20", "WeaselJson_OK", 0),
|
||||||
|
("0.000e-5", "WeaselJson_OK", 0),
|
||||||
|
]
|
||||||
|
cases_src = self._build_cases_array("root", cases)
|
||||||
|
harness = textwrap.dedent(
|
||||||
|
f"""
|
||||||
|
#include "gen.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
{cases_src}
|
||||||
|
int main() {{
|
||||||
|
for (const auto \u0026c : root_cases) {{
|
||||||
|
test_schema::RootBuilder b;
|
||||||
|
char buf[512];
|
||||||
|
std::strncpy(buf, c.s, sizeof(buf) - 1);
|
||||||
|
buf[sizeof(buf) - 1] = '\\0';
|
||||||
|
WeaselJsonStatus st = b.feed(buf, std::strlen(buf));
|
||||||
|
st = b.finish();
|
||||||
|
if (st != c.expected) {{
|
||||||
|
std::printf("root case %s expected %d got %d\\n", c.s, c.expected, st);
|
||||||
|
return 1;
|
||||||
|
}}
|
||||||
|
if (st == WeaselJson_OK \u0026\u0026 b.take() != c.v) {{
|
||||||
|
std::printf("root case %s value mismatch\\n", c.s);
|
||||||
|
return 2;
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
return 0;
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
self._compile_harness(tmpdir, {"type": "integer"}, harness)
|
||||||
|
|
||||||
|
def test_integer_boundary_object_field(self):
|
||||||
|
if not self.compiler:
|
||||||
|
self.skipTest("C++ compiler not available")
|
||||||
|
cases = [
|
||||||
|
('{"age":9223372036854775807.0}', "WeaselJson_OK", 9223372036854775807),
|
||||||
|
('{"age":-9223372036854775809}', "WeaselJson_REJECT", 0),
|
||||||
|
('{"age":1e3}', "WeaselJson_OK", 1000),
|
||||||
|
('{"age":2.0}', "WeaselJson_OK", 2),
|
||||||
|
('{"age":0.0001e4}', "WeaselJson_OK", 1),
|
||||||
|
('{"age":0.001}', "WeaselJson_REJECT", 0),
|
||||||
|
# Issue #56: zero written with a negative exponent must be accepted.
|
||||||
|
('{"age":0e-2}', "WeaselJson_OK", 0),
|
||||||
|
('{"age":-0e-20}', "WeaselJson_OK", 0),
|
||||||
|
(
|
||||||
|
'{"age":-9223372036854775808.0}',
|
||||||
|
"WeaselJson_OK",
|
||||||
|
"-9223372036854775807LL - 1",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
cases_src = self._build_cases_array("object", cases)
|
||||||
|
harness = textwrap.dedent(
|
||||||
|
f"""
|
||||||
|
#include "gen.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
{cases_src}
|
||||||
|
int main() {{
|
||||||
|
for (const auto \u0026c : object_cases) {{
|
||||||
|
test_schema::RootBuilder b;
|
||||||
|
char buf[512];
|
||||||
|
std::strncpy(buf, c.s, sizeof(buf) - 1);
|
||||||
|
buf[sizeof(buf) - 1] = '\\0';
|
||||||
|
WeaselJsonStatus st = b.feed(buf, std::strlen(buf));
|
||||||
|
st = b.finish();
|
||||||
|
if (st != c.expected) {{
|
||||||
|
std::printf("object case %s expected %d got %d\\n", c.s, c.expected, st);
|
||||||
|
return 3;
|
||||||
|
}}
|
||||||
|
if (st == WeaselJson_OK \u0026\u0026 b.take().age != c.v) {{
|
||||||
|
std::printf("object case %s value mismatch\\n", c.s);
|
||||||
|
return 4;
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
return 0;
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {"age": {"type": "integer"}},
|
||||||
|
"required": ["age"],
|
||||||
|
}
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
self._compile_harness(tmpdir, schema, harness)
|
||||||
|
|
||||||
|
def test_integer_no_quadratic_leading_zero_loop(self):
|
||||||
|
"""Regression test for issue #34: leading-zero stripping must not be quadratic."""
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
schema_path = os.path.join(tmpdir, "schema.json")
|
||||||
|
with open(schema_path, "w") as fp:
|
||||||
|
json.dump({"type": "integer"}, fp)
|
||||||
|
result = subprocess.run(
|
||||||
|
[sys.executable, SCRIPT, schema_path],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(result.returncode, 0, msg=result.stderr)
|
||||||
|
self.assertIn("parseJsonInt64", result.stdout)
|
||||||
|
self.assertNotIn("digits.erase(digits.begin())", result.stdout)
|
||||||
|
|
||||||
|
def test_integer_large_fractional_leading_zeros(self):
|
||||||
|
"""Numbers with many leading fractional zeros must parse correctly."""
|
||||||
|
if not self.compiler:
|
||||||
|
self.skipTest("C++ compiler not available")
|
||||||
|
harness = textwrap.dedent(
|
||||||
|
"""
|
||||||
|
#include "gen.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
int main() {
|
||||||
|
const int n = 100000;
|
||||||
|
std::string s = std::string("0.") + std::string(n - 1, '0') + "1e" + std::to_string(n);
|
||||||
|
test_schema::RootBuilder b;
|
||||||
|
WeaselJsonStatus st = b.feed(s.data(), static_cast<int>(s.size()));
|
||||||
|
st = b.finish();
|
||||||
|
if (st != WeaselJson_OK) {
|
||||||
|
std::printf("expected OK, got %d\\n", st);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (b.take() != 1) {
|
||||||
|
std::printf("expected value 1\\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
self._compile_harness(tmpdir, {"type": "integer"}, harness)
|
||||||
|
|
||||||
|
|
||||||
|
class SchemagenStringEscapeTest(unittest.TestCase):
|
||||||
|
"""Regression tests for issue #35: control characters in string literals."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.repo_root = os.path.dirname(
|
||||||
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
)
|
||||||
|
self.include_dir = os.path.join(self.repo_root, "include")
|
||||||
|
self.compiler = shutil.which("c++")
|
||||||
|
|
||||||
|
def generate_and_compile(self, schema):
|
||||||
|
"""Run schemagen on schema and syntax-check the resulting header."""
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
schema_path = os.path.join(tmpdir, "schema.json")
|
||||||
|
with open(schema_path, "w") as fp:
|
||||||
|
json.dump(schema, fp)
|
||||||
|
header_path = os.path.join(tmpdir, "gen.h")
|
||||||
|
cmd = [
|
||||||
|
sys.executable,
|
||||||
|
SCRIPT,
|
||||||
|
schema_path,
|
||||||
|
"-o",
|
||||||
|
header_path,
|
||||||
|
"--namespace",
|
||||||
|
"test_schema",
|
||||||
|
]
|
||||||
|
result = subprocess.run(cmd, capture_output=True, text=True, check=False)
|
||||||
|
self.assertEqual(result.returncode, 0, msg=result.stderr)
|
||||||
|
|
||||||
|
if self.compiler:
|
||||||
|
cpp_path = os.path.join(tmpdir, "test.cpp")
|
||||||
|
with open(cpp_path, "w") as fp:
|
||||||
|
fp.write(
|
||||||
|
'#include "gen.h"\n'
|
||||||
|
"int main() {\n"
|
||||||
|
" test_schema::RootBuilder b;\n"
|
||||||
|
" test_schema::Root r = b.take();\n"
|
||||||
|
" (void)r;\n"
|
||||||
|
"}\n"
|
||||||
|
)
|
||||||
|
comp = subprocess.run(
|
||||||
|
[
|
||||||
|
self.compiler,
|
||||||
|
"-std=c++20",
|
||||||
|
"-fsyntax-only",
|
||||||
|
"-I",
|
||||||
|
self.include_dir,
|
||||||
|
"-I",
|
||||||
|
tmpdir,
|
||||||
|
cpp_path,
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(comp.returncode, 0, msg=comp.stderr)
|
||||||
|
|
||||||
|
with open(header_path) as fp:
|
||||||
|
return fp.read()
|
||||||
|
|
||||||
|
def test_newline_in_property_key(self):
|
||||||
|
"""A JSON key containing a newline must become a valid C++ literal."""
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {"a\nb": {"type": "string"}},
|
||||||
|
}
|
||||||
|
out = self.generate_and_compile(schema)
|
||||||
|
self.assertIn('// "a\\nb"', out)
|
||||||
|
self.assertIn('if (key == "a\\nb") return 0;', out)
|
||||||
|
|
||||||
|
def test_newline_in_enum_value(self):
|
||||||
|
"""An enum value containing a newline must become a valid C++ literal."""
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {"x": {"enum": ["a\nb"]}},
|
||||||
|
}
|
||||||
|
out = self.generate_and_compile(schema)
|
||||||
|
self.assertIn('static constexpr const char *X_names[] = { "a\\nb" };', out)
|
||||||
|
|
||||||
|
def test_mixed_control_chars_in_enum_value(self):
|
||||||
|
"""Mixed control characters in an enum value must be escaped."""
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {
|
||||||
|
"x": {"enum": ["x\ny\rz\tw\vq\x00\x01"]},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
out = self.generate_and_compile(schema)
|
||||||
|
self.assertIn(
|
||||||
|
'static constexpr const char *X_names[] = { "x\\ny\\rz\\tw\\vq\\u0000\\u0001" };',
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_backslash_and_quote_still_escaped(self):
|
||||||
|
"""Existing escaping for backslash and double quote must remain correct."""
|
||||||
|
schema = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {'a"b\\c': {"type": "string"}},
|
||||||
|
}
|
||||||
|
out = self.generate_and_compile(schema)
|
||||||
|
self.assertIn('// "a\\"b\\\\c"', out)
|
||||||
|
self.assertIn('if (key == "a\\"b\\\\c") return 0;', out)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -18,6 +18,43 @@ import keyword
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def _escape_cpp_string(s):
|
||||||
|
"""Return *s* escaped for use inside a C++ double-quoted string literal.
|
||||||
|
|
||||||
|
JSON strings may contain control characters; emitting them verbatim into
|
||||||
|
generated C++ source breaks tokenization. This helper escapes backslashes
|
||||||
|
and double quotes, maps common control characters to their short escape
|
||||||
|
sequences, and uses universal character names (\\u00XX) for any other
|
||||||
|
character below 0x20.
|
||||||
|
"""
|
||||||
|
out = []
|
||||||
|
for ch in s:
|
||||||
|
cp = ord(ch)
|
||||||
|
if cp == 0x09:
|
||||||
|
out.append("\\t")
|
||||||
|
elif cp == 0x0A:
|
||||||
|
out.append("\\n")
|
||||||
|
elif cp == 0x0B:
|
||||||
|
out.append("\\v")
|
||||||
|
elif cp == 0x0C:
|
||||||
|
out.append("\\f")
|
||||||
|
elif cp == 0x0D:
|
||||||
|
out.append("\\r")
|
||||||
|
elif cp == 0x08:
|
||||||
|
out.append("\\b")
|
||||||
|
elif cp == 0x07:
|
||||||
|
out.append("\\a")
|
||||||
|
elif cp < 0x20:
|
||||||
|
out.append(f"\\u{cp:04X}")
|
||||||
|
elif ch == "\\":
|
||||||
|
out.append("\\\\")
|
||||||
|
elif ch == '"':
|
||||||
|
out.append('\\"')
|
||||||
|
else:
|
||||||
|
out.append(ch)
|
||||||
|
return "".join(out)
|
||||||
|
|
||||||
|
|
||||||
class GenError(Exception):
|
class GenError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -60,7 +97,6 @@ class ObjectType:
|
|||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.fields = [] # list[Field]
|
self.fields = [] # list[Field]
|
||||||
self.strict = False # additionalProperties: false
|
|
||||||
|
|
||||||
|
|
||||||
class EnumType:
|
class EnumType:
|
||||||
@@ -234,7 +270,25 @@ class Builder:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_reserved(name):
|
def _is_reserved(name):
|
||||||
"""Names generated internally that must not collide with user types."""
|
"""Names generated internally that must not collide with user types."""
|
||||||
return name in ("Root", "Skip", "RootScalar")
|
return name in ("Root", "RootScalar")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _array_reaches(target, ty):
|
||||||
|
"""Return True if `target` can be reached from `ty` by following
|
||||||
|
TArr element types. This detects self-referential array cycles that
|
||||||
|
cannot be expressed as C++ structs."""
|
||||||
|
seen = set()
|
||||||
|
stack = [ty]
|
||||||
|
while stack:
|
||||||
|
cur = stack.pop()
|
||||||
|
if cur is target:
|
||||||
|
return True
|
||||||
|
if id(cur) in seen:
|
||||||
|
continue
|
||||||
|
seen.add(id(cur))
|
||||||
|
if isinstance(cur, TArr):
|
||||||
|
stack.append(cur.elem)
|
||||||
|
return False
|
||||||
|
|
||||||
def ref_name(self, ref):
|
def ref_name(self, ref):
|
||||||
if not ref.startswith("#/"):
|
if not ref.startswith("#/"):
|
||||||
@@ -251,7 +305,6 @@ class Builder:
|
|||||||
if defname not in self.defs:
|
if defname not in self.defs:
|
||||||
raise GenError(f"$ref to unknown def: {defname}")
|
raise GenError(f"$ref to unknown def: {defname}")
|
||||||
node = self.defs[defname]
|
node = self.defs[defname]
|
||||||
# For objects we must register the name before recursing into fields.
|
|
||||||
return self.build_type(node, defname, defname=defname)
|
return self.build_type(node, defname, defname=defname)
|
||||||
|
|
||||||
def build_type(self, node, hint, defname=None):
|
def build_type(self, node, hint, defname=None):
|
||||||
@@ -280,6 +333,10 @@ class Builder:
|
|||||||
if "$ref" in node:
|
if "$ref" in node:
|
||||||
return self.build_def(self.ref_name(node["$ref"]))
|
return self.build_def(self.ref_name(node["$ref"]))
|
||||||
|
|
||||||
|
# Non-object $defs entries must reuse the same type for every $ref.
|
||||||
|
if defname is not None and defname in self._building:
|
||||||
|
return self._building[defname]
|
||||||
|
|
||||||
# nullability via type lists: ["string", "null"]
|
# nullability via type lists: ["string", "null"]
|
||||||
nullable = False
|
nullable = False
|
||||||
typ = node.get("type")
|
typ = node.get("type")
|
||||||
@@ -298,18 +355,35 @@ class Builder:
|
|||||||
raise GenError("only non-empty string enums are supported")
|
raise GenError("only non-empty string enums are supported")
|
||||||
name = defname and self.unique_name(defname) or self.unique_name(hint)
|
name = defname and self.unique_name(defname) or self.unique_name(hint)
|
||||||
self.enums[name] = EnumType(name, list(vals))
|
self.enums[name] = EnumType(name, list(vals))
|
||||||
return (TEnum(name), nullable)
|
result = (TEnum(name), nullable)
|
||||||
|
if defname is not None:
|
||||||
|
self._building[defname] = result
|
||||||
|
return result
|
||||||
|
|
||||||
if typ == "object" or (typ is None and "properties" in node):
|
if typ == "object" or (typ is None and "properties" in node):
|
||||||
return (self._build_object(node, hint, defname), nullable)
|
return (self._build_object(node, hint, defname, nullable), nullable)
|
||||||
|
|
||||||
if typ == "array":
|
if typ == "array":
|
||||||
if "items" not in node or not isinstance(node["items"], dict):
|
if "items" not in node or not isinstance(node["items"], dict):
|
||||||
raise GenError("arrays require a single 'items' schema")
|
raise GenError("arrays require a single 'items' schema")
|
||||||
|
# Register the array before building its items so $ref cycles back
|
||||||
|
# to this definition resolve to the same TArr instance.
|
||||||
|
t = TArr(None, False)
|
||||||
|
result = (t, nullable)
|
||||||
|
if defname is not None:
|
||||||
|
self._building[defname] = result
|
||||||
elem, elem_nullable = self._unpack(
|
elem, elem_nullable = self._unpack(
|
||||||
self.build_type(node["items"], hint + "Item")
|
self.build_type(node["items"], hint + "Item")
|
||||||
)
|
)
|
||||||
return (TArr(elem, elem_nullable), nullable)
|
t.elem = elem
|
||||||
|
t.elem_nullable = elem_nullable
|
||||||
|
# Self-referential array cycles (directly or through a chain of
|
||||||
|
# array definitions) cannot be represented as a C++ value type.
|
||||||
|
if self._array_reaches(t, elem):
|
||||||
|
raise GenError(
|
||||||
|
"recursive array type is not supported: " f"{defname or hint!r}"
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
scalar = {
|
scalar = {
|
||||||
"string": "str",
|
"string": "str",
|
||||||
@@ -318,7 +392,10 @@ class Builder:
|
|||||||
"boolean": "bool",
|
"boolean": "bool",
|
||||||
}.get(typ)
|
}.get(typ)
|
||||||
if scalar:
|
if scalar:
|
||||||
return (TScalar(scalar), nullable)
|
result = (TScalar(scalar), nullable)
|
||||||
|
if defname is not None:
|
||||||
|
self._building[defname] = result
|
||||||
|
return result
|
||||||
if typ == "null":
|
if typ == "null":
|
||||||
raise GenError("'null'-only types are not supported")
|
raise GenError("'null'-only types are not supported")
|
||||||
|
|
||||||
@@ -332,19 +409,27 @@ class Builder:
|
|||||||
return result
|
return result
|
||||||
return (result, False)
|
return (result, False)
|
||||||
|
|
||||||
def _build_object(self, node, hint, defname):
|
def _build_object(self, node, hint, defname, nullable=False):
|
||||||
name = self.unique_name(defname or hint)
|
name = self.unique_name(defname or hint)
|
||||||
obj = ObjectType(name)
|
obj = ObjectType(name)
|
||||||
self.objects[name] = obj
|
self.objects[name] = obj
|
||||||
# register for $ref cycles before building fields
|
# register for $ref cycles before building fields
|
||||||
|
tobj = TObj(name)
|
||||||
if defname is not None:
|
if defname is not None:
|
||||||
self._building[defname] = TObj(name)
|
self._building[defname] = (tobj, nullable)
|
||||||
ap = node.get("additionalProperties", True)
|
ap = node.get("additionalProperties", None)
|
||||||
|
if ap is None:
|
||||||
|
raise GenError(
|
||||||
|
"additionalProperties is required for object schemas; set it "
|
||||||
|
"explicitly to false to reject unknown keys (absent "
|
||||||
|
"additionalProperties is not supported)"
|
||||||
|
)
|
||||||
|
if ap is True:
|
||||||
|
raise GenError("additionalProperties: true is not supported")
|
||||||
if isinstance(ap, dict):
|
if isinstance(ap, dict):
|
||||||
raise GenError(
|
raise GenError(
|
||||||
"additionalProperties with a schema (typed map) is not " "supported yet"
|
"additionalProperties with a schema (typed map) is not " "supported yet"
|
||||||
)
|
)
|
||||||
obj.strict = ap is False
|
|
||||||
required = set(node.get("required", []))
|
required = set(node.get("required", []))
|
||||||
props = node.get("properties", {})
|
props = node.get("properties", {})
|
||||||
seen_cpp = set()
|
seen_cpp = set()
|
||||||
@@ -358,7 +443,7 @@ class Builder:
|
|||||||
cpp = f"{base}{i}"
|
cpp = f"{base}{i}"
|
||||||
seen_cpp.add(cpp)
|
seen_cpp.add(cpp)
|
||||||
obj.fields.append(Field(key, cpp, ty, key in required, nullable))
|
obj.fields.append(Field(key, cpp, ty, key in required, nullable))
|
||||||
return TObj(name)
|
return tobj
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -600,7 +685,8 @@ namespace {ns} {{"""
|
|||||||
and f.ty.kind in ("int", "dbl", "bool")
|
and f.ty.kind in ("int", "dbl", "bool")
|
||||||
):
|
):
|
||||||
init = " = 0" if f.ty.kind != "bool" else " = false"
|
init = " = 0" if f.ty.kind != "bool" else " = false"
|
||||||
out.append(f' {store} {f.cpp}{init}; // "{f.key}"')
|
esc_key = _escape_cpp_string(f.key)
|
||||||
|
out.append(f' {store} {f.cpp}{init}; // "{esc_key}"')
|
||||||
out.append("};")
|
out.append("};")
|
||||||
out.append("")
|
out.append("")
|
||||||
return "\n".join(out)
|
return "\n".join(out)
|
||||||
@@ -620,7 +706,6 @@ namespace {ns} {{"""
|
|||||||
root_is_container = isinstance(self.root_ty, (TObj, TArr))
|
root_is_container = isinstance(self.root_ty, (TObj, TArr))
|
||||||
if not root_is_container:
|
if not root_is_container:
|
||||||
kinds.append("RootScalar")
|
kinds.append("RootScalar")
|
||||||
kinds.append("Skip")
|
|
||||||
self.kind_order = kinds
|
self.kind_order = kinds
|
||||||
return " enum class Kind : uint8_t { " + ", ".join(kinds) + " };"
|
return " enum class Kind : uint8_t { " + ", ".join(kinds) + " };"
|
||||||
|
|
||||||
@@ -729,7 +814,7 @@ namespace {ns} {{"""
|
|||||||
for name, obj in self.b.objects.items():
|
for name, obj in self.b.objects.items():
|
||||||
lines.append(f" case Kind::{name}:")
|
lines.append(f" case Kind::{name}:")
|
||||||
for i, fld in enumerate(obj.fields):
|
for i, fld in enumerate(obj.fields):
|
||||||
esc = fld.key.replace("\\", "\\\\").replace('"', '\\"')
|
esc = _escape_cpp_string(fld.key)
|
||||||
lines.append(f' if (key == "{esc}") return {i};')
|
lines.append(f' if (key == "{esc}") return {i};')
|
||||||
lines.append(" return -1;")
|
lines.append(" return -1;")
|
||||||
lines.append(" default: return -1;")
|
lines.append(" default: return -1;")
|
||||||
@@ -809,24 +894,10 @@ namespace {ns} {{"""
|
|||||||
lines.append(" }")
|
lines.append(" }")
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
def _is_strict(self):
|
|
||||||
strict = [n for n, o in self.b.objects.items() if o.strict]
|
|
||||||
if not strict:
|
|
||||||
return " bool isStrict(Kind) const { return false; }"
|
|
||||||
cases = " ".join(f"case Kind::{n}:" for n in strict)
|
|
||||||
return (
|
|
||||||
" bool isStrict(Kind k) const {\n"
|
|
||||||
f" switch (k) {{ {cases} return true; default: return false; }}\n"
|
|
||||||
" }"
|
|
||||||
)
|
|
||||||
|
|
||||||
def _enum_name_arrays(self):
|
def _enum_name_arrays(self):
|
||||||
out = []
|
out = []
|
||||||
for e in self.b.enums.values():
|
for e in self.b.enums.values():
|
||||||
lits = ", ".join(
|
lits = ", ".join('"' + _escape_cpp_string(v) + '"' for v in e.values)
|
||||||
'"' + v.replace("\\", "\\\\").replace('"', '\\"') + '"'
|
|
||||||
for v in e.values
|
|
||||||
)
|
|
||||||
out.append(
|
out.append(
|
||||||
f" static constexpr const char *{e.name}_names[] = {{ {lits} }};"
|
f" static constexpr const char *{e.name}_names[] = {{ {lits} }};"
|
||||||
)
|
)
|
||||||
@@ -861,13 +932,7 @@ namespace {ns} {{"""
|
|||||||
else:
|
else:
|
||||||
lines.append(" if (stack_.empty()) { reject(); return; }")
|
lines.append(" if (stack_.empty()) { reject(); return; }")
|
||||||
lines.append(" Frame &f = stack_.back();")
|
lines.append(" Frame &f = stack_.back();")
|
||||||
lines.append(
|
|
||||||
" if (f.kind == Kind::Skip) { stack_.push_back(Frame{Kind::Skip, nullptr}); return; }"
|
|
||||||
)
|
|
||||||
lines.append(" SlotInfo si = slotInfoG(f);")
|
lines.append(" SlotInfo si = slotInfoG(f);")
|
||||||
lines.append(
|
|
||||||
" if (si.cat == Cat::Skip) { stack_.push_back(Frame{Kind::Skip, nullptr}); return; }"
|
|
||||||
)
|
|
||||||
lines.append(f" if (si.cat != Cat::{event_cat}) {{ reject(); return; }}")
|
lines.append(f" if (si.cat != Cat::{event_cat}) {{ reject(); return; }}")
|
||||||
lines.append(" void *p = engage(f, true);")
|
lines.append(" void *p = engage(f, true);")
|
||||||
lines.append(" stack_.push_back(Frame{si.child, p});")
|
lines.append(" stack_.push_back(Frame{si.child, p});")
|
||||||
@@ -892,6 +957,10 @@ public:
|
|||||||
explicit RootBuilder(int stackSize = 1024) {{
|
explicit RootBuilder(int stackSize = 1024) {{
|
||||||
cb_ = makeCallbacks();
|
cb_ = makeCallbacks();
|
||||||
parser_ = WeaselJsonParser_create(stackSize, &cb_, this, 0);
|
parser_ = WeaselJsonParser_create(stackSize, &cb_, this, 0);
|
||||||
|
if (!parser_) {{
|
||||||
|
error_ = true;
|
||||||
|
return;
|
||||||
|
}}
|
||||||
{self._ctor_body()}
|
{self._ctor_body()}
|
||||||
}}
|
}}
|
||||||
~RootBuilder() {{ if (parser_) WeaselJsonParser_destroy(parser_); }}
|
~RootBuilder() {{ if (parser_) WeaselJsonParser_destroy(parser_); }}
|
||||||
@@ -918,7 +987,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
{kind_enum}
|
{kind_enum}
|
||||||
enum class Cat {{ Reject, Str, Int, Dbl, Bool, Enum, Obj, Arr, Skip }};
|
enum class Cat {{ Reject, Str, Int, Dbl, Bool, Enum, Obj, Arr }};
|
||||||
struct SlotInfo {{
|
struct SlotInfo {{
|
||||||
Cat cat;
|
Cat cat;
|
||||||
Kind child{{}};
|
Kind child{{}};
|
||||||
@@ -929,11 +998,10 @@ private:
|
|||||||
struct Frame {{
|
struct Frame {{
|
||||||
Kind kind;
|
Kind kind;
|
||||||
void *dest;
|
void *dest;
|
||||||
int field = -1; // object: selected field (-1 want key, -2 skip)
|
int field = -1; // object: selected field (-1 means waiting for key)
|
||||||
std::vector<uint64_t> seen; // populated field bitset (object frames)
|
std::vector<uint64_t> seen; // populated field bitset (object frames)
|
||||||
}};
|
}};
|
||||||
static constexpr int kWantKey = -1;
|
static constexpr int kWantKey = -1;
|
||||||
static constexpr int kSkip = -2;
|
|
||||||
|
|
||||||
{self._enum_name_arrays()}
|
{self._enum_name_arrays()}
|
||||||
|
|
||||||
@@ -948,10 +1016,95 @@ private:
|
|||||||
|
|
||||||
void reject() {{ error_ = true; }}
|
void reject() {{ error_ = true; }}
|
||||||
|
|
||||||
// Wrap the generated slotInfo() with the generic key/skip states.
|
// Parse a JSON number text as int64_t. Accepts optional decimal point and
|
||||||
|
// exponent only when the mathematical value is an integer that fits in a
|
||||||
|
// signed 64-bit range.
|
||||||
|
static bool parseJsonInt64(const char *b, const char *e, int64_t &out) {{
|
||||||
|
const char *p = b;
|
||||||
|
bool neg = false;
|
||||||
|
if (p < e) {{
|
||||||
|
if (*p == '-') {{ neg = true; ++p; }}
|
||||||
|
else if (*p == '+') return false;
|
||||||
|
}}
|
||||||
|
const char *intStart = p;
|
||||||
|
while (p < e && *p >= '0' && *p <= '9') ++p;
|
||||||
|
const char *intEnd = p;
|
||||||
|
int fracDigits = 0;
|
||||||
|
const char *fracStart = p;
|
||||||
|
if (p < e && *p == '.') {{
|
||||||
|
++p;
|
||||||
|
fracStart = p;
|
||||||
|
while (p < e && *p >= '0' && *p <= '9') {{ ++p; ++fracDigits; }}
|
||||||
|
if (fracStart == p) return false;
|
||||||
|
}}
|
||||||
|
int64_t exp = 0;
|
||||||
|
bool expNeg = false;
|
||||||
|
if (p < e && (*p == 'e' || *p == 'E')) {{
|
||||||
|
++p;
|
||||||
|
if (p < e && (*p == '-' || *p == '+')) {{ expNeg = (*p == '-'); ++p; }}
|
||||||
|
if (p == e || *p < '0' || *p > '9') return false;
|
||||||
|
while (p < e && *p >= '0' && *p <= '9') {{
|
||||||
|
int digit = *p - '0';
|
||||||
|
if (exp <= (INT64_MAX - digit) / 10) exp = exp * 10 + digit;
|
||||||
|
else exp = INT64_MAX;
|
||||||
|
++p;
|
||||||
|
}}
|
||||||
|
if (expNeg) exp = -exp;
|
||||||
|
}}
|
||||||
|
if (p != e) return false;
|
||||||
|
if (intStart == intEnd) return false;
|
||||||
|
|
||||||
|
std::string digits;
|
||||||
|
digits.reserve((intEnd - intStart) + fracDigits);
|
||||||
|
for (const char *q = intStart; q < intEnd; ++q) digits.push_back(*q);
|
||||||
|
for (int i = 0; i < fracDigits; ++i) digits.push_back(fracStart[i]);
|
||||||
|
int64_t trim = 0;
|
||||||
|
while (!digits.empty() && digits.back() == '0') {{
|
||||||
|
digits.pop_back();
|
||||||
|
++trim;
|
||||||
|
}}
|
||||||
|
int64_t finalExp = exp - fracDigits + trim;
|
||||||
|
size_t leadingZeros = 0;
|
||||||
|
while (leadingZeros < digits.size() && digits[leadingZeros] == '0') ++leadingZeros;
|
||||||
|
if (leadingZeros == digits.size()) {{ out = 0; return true; }}
|
||||||
|
if (finalExp < 0) return false;
|
||||||
|
if (leadingZeros > 0) digits.erase(0, leadingZeros);
|
||||||
|
|
||||||
|
constexpr uint64_t kMaxNeg = 9223372036854775808ULL;
|
||||||
|
constexpr uint64_t kMaxPos = 9223372036854775807ULL;
|
||||||
|
const uint64_t limit = neg ? kMaxNeg : kMaxPos;
|
||||||
|
|
||||||
|
if (finalExp > 19) return false;
|
||||||
|
int64_t maxSig = 19 - finalExp;
|
||||||
|
uint64_t mag = 0;
|
||||||
|
int64_t sigDigits = 0;
|
||||||
|
for (char ch : digits) {{
|
||||||
|
uint64_t d = static_cast<uint64_t>(ch - '0');
|
||||||
|
if (sigDigits >= maxSig) return false;
|
||||||
|
if (mag > (limit - d) / 10) return false;
|
||||||
|
mag = mag * 10 + d;
|
||||||
|
++sigDigits;
|
||||||
|
}}
|
||||||
|
for (int64_t i = 0; i < finalExp; ++i) {{
|
||||||
|
if (mag > limit / 10) return false;
|
||||||
|
mag *= 10;
|
||||||
|
}}
|
||||||
|
if (mag > limit) return false;
|
||||||
|
if (neg) {{
|
||||||
|
if (mag == kMaxNeg) {{
|
||||||
|
out = INT64_MIN;
|
||||||
|
}} else {{
|
||||||
|
out = -static_cast<int64_t>(mag);
|
||||||
|
}}
|
||||||
|
}} else {{
|
||||||
|
out = static_cast<int64_t>(mag);
|
||||||
|
}}
|
||||||
|
return true;
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Wrap the generated slotInfo() with the generic key state.
|
||||||
SlotInfo slotInfoG(const Frame &f) {{
|
SlotInfo slotInfoG(const Frame &f) {{
|
||||||
if (isObjectKind(f.kind)) {{
|
if (isObjectKind(f.kind)) {{
|
||||||
if (f.field == kSkip) return SlotInfo{{Cat::Skip}};
|
|
||||||
if (f.field < 0) return SlotInfo{{Cat::Reject}};
|
if (f.field < 0) return SlotInfo{{Cat::Reject}};
|
||||||
}}
|
}}
|
||||||
return slotInfo(f);
|
return slotInfo(f);
|
||||||
@@ -976,11 +1129,6 @@ private:
|
|||||||
void cbEndObject() {{
|
void cbEndObject() {{
|
||||||
if (error_) return;
|
if (error_) return;
|
||||||
Frame &f = stack_.back();
|
Frame &f = stack_.back();
|
||||||
if (f.kind == Kind::Skip) {{
|
|
||||||
stack_.pop_back();
|
|
||||||
if (stack_.empty() || stack_.back().kind != Kind::Skip) valueComplete();
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
if (isObjectKind(f.kind)) {{
|
if (isObjectKind(f.kind)) {{
|
||||||
const auto &req = requiredMask(f.kind);
|
const auto &req = requiredMask(f.kind);
|
||||||
bool missing = false;
|
bool missing = false;
|
||||||
@@ -998,11 +1146,6 @@ private:
|
|||||||
void cbEndArray() {{
|
void cbEndArray() {{
|
||||||
if (error_) return;
|
if (error_) return;
|
||||||
Frame f = stack_.back();
|
Frame f = stack_.back();
|
||||||
if (f.kind == Kind::Skip) {{
|
|
||||||
stack_.pop_back();
|
|
||||||
if (stack_.empty() || stack_.back().kind != Kind::Skip) valueComplete();
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
stack_.pop_back();
|
stack_.pop_back();
|
||||||
valueComplete();
|
valueComplete();
|
||||||
}}
|
}}
|
||||||
@@ -1014,12 +1157,10 @@ private:
|
|||||||
scratch_.append(buf, len);
|
scratch_.append(buf, len);
|
||||||
if (!done) return;
|
if (!done) return;
|
||||||
int idx = matchKey(f.kind, scratch_);
|
int idx = matchKey(f.kind, scratch_);
|
||||||
scratch_.clear();
|
|
||||||
if (idx < 0) {{
|
if (idx < 0) {{
|
||||||
if (isStrict(f.kind)) {{ reject(); return; }}
|
reject(); return; // unknown key
|
||||||
f.field = kSkip;
|
|
||||||
return;
|
|
||||||
}}
|
}}
|
||||||
|
scratch_.clear();
|
||||||
if (f.seen[idx >> 6] & (1ull << (idx & 63))) {{
|
if (f.seen[idx >> 6] & (1ull << (idx & 63))) {{
|
||||||
reject(); return; // duplicate key
|
reject(); return; // duplicate key
|
||||||
}}
|
}}
|
||||||
@@ -1028,10 +1169,9 @@ private:
|
|||||||
|
|
||||||
void cbStringData(const char *buf, int len, int done) {{
|
void cbStringData(const char *buf, int len, int done) {{
|
||||||
if (error_) return;
|
if (error_) return;
|
||||||
|
if (stack_.empty()) {{ reject(); return; }}
|
||||||
Frame &f = stack_.back();
|
Frame &f = stack_.back();
|
||||||
if (f.kind == Kind::Skip) return;
|
|
||||||
SlotInfo si = slotInfoG(f);
|
SlotInfo si = slotInfoG(f);
|
||||||
if (si.cat == Cat::Skip) {{ if (done) valueComplete(); return; }}
|
|
||||||
if (si.cat == Cat::Str) {{
|
if (si.cat == Cat::Str) {{
|
||||||
auto *s = (std::string *)engage(f, !started_);
|
auto *s = (std::string *)engage(f, !started_);
|
||||||
s->append(buf, len);
|
s->append(buf, len);
|
||||||
@@ -1056,10 +1196,9 @@ private:
|
|||||||
|
|
||||||
void cbNumberData(const char *buf, int len, int done) {{
|
void cbNumberData(const char *buf, int len, int done) {{
|
||||||
if (error_) return;
|
if (error_) return;
|
||||||
|
if (stack_.empty()) {{ reject(); return; }}
|
||||||
Frame &f = stack_.back();
|
Frame &f = stack_.back();
|
||||||
if (f.kind == Kind::Skip) return;
|
|
||||||
SlotInfo si = slotInfoG(f);
|
SlotInfo si = slotInfoG(f);
|
||||||
if (si.cat == Cat::Skip) {{ if (done) valueComplete(); return; }}
|
|
||||||
if (si.cat != Cat::Int && si.cat != Cat::Dbl) {{ reject(); return; }}
|
if (si.cat != Cat::Int && si.cat != Cat::Dbl) {{ reject(); return; }}
|
||||||
scratch_.append(buf, len);
|
scratch_.append(buf, len);
|
||||||
started_ = true;
|
started_ = true;
|
||||||
@@ -1074,16 +1213,11 @@ private:
|
|||||||
*(int64_t *)p = v; // plain integer literal: parsed exactly
|
*(int64_t *)p = v; // plain integer literal: parsed exactly
|
||||||
}} else {{
|
}} else {{
|
||||||
// JSON Schema "integer" accepts any number with no fractional part,
|
// JSON Schema "integer" accepts any number with no fractional part,
|
||||||
// including exponent/decimal forms like 1e3 or 2.0. Parse those as a
|
// including exponent/decimal forms like 1e3 or 2.0. Parse those
|
||||||
// double and require an integral value within int64 range.
|
// exactly as int64 when the value is integral and in range.
|
||||||
double d = 0;
|
int64_t v2 = 0;
|
||||||
auto rd = std::from_chars(b, e, d);
|
if (!parseJsonInt64(b, e, v2)) {{ reject(); return; }}
|
||||||
if (rd.ec != std::errc() || rd.ptr != e || d != std::trunc(d) ||
|
*(int64_t *)p = v2;
|
||||||
d < -9223372036854775808.0 || d >= 9223372036854775808.0) {{
|
|
||||||
reject();
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
*(int64_t *)p = (int64_t)d;
|
|
||||||
}}
|
}}
|
||||||
}} else {{
|
}} else {{
|
||||||
double v = 0;
|
double v = 0;
|
||||||
@@ -1096,10 +1230,9 @@ private:
|
|||||||
|
|
||||||
void cbBool(bool value) {{
|
void cbBool(bool value) {{
|
||||||
if (error_) return;
|
if (error_) return;
|
||||||
|
if (stack_.empty()) {{ reject(); return; }}
|
||||||
Frame &f = stack_.back();
|
Frame &f = stack_.back();
|
||||||
if (f.kind == Kind::Skip) return;
|
|
||||||
SlotInfo si = slotInfoG(f);
|
SlotInfo si = slotInfoG(f);
|
||||||
if (si.cat == Cat::Skip) {{ valueComplete(); return; }}
|
|
||||||
if (si.cat != Cat::Bool) {{ reject(); return; }}
|
if (si.cat != Cat::Bool) {{ reject(); return; }}
|
||||||
*(bool *)engage(f, true) = value;
|
*(bool *)engage(f, true) = value;
|
||||||
valueComplete();
|
valueComplete();
|
||||||
@@ -1115,9 +1248,7 @@ private:
|
|||||||
{null_at_root}
|
{null_at_root}
|
||||||
}}
|
}}
|
||||||
Frame &f = stack_.back();
|
Frame &f = stack_.back();
|
||||||
if (f.kind == Kind::Skip) return;
|
|
||||||
SlotInfo si = slotInfoG(f);
|
SlotInfo si = slotInfoG(f);
|
||||||
if (si.cat == Cat::Skip) {{ valueComplete(); return; }}
|
|
||||||
if (!si.nullable) {{ reject(); return; }}
|
if (!si.nullable) {{ reject(); return; }}
|
||||||
if (isArrayKind(f.kind)) appendNull(f); // keep null array elements
|
if (isArrayKind(f.kind)) appendNull(f); // keep null array elements
|
||||||
valueComplete(); // leave optional empty / pointer null
|
valueComplete(); // leave optional empty / pointer null
|
||||||
@@ -1155,8 +1286,6 @@ private:
|
|||||||
{self._reqmask()}
|
{self._reqmask()}
|
||||||
|
|
||||||
{self._is_object_kind()}
|
{self._is_object_kind()}
|
||||||
|
|
||||||
{self._is_strict()}
|
|
||||||
}};
|
}};
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
"d\ud82d\udd9c8\ud8ed
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
[4,[5,[5,[4,[6,[5,[5,55,5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[[[[5,5,[5,[5,[[null,[461,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[
[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-41,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-.41.8,[8,[7,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[5,[5,[[null,5,[1.0e+9, ""[[{},{}:0 -1.0e028 },[[false, [[false, [[[{},8,
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
[[[{ "min":-6.8, "in":-6.8, "in": -6, "Umin": -6.8, "m":-6.4, "max": 1, "mij": -6.8," ": -6.8, "UUaxax": 1, "mij": -6.8," ": -6.8, "UUax":-6.8, "Tin":-6.8, "mUUUax":-6.8, "maxn":-6.8, "in": -6, "Umin": -6.8, "m":-6.4, "max": 1, "mij": -6.8," ": -6.8, "UUax":-6.8, "Tin":-6.8, "mUUUax":-6.8, "max": -6.8, "min":-6.8, "mUax":-6.8, "man": -6, "mUmin": -6.8, "mi": -6, "Umx":-6.8, "Tin":-6.8, "mUUUax":-6.8, "maxn":-6.8, "in": -6, "Umin": -6.8, "m":-6.4, "max": 1, "mij": -6.8," ": -6.8, "UUax":-6.8, "Tin":-6.8, "mUUUax":-6.8, "max": -6.8, "min":-6.8, "mUax":-6.8, "man": -6, "mUmin": -6.8, "mi": -6, "Umin": -6.8, "m":-6.4, "max": 1, "mij": -6.8," ": -6.8, "UUaxin": -6, "Umin": -6.8, "m":-6.4, 1,334en":-5e556.8, "n": -6
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
["\uDA9D\uDDDDux\uDA9D\uDDDdDux\uDA9D\uDDDduxux\uDA9D\uDDDdDDDux\uDA9D\uDDDeu|\uDA9D\uDDDDDDux\uDA9D\uDDDdDDADDDux\uDA9D\uDDDduxux\uDA9D\uDDDdD\uDA9D\uDDDduuDDA9D\uDA9D\uDDDDD-ux\uDA9D\uDDDdDDAuDDDDDDDux\uDA9D\uDDDduxux\uDA9D\uDDDdDux\uDA0D\uDDDdu|DDux\uDA9D\uDDDddDDDDDux\uDA9D\uDDDduxux\uDA9D\uDDDdDux\uDA9D\uDDDdu|DDux\uDA9D\uDDDddDDux\uDA9D\uDDDdu|\uDA4D\uDDA9D\u³D\uDA9D\uDDDDDDDDD\uDA9D\uDDDduxu\uDA9D\uDDDd:DEux\uDA9D\uDDDdDux\uDA9DDDDux\uDA9D\uDDDdu|\uDA8D\uDDDDDDDDux\uDA9D\uDDDddDDDx\uDA9D\uDDDd\uDA4D\uDDA0DDDux\uDA9D\uDDDdDDA0
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
[15,4,5,[[5,5,[4,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,4,[5,[5,[4,[6,[5,[54,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,-418,[8,[[[
|
||||||
|
[[-41.8,
[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,28,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[[5,2,[5,[5,[[null,[413,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[ "\
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
[[[{},{}, [[[{},{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},3,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[7,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, 8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[7,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[ [-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-20,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-417.777E-8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ { "$i": 9, "max": 8, "x": 2.0e+28,[[false, [[false, "8[[-418,[8,[4,[5,[5,[4,[6 8, "man": -3.8, "max": 8, "max": 8, "man": ,[ššššššššššš5,5, 5,[5,max
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{},{}, [[[{},{},[[[[{},{}, [[[{},{},[5,[[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,5,4,[5,[5,[4,[6,[5,[5,55,5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[4,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[{"x":[{"id": "xx"}],"x":[{"d":"x"}],""J:"xx"}],,[5,[[5,[4,5[[,5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[462,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,4,[5,[5,[5,ž,[5,[5,[[5,[5,[415,[4,[5,[5,[[5,(((((((((((((((((((((((((((((((((((((((((((((((((((((([[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[4,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[[55,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[4,[5,[[null,5,[5,[5,[[5,[5,[415,[4,
|
||||||
|
[[[[[false, [[f[
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4
|
||||||
|
"p{ },,[5[
|
||||||
|
[
|
||||||
|
[{ },[[[6[
|
||||||
|
|
||||||
|
]ue,true,[ true,[[-41,[-,[5[[[[[[true,t[,[5rue,[ true,true, true,[[[[[[[[[[ true,true,[[ true,true,[41,,[ true,pr]]]
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,4,[5,[5,[4,[6,[5,[5,55,5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[4,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,4,[5,[5,[4,[6,[5,[5,55,5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[4,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[{"x":[{"id": {";;" : -8,"8[-5,[-5,5,[-5,5,[-" : 8,"" : -8,"" : -8,"8" : -8,"8;" : -8,"8" : 8,"" : -8,"8[-5,[-5,5,[-5,5,[-" : 8,"" : -8,"" : -8,"8" : -8,"8;" : -8,"8" : 8,"" : -8,"8" :-8,"8" : 8,"" : -8,"" : "" :",5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,4,[5,[5,[5,ž,[5,[5,[[5,[5,[415,[4,[5,[5,[[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,4,[5,[5,[4,[6,[5,[5,55,5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[4,[5,[[null,5,[5,[5,[[5,[5,[415,[4,
|
||||||
|
[[[[[false, [[f[
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4
|
||||||
|
"p{ },,[5[
|
||||||
|
[
|
||||||
|
[{ },[[[6[
|
||||||
|
|
||||||
|
][-41,[-,[5[,[5,[41,
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
"\uDBFF\zFEFF
|
||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{},{}, [[[{},{},[[[[{},{}, [[[{},{},[5,[[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[{"x":[{"id": "xx"}],"x":[{"d":"x"}],"":"xx"}],,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,4,[5,[5,[5,ž,[5,[5,[[5,[5,[415,[4,[5,[5,[[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5[[[[[[[[[[[
|
||||||
|
[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,4,[5,[5,[4,[6,[5,[5,55,5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[4,[5,[[null,5,[5,[5,[[5,[5,[415,[4,
|
||||||
|
[[[[[false, [[f[
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4
|
||||||
|
"p{ },,[5[
|
||||||
|
[
|
||||||
|
[{ },[[[6[
|
||||||
|
|
||||||
|
][-41,[-,[5[,[5,[41,
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"title":"\u041e\ud41d41d\ud82d\udd29\4d9cu0430 \u;a 4 \u03
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
[[[{},{}, [[[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ 8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-417,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[0.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[["\uDA9D\uDDDDux\uDA9D^uDDDdux\uDA9D\uDDA9D\uDA9D\DDDD[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,[[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1Dux9D\uDA9D\uDDDDDD*x¤Ý¤Ò-ËŠ\u18,DA9D\uDDdDDA0
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
[[[{},{}, [[[{},{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222241.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[7,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[0,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,8,[8,[8,[[[[[-41.8,[7E-5,7E-5,3E8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[0,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,8,[8,[8,[[[[[-41.8,[7E-5,7E-5,3E8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222241.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[7,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[0,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,8,[8,[8,[[[[[-41.8,[7E-5,7E-5,3E8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[0,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,8,[8,[8,[[[[[-41.8,[7E-5,7E-5,3E8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-20.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[ [[[ [[-41.8,[3,[8,[[,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222241.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[7,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{
|
||||||
|
|
||||||
|
}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-20.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418[[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false,"\@d83d\u34e55,335223334e55,33e5,334e55,3e5,39990.099999de55,e3339\ud
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{},{}, [[[{},{},[[[[{},{}, [[[{},{},[5,[[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[95,[5,[4,5,[5,5,[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[[[[[[[[[[[[[[[[[[[[[[[[[[{"a0.000000+0000000000000000000000000sd":"s1f", "dfg0000000000000d":"s1f", "d0g00000000000000sd":"s1f", "dff[[[[[[[[[[[[[[[[[0sd":"s1f", "dff[[[[[000000000000000sd":"G1f", "dfg00000000040000sd":"s1f", "d]]]null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,4,[5,[5,[4,[6,[5,[5,55,5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[4,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5]]]]]]]]]]]]]]]]]]]]]]]](]]]]]]]]]]]]]]]]]]]]0]]]]]]000sd":"s1f", "dfg00000000000000sd":,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5"sÌ™,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5415,[4,[5,[[5,[4,[5,[5,4,[5,[5,[4,[6,[5,[5,55,5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[ÝÓ5,[3,[5,5,[5,[5,[[n "0ÿ"fg"]]ull,[415,[[5,[5,[415,4,5,[[5,5,[4,[5,[[null,5,[5,[5,[[5,[5,[415,[4,
|
||||||
|
[[[[[false, [[f[
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4
|
||||||
|
"p{ },,[5[
|
||||||
|
[
|
||||||
|
[{ },[[[6[
|
||||||
|
|
||||||
|
][-41,[-,[5[,[5,[41",:]
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
{";N" :[[[{},{}, [[[{},{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[ 8, [ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[faf
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
"\uDA8D\tD]{DDD
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
[4,[5,[5,[4,[6,[5,[5,55,5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,[[5,[5,[415,[4,[5,[5,[3,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[413,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[[5,[4,[5,[5,[5,5,[5,[5,[[5,[5,[415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,5,[5,[5,[[null,5,[5,[5,5,[5,[5,[[5,[5,[3415,[4,[5,[5,[4,[5,[5,[5,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[5,5,[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[
[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-41,5,[[5,[4,[5,[[5,5,[5,[5,[[null,[415,[4,[5,[5,[4,5,[[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[4,[5,[5,[4,5,[[[[5,5,[5,[5,[[null,[415,[[5,[5,[415,4,5,[[5,[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [{ "min":1.0e+9, ""[[{},{}:0 -1.0e020 },[[false, [[false, [[[{},8,
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,71 @@
|
|||||||
|
[[[{},{}, [[[{},{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ 8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{},[[[{},8,[[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
9777E-1,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[83,6663,66666666,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[[[[[[-41.8,[83,666377777777777, 777728273720, 1, "1", 77777777, 1, "1", 77, 677777777777777777777777777777777777, 1, "1", 7738888888888, 1, "1", 67731, "1-", 7777777777777, 1,7777777777777777777, 1, "1", 7777777, "1", 77, 677777777777777777777777777777777777, 1, 77777777777, 1, "1", 7738888888888, 1, "1",7777777, 7777777777, 777728273720, 1, "1", 777777777777777, ,66666666,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,[[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
["[-Ò418,
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"":"_________..............................._____________@@@@ffa\udafa\udffa2fa[-401.
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
|
||||||
|
|
||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[[[
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{"":
|
||||||
|
|
||||||
|
|
||||||
|
5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[[[[false, [[f[
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4
|
||||||
|
"p{ },[
|
||||||
|
[
|
||||||
|
[{ },[[[6[
|
||||||
|
|
||||||
|
][-41,[-[
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
"de39\ud83dLudœ8
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
[[[{},{}, [[[{},{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[7,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
|
||||||
|
|
||||||
|
-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
9777E-1,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},2,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[8,[8,[[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[7,[[[[41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,[[[[[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-20.8,[8,[8,[[1.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41,{},[[false, [[false, [[[{},8,[-41.8,[8,[8,[[[[[-41.8,[8,[8,[[[[ [[[ [[-41.8,[3,[8,[[[[ [[[
|
||||||
|
[[-418,[8,[[[
|
||||||
|
[[-41.8,[8,[8,
|
||||||
|
[[-41.8,[-41.8,[8,[8,1.8,[-41.8,[8,[
|
||||||
|
[[-418,[8,[[[[[[-41.8,[8,[8,[[[[ [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, [[[{},8,[-41.8,[8,[8.8,[8,[[[{},{}, [[[{},{},[[false, [[false, [[[{},8, [[[
|
||||||
|
[[-41,{},[[[[{},{}, [[[{},{},[[false, [[false, "ffa2ffa\udafa\udffad@faa\udff41.8,[8,[8,[[[
|
||||||
|
[8{},[-[
|
||||||
@@ -38,6 +38,8 @@ enum WeaselJsonStatus {
|
|||||||
WeaselJson_REJECT,
|
WeaselJson_REJECT,
|
||||||
/** json is too deeply nested */
|
/** json is too deeply nested */
|
||||||
WeaselJson_OVERFLOW,
|
WeaselJson_OVERFLOW,
|
||||||
|
/** Tried to call parse on a null parser */
|
||||||
|
WeaselJson_NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct WeaselJsonParser WeaselJsonParser;
|
typedef struct WeaselJsonParser WeaselJsonParser;
|
||||||
@@ -65,7 +67,7 @@ void WeaselJsonParser_destroy(WeaselJsonParser *parser);
|
|||||||
/** Incrementally parse `len` more bytes starting at `buf`. `buf` may be
|
/** Incrementally parse `len` more bytes starting at `buf`. `buf` may be
|
||||||
* modified. Call with `len` 0 to indicate end of data. `buf` may be null if
|
* modified. Call with `len` 0 to indicate end of data. `buf` may be null if
|
||||||
* `len` is 0. `len` must not be negative; a negative length is treated as a
|
* `len` is 0. `len` must not be negative; a negative length is treated as a
|
||||||
* rejected input. */
|
* rejected input. Returns WeaselJson_NULL if parser is null */
|
||||||
WeaselJsonStatus WeaselJsonParser_parse(WeaselJsonParser *parser, char *buf,
|
WeaselJsonStatus WeaselJsonParser_parse(WeaselJsonParser *parser, char *buf,
|
||||||
int len);
|
int len);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|||||||
@@ -29,17 +29,26 @@ WeaselJsonParser_create(int stackSize, const WeaselJsonCallbacks *callbacks,
|
|||||||
|
|
||||||
__attribute__((visibility("default"))) void
|
__attribute__((visibility("default"))) void
|
||||||
WeaselJsonParser_reset(WeaselJsonParser *parser) {
|
WeaselJsonParser_reset(WeaselJsonParser *parser) {
|
||||||
|
if (parser == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
((Parser3 *)parser)->reset();
|
((Parser3 *)parser)->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((visibility("default"))) void
|
__attribute__((visibility("default"))) void
|
||||||
WeaselJsonParser_destroy(WeaselJsonParser *parser) {
|
WeaselJsonParser_destroy(WeaselJsonParser *parser) {
|
||||||
|
if (parser == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
((Parser3 *)parser)->~Parser3();
|
((Parser3 *)parser)->~Parser3();
|
||||||
free(parser);
|
free(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((visibility("default"))) WeaselJsonStatus
|
__attribute__((visibility("default"))) WeaselJsonStatus
|
||||||
WeaselJsonParser_parse(WeaselJsonParser *parser, char *buf, int len) {
|
WeaselJsonParser_parse(WeaselJsonParser *parser, char *buf, int len) {
|
||||||
|
if (parser == nullptr) [[unlikely]] {
|
||||||
|
return WeaselJson_NULL;
|
||||||
|
}
|
||||||
return ((Parser3 *)parser)->parse(buf, len);
|
return ((Parser3 *)parser)->parse(buf, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-11
@@ -139,7 +139,7 @@ struct Parser3 {
|
|||||||
stackPtr = stack();
|
stackPtr = stack();
|
||||||
std::ignore = push({N_VALUE, N_WHITESPACE, T_EOF});
|
std::ignore = push({N_VALUE, N_WHITESPACE, T_EOF});
|
||||||
inKey = false;
|
inKey = false;
|
||||||
rejected = false;
|
terminalStatus = WeaselJson_OK;
|
||||||
utf8Codepoint = 0;
|
utf8Codepoint = 0;
|
||||||
utf16Surrogate = 0;
|
utf16Surrogate = 0;
|
||||||
minCodepoint = 0;
|
minCodepoint = 0;
|
||||||
@@ -162,7 +162,7 @@ struct Parser3 {
|
|||||||
NumDfa numDfa;
|
NumDfa numDfa;
|
||||||
Utf8Dfa strDfa;
|
Utf8Dfa strDfa;
|
||||||
bool inKey = false;
|
bool inKey = false;
|
||||||
bool rejected = false;
|
WeaselJsonStatus terminalStatus = WeaselJson_OK;
|
||||||
|
|
||||||
#ifndef HAS_MUSTTAIL
|
#ifndef HAS_MUSTTAIL
|
||||||
char *stashBufForTrampoline;
|
char *stashBufForTrampoline;
|
||||||
@@ -625,7 +625,7 @@ inline PRESERVE_NONE ContinuationStatus n_string2(Parser3 *self, char *buf,
|
|||||||
return WeaselJson_REJECT;
|
return WeaselJson_REJECT;
|
||||||
}
|
}
|
||||||
buf += 4;
|
buf += 4;
|
||||||
if (0xd800 <= codepoint && codepoint <= 0xdfff) {
|
if (0xd800 <= codepoint && codepoint <= 0xdbff) {
|
||||||
// utf-16 surrogate
|
// utf-16 surrogate
|
||||||
int32_t codepoint2 = read4_hex(buf + 2);
|
int32_t codepoint2 = read4_hex(buf + 2);
|
||||||
if (!(buf[0] == '\\' && buf[1] == 'u' && 0xdc00 <= codepoint2 &&
|
if (!(buf[0] == '\\' && buf[1] == 'u' && 0xdc00 <= codepoint2 &&
|
||||||
@@ -650,6 +650,8 @@ inline PRESERVE_NONE ContinuationStatus n_string2(Parser3 *self, char *buf,
|
|||||||
self->writeBuf[0] = (0b00000111 & codepoint) | 0b11110000;
|
self->writeBuf[0] = (0b00000111 & codepoint) | 0b11110000;
|
||||||
self->writeBuf += 4;
|
self->writeBuf += 4;
|
||||||
}
|
}
|
||||||
|
} else if (0xdc00 <= codepoint && codepoint <= 0xdfff) [[unlikely]] {
|
||||||
|
return WeaselJson_REJECT;
|
||||||
} else {
|
} else {
|
||||||
if (!(self->flags & WeaselJsonRaw)) {
|
if (!(self->flags & WeaselJsonRaw)) {
|
||||||
if (codepoint < 0x80) {
|
if (codepoint < 0x80) {
|
||||||
@@ -793,7 +795,7 @@ inline PRESERVE_NONE ContinuationStatus t_hex2(Parser3 *self, char *buf,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(self->utf8Codepoint < 0x10000);
|
assert(self->utf8Codepoint < 0x10000);
|
||||||
if (0xd800 <= self->utf8Codepoint && self->utf8Codepoint <= 0xdfff) {
|
if (0xd800 <= self->utf8Codepoint && self->utf8Codepoint <= 0xdbff) {
|
||||||
// utf-16 surrogate
|
// utf-16 surrogate
|
||||||
self->utf16Surrogate = self->utf8Codepoint;
|
self->utf16Surrogate = self->utf8Codepoint;
|
||||||
self->utf8Codepoint = 0;
|
self->utf8Codepoint = 0;
|
||||||
@@ -808,6 +810,10 @@ inline PRESERVE_NONE ContinuationStatus t_hex2(Parser3 *self, char *buf,
|
|||||||
}
|
}
|
||||||
MUSTTAIL return Parser3::keepGoing(self, buf, bufEnd);
|
MUSTTAIL return Parser3::keepGoing(self, buf, bufEnd);
|
||||||
}
|
}
|
||||||
|
if (0xdc00 <= self->utf8Codepoint && self->utf8Codepoint <= 0xdfff)
|
||||||
|
[[unlikely]] {
|
||||||
|
return WeaselJson_REJECT;
|
||||||
|
}
|
||||||
if (!(self->flags & WeaselJsonRaw)) {
|
if (!(self->flags & WeaselJsonRaw)) {
|
||||||
bool useTmp = buf - self->writeBuf < 3;
|
bool useTmp = buf - self->writeBuf < 3;
|
||||||
char *p = tmp;
|
char *p = tmp;
|
||||||
@@ -1064,12 +1070,12 @@ constexpr inline struct ContinuationTable {
|
|||||||
inline WeaselJsonStatus Parser3::parse(char *buf, int len) {
|
inline WeaselJsonStatus Parser3::parse(char *buf, int len) {
|
||||||
this->dataBegin = this->writeBuf = buf;
|
this->dataBegin = this->writeBuf = buf;
|
||||||
|
|
||||||
if (this->rejected) [[unlikely]] {
|
if (this->terminalStatus != WeaselJson_OK) [[unlikely]] {
|
||||||
return WeaselJson_REJECT;
|
return this->terminalStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len < 0) [[unlikely]] {
|
if (len < 0) [[unlikely]] {
|
||||||
this->rejected = true;
|
this->terminalStatus = WeaselJson_REJECT;
|
||||||
return WeaselJson_REJECT;
|
return WeaselJson_REJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1079,8 +1085,8 @@ inline WeaselJsonStatus Parser3::parse(char *buf, int len) {
|
|||||||
// range.
|
// range.
|
||||||
ContinuationStatus status =
|
ContinuationStatus status =
|
||||||
symbolTables.continuations[top()](this, buf, buf + len);
|
symbolTables.continuations[top()](this, buf, buf + len);
|
||||||
if (status == WeaselJson_REJECT) {
|
if (status > WeaselJson_AGAIN) {
|
||||||
this->rejected = true;
|
this->terminalStatus = WeaselJsonStatus(status);
|
||||||
}
|
}
|
||||||
return WeaselJsonStatus(status);
|
return WeaselJsonStatus(status);
|
||||||
#else
|
#else
|
||||||
@@ -1089,8 +1095,8 @@ inline WeaselJsonStatus Parser3::parse(char *buf, int len) {
|
|||||||
while ((result = symbolTables.continuations[top()](
|
while ((result = symbolTables.continuations[top()](
|
||||||
this, stashBufForTrampoline, buf + len)) == kBounce)
|
this, stashBufForTrampoline, buf + len)) == kBounce)
|
||||||
;
|
;
|
||||||
if (result == WeaselJson_REJECT) {
|
if (result > WeaselJson_AGAIN) {
|
||||||
this->rejected = true;
|
this->terminalStatus = WeaselJsonStatus(result);
|
||||||
}
|
}
|
||||||
return WeaselJsonStatus(result);
|
return WeaselJsonStatus(result);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -202,6 +202,62 @@ TEST_CASE("parser3") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("overflow state is sticky") {
|
||||||
|
auto c = noopCallbacks();
|
||||||
|
// stackSize 3 is exactly big enough to hold reset()'s bootstrap, but too
|
||||||
|
// small for nested arrays. Overflows must be terminal like rejects: a later
|
||||||
|
// end-of-data call must never report OK for an incomplete document.
|
||||||
|
auto *parser = WeaselJsonParser_create(3, &c, nullptr, 0);
|
||||||
|
REQUIRE(parser != nullptr);
|
||||||
|
|
||||||
|
std::string doc = "[[";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, doc.data(), doc.size()) ==
|
||||||
|
WeaselJson_OVERFLOW);
|
||||||
|
|
||||||
|
// After overflow, the end-of-data call must not return OK.
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) != WeaselJson_OK);
|
||||||
|
// It should keep reporting a terminal failure.
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) != WeaselJson_OK);
|
||||||
|
|
||||||
|
// Further data chunks must also stay terminal.
|
||||||
|
std::string more = "]]";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, more.data(), more.size()) !=
|
||||||
|
WeaselJson_OK);
|
||||||
|
|
||||||
|
WeaselJsonParser_destroy(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("overflow is sticky for nested objects") {
|
||||||
|
auto c = noopCallbacks();
|
||||||
|
auto *parser = WeaselJsonParser_create(4, &c, nullptr, 0);
|
||||||
|
REQUIRE(parser != nullptr);
|
||||||
|
|
||||||
|
std::string doc = "{\"a\":{ \"a\":";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, doc.data(), doc.size()) ==
|
||||||
|
WeaselJson_OVERFLOW);
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) != WeaselJson_OK);
|
||||||
|
|
||||||
|
WeaselJsonParser_destroy(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("reset clears overflow state") {
|
||||||
|
auto c = noopCallbacks();
|
||||||
|
auto *parser = WeaselJsonParser_create(3, &c, nullptr, 0);
|
||||||
|
REQUIRE(parser != nullptr);
|
||||||
|
|
||||||
|
std::string doc = "[[";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, doc.data(), doc.size()) ==
|
||||||
|
WeaselJson_OVERFLOW);
|
||||||
|
// After reset the parser should accept a minimal document again.
|
||||||
|
WeaselJsonParser_reset(parser);
|
||||||
|
std::string copy = "1";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, copy.data(), copy.size()) ==
|
||||||
|
WeaselJson_AGAIN);
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) == WeaselJson_OK);
|
||||||
|
|
||||||
|
WeaselJsonParser_destroy(parser);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("rejected state is sticky") {
|
TEST_CASE("rejected state is sticky") {
|
||||||
auto c = noopCallbacks();
|
auto c = noopCallbacks();
|
||||||
auto *parser = WeaselJsonParser_create(1024, &c, nullptr, 0);
|
auto *parser = WeaselJsonParser_create(1024, &c, nullptr, 0);
|
||||||
@@ -246,6 +302,20 @@ TEST_CASE("create rejects too-small stack") {
|
|||||||
WeaselJsonParser_destroy(parser);
|
WeaselJsonParser_destroy(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("reset and destroy accept null parser") {
|
||||||
|
// Creation can legitimately fail and return null. The cleanup functions must
|
||||||
|
// tolerate a null pointer the same way free(nullptr) is a no-op.
|
||||||
|
auto c = noopCallbacks();
|
||||||
|
WeaselJsonParser *parser = WeaselJsonParser_create(-1, &c, nullptr, 0);
|
||||||
|
REQUIRE(parser == nullptr);
|
||||||
|
WeaselJsonParser_reset(parser); // must not crash
|
||||||
|
WeaselJsonParser_destroy(parser); // must not crash
|
||||||
|
|
||||||
|
// Calling reset/destroy on literal nullptr directly must also be safe.
|
||||||
|
WeaselJsonParser_reset(nullptr);
|
||||||
|
WeaselJsonParser_destroy(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("parse rejects negative length") {
|
TEST_CASE("parse rejects negative length") {
|
||||||
auto c = noopCallbacks();
|
auto c = noopCallbacks();
|
||||||
auto *parser = WeaselJsonParser_create(1024, &c, nullptr, 0);
|
auto *parser = WeaselJsonParser_create(1024, &c, nullptr, 0);
|
||||||
@@ -260,6 +330,10 @@ TEST_CASE("parse rejects negative length") {
|
|||||||
WeaselJsonParser_destroy(parser);
|
WeaselJsonParser_destroy(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Calling parse with nullptr doesn't crash") {
|
||||||
|
REQUIRE(WeaselJsonParser_parse(nullptr, nullptr, 0) == WeaselJson_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("streaming") { testStreaming(json); }
|
TEST_CASE("streaming") { testStreaming(json); }
|
||||||
|
|
||||||
TEST_CASE("reset clears inKey and transient state") {
|
TEST_CASE("reset clears inKey and transient state") {
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ int main(int argc, char **argv) {
|
|||||||
case WeaselJson_REJECT:
|
case WeaselJson_REJECT:
|
||||||
case WeaselJson_OVERFLOW:
|
case WeaselJson_OVERFLOW:
|
||||||
return 1;
|
return 1;
|
||||||
|
case WeaselJson_NULL:
|
||||||
|
fprintf(stderr, "parse called with a null parser\n");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
if (l == 0) {
|
if (l == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -95,8 +95,20 @@ def test_create_rejects_too_small_stack():
|
|||||||
raise AssertionError(f"expected ValueError for stackSize={stack_size}")
|
raise AssertionError(f"expected ValueError for stackSize={stack_size}")
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_library_raises_oserror():
|
||||||
|
try:
|
||||||
|
weaseljson.WeaselJsonParser(
|
||||||
|
weaseljson.WeaselJsonCallbacksBase(),
|
||||||
|
build_dir="/nonexistent",
|
||||||
|
)
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
|
raise AssertionError("expected OSError when the shared library is missing")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_object_keys_routed_correctly()
|
test_object_keys_routed_correctly()
|
||||||
test_mixed_values()
|
test_mixed_values()
|
||||||
test_create_rejects_too_small_stack()
|
test_create_rejects_too_small_stack()
|
||||||
|
test_missing_library_raises_oserror()
|
||||||
print("python bindings ok")
|
print("python bindings ok")
|
||||||
|
|||||||
+2
-7
@@ -30,6 +30,7 @@ class WeaselJsonStatus(enum.Enum):
|
|||||||
AGAIN = 1
|
AGAIN = 1
|
||||||
REJECT = 2
|
REJECT = 2
|
||||||
OVERFLOW = 3
|
OVERFLOW = 3
|
||||||
|
NULL = 4
|
||||||
|
|
||||||
|
|
||||||
class WeaselJsonCallbacksBase:
|
class WeaselJsonCallbacksBase:
|
||||||
@@ -84,13 +85,7 @@ class WeaselJsonParser:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
if self._lib is None:
|
if self._lib is None:
|
||||||
import sys
|
raise OSError(f"Could not load libweaseljson from {build_dir}")
|
||||||
|
|
||||||
print(
|
|
||||||
"Could not find libweaseljson implementation",
|
|
||||||
file=sys.stderr,
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
self._lib.WeaselJsonParser_create.argtypes = (
|
self._lib.WeaselJsonParser_create.argtypes = (
|
||||||
ctypes.c_int,
|
ctypes.c_int,
|
||||||
|
|||||||
Reference in New Issue
Block a user