Skip to content

Commit fcbe04b

Browse files
added objects, added mandatory
1 parent 9f6bf10 commit fcbe04b

File tree

4 files changed

+175
-67
lines changed

4 files changed

+175
-67
lines changed

src/sjv/sjv.cpp

Lines changed: 94 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -13,74 +13,67 @@ namespace sjv
1313

1414
bool sjv::verify_json(const string &pointer, const json &input, const json &rules)
1515
{
16-
try
16+
// Polymorphism on list, for us a single item or a list are indistinguishable
17+
// All the elements in the list must pass the test
18+
if (input.is_array())
1719
{
18-
// Polymorphism on list, for us a single item or a list are indistinguishable
19-
// All the elements in the list must pass the test
20-
if (input.is_array())
21-
{
22-
for (auto i : input)
23-
if (!verify_json(pointer, i, rules))
24-
return false;
25-
return true;
26-
}
27-
28-
// Find all rules that apply for the input node
29-
// TODO: accelerate this
30-
std::vector<json> matching_rules;
31-
for (auto i : rules)
32-
{
33-
if (i.at("pointer") == pointer)
34-
matching_rules.push_back(i);
35-
}
36-
37-
// There must be at least one, otherwise warning and return true if not strict
38-
if (matching_rules.empty())
39-
{
40-
std::cout << "WARNING: "
41-
<< "Unknown entry " << pointer << std::endl;
42-
43-
if (strict)
20+
for (auto i : input)
21+
if (!verify_json(pointer, i, rules))
4422
return false;
45-
}
23+
return true;
24+
}
4625

47-
// Test all rules, only one must pass, otherwise throw exception
48-
int count = 0;
26+
// Find all rules that apply for the input node
27+
// TODO: accelerate this
28+
std::vector<json> matching_rules;
29+
for (auto i : rules)
30+
{
31+
if (i.at("pointer") == pointer)
32+
matching_rules.push_back(i);
33+
}
4934

50-
for (auto i : matching_rules)
51-
if (verify_rule(input, i))
52-
count++;
35+
// There must be at least one, otherwise warning and return true if not strict
36+
if (matching_rules.empty())
37+
{
38+
std::cout << "WARNING: "
39+
<< "Unknown entry " << pointer << std::endl;
5340

54-
if (count == 0)
55-
{
56-
std::cout << "ERROR: No valid rules in this list:" << std::endl;
57-
for (auto i : matching_rules)
58-
std::cout << i << std::endl;
41+
if (strict)
5942
return false;
60-
}
43+
}
6144

62-
if (count > 1)
63-
{
64-
std::cout << "ERROR: Multiple valid rules in this list, only one should be valid:" << std::endl;
65-
for (auto i : matching_rules)
66-
std::cout << i << std::endl;
67-
return false;
68-
}
45+
// Test all rules, only one must pass, otherwise throw exception
46+
int count = 0;
6947

70-
// If it passes and if it is a dictionary, then test all childrens
71-
// TODO: if any of these fails we need to report it somehow
72-
if (input.is_structured())
73-
for (auto &i : input.items())
74-
if (!verify_json(pointer + i.key() + "/", i.value(), rules))
75-
return false;
48+
for (auto i : matching_rules)
49+
if (verify_rule(input, i))
50+
count++;
7651

77-
// If they all pass, return true
78-
return true;
52+
if (count == 0 && !matching_rules.empty())
53+
{
54+
std::cout << "ERROR: No valid rules in this list:" << std::endl;
55+
for (auto i : matching_rules)
56+
std::cout << i << std::endl;
57+
return false;
7958
}
80-
catch (std::vector<json> e)
59+
60+
if (count > 1)
8161
{
62+
std::cout << "ERROR: Multiple valid rules in this list, only one should be valid:" << std::endl;
63+
for (auto i : matching_rules)
64+
std::cout << i << std::endl;
8265
return false;
8366
}
67+
68+
// If it passes and if it is a dictionary, then test all childrens
69+
// TODO: if any of these fails we need to report it somehow
70+
if (input.is_structured())
71+
for (auto &i : input.items())
72+
if (!verify_json(pointer + i.key() + "/", i.value(), rules))
73+
return false;
74+
75+
// If they all pass, return true
76+
return true;
8477
};
8578
bool sjv::verify_rule(const json &input, const json &rule)
8679
{
@@ -93,6 +86,12 @@ namespace sjv
9386
return verify_rule_float(input, rule);
9487
else if (type == "file")
9588
return verify_rule_file(input, rule);
89+
else if (type == "folder")
90+
return verify_rule_folder(input, rule);
91+
else if (type == "string")
92+
return verify_rule_string(input, rule);
93+
else if (type == "object")
94+
return verify_rule_object(input, rule);
9695
else
9796
{
9897
std::cout << "ERROR: Unknown type " << std::endl;
@@ -123,6 +122,18 @@ namespace sjv
123122

124123
return true;
125124
};
125+
bool sjv::verify_rule_folder(const json &input, const json &rule)
126+
{
127+
assert(rule.at("type") == "folder");
128+
129+
std::string p_str = cwd + "/" + string(input);
130+
std::filesystem::path p = std::filesystem::path(p_str);
131+
132+
if (!std::filesystem::is_directory(p))
133+
return false;
134+
135+
return true;
136+
};
126137
bool sjv::verify_rule_float(const json &input, const json &rule)
127138
{
128139
assert(rule.at("type") == "float");
@@ -153,17 +164,38 @@ namespace sjv
153164

154165
return true;
155166
};
156-
bool sjv::verify_rule_path(const json &input, const json &rule)
157-
{
158-
return false;
159-
};
160167
bool sjv::verify_rule_string(const json &input, const json &rule)
161168
{
162-
return false;
169+
assert(rule.at("type") == "string");
170+
171+
if (!input.is_string())
172+
return false;
173+
174+
if (rule.contains("options"))
175+
{
176+
int count = 0;
177+
for (auto e : rule["options"])
178+
if (e == input)
179+
count++;
180+
if (count != 1)
181+
return false;
182+
}
183+
184+
return true;
163185
};
164-
bool sjv::verify_rule_dict(const json &input, const json &rule)
186+
bool sjv::verify_rule_object(const json &input, const json &rule)
165187
{
166-
return false;
188+
assert(rule.at("type") == "object");
189+
190+
if (!input.is_object())
191+
return false;
192+
193+
if (rule.contains("required"))
194+
for (auto e : rule["required"])
195+
if (!input.contains(string(e)))
196+
return false;
197+
198+
return true;
167199
};
168200

169201
} // namespace sjv

src/sjv/sjv.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ namespace sjv
2121

2222
// Type-specific rule handlers
2323
bool verify_rule_file(const json &input, const json &rule);
24+
bool verify_rule_folder(const json &input, const json &rule);
2425
bool verify_rule_float(const json &input, const json &rule);
2526
bool verify_rule_int(const json &input, const json &rule);
26-
bool verify_rule_path(const json &input, const json &rule);
2727
bool verify_rule_string(const json &input, const json &rule);
28-
bool verify_rule_dict(const json &input, const json &rule);
28+
bool verify_rule_object(const json &input, const json &rule);
2929

3030
// Working directory
3131
string cwd = "";

tags.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,19 @@
22

33
## float,int:
44

5-
* min
6-
* max
5+
* min: number
6+
* max: number
77

88
## file
99

10-
* extensions
10+
* extensions: [".txt",".msh"]
11+
12+
## folder
13+
14+
## string
15+
16+
options: ["these","are","options"]
17+
18+
## object
19+
20+
required: list of fields required for this object to be valid

tests/test_validator.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,69 @@ TEST_CASE("file_type", "[validator]")
123123
REQUIRE(!sjv.verify_json(input,rules));
124124

125125
}
126+
127+
TEST_CASE("type_string", "[validator]")
128+
{
129+
json input = R"(
130+
{
131+
"string1": "teststring"
132+
}
133+
)"_json;
134+
135+
json rules = R"(
136+
[
137+
{
138+
"pointer": "/",
139+
"type": "skip_check"
140+
},
141+
{
142+
"pointer": "/string1/",
143+
"type": "string"
144+
}
145+
]
146+
)"_json;
147+
148+
sjv::sjv sjv;
149+
150+
REQUIRE(sjv.verify_json(input,rules));
151+
152+
rules[1]["options"][0] = "blah";
153+
154+
REQUIRE(!sjv.verify_json(input,rules));
155+
156+
rules[1]["options"][1] = "teststring";
157+
158+
REQUIRE(sjv.verify_json(input,rules));
159+
160+
}
161+
162+
TEST_CASE("type_object", "[validator]")
163+
{
164+
json input = R"(
165+
{
166+
"string1": "teststring"
167+
}
168+
)"_json;
169+
170+
json rules = R"(
171+
[
172+
{
173+
"pointer": "/",
174+
"type": "object",
175+
"required": ["string1"]
176+
}
177+
]
178+
)"_json;
179+
180+
sjv::sjv sjv;
181+
182+
sjv.strict = true;
183+
REQUIRE(!sjv.verify_json(input,rules));
184+
sjv.strict = false;
185+
REQUIRE(sjv.verify_json(input,rules));
186+
187+
rules[0]["required"][1] = "randomstring";
188+
189+
REQUIRE(!sjv.verify_json(input,rules));
190+
191+
}

0 commit comments

Comments
 (0)