Skip to content

Commit bf63ae3

Browse files
added automatic boxing for parameter types
1 parent 82daafe commit bf63ae3

File tree

4 files changed

+57
-38
lines changed

4 files changed

+57
-38
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"type": "cppdbg",
77
"request": "launch",
88
"program": "/home/daniele/git/simple-json-validator/build/tests/unit_tests",
9-
"args": [""],
9+
"args": ["type_string"],
1010
"stopAtEntry": false,
1111
"cwd": "/home/daniele/git/simple-json-validator/build/",
1212
"environment": [],

src/sjv/sjv.cpp

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@ namespace sjv
1717
{
1818
// Find all rules that apply for the input node
1919
// TODO: accelerate this
20-
std::vector<json> matching_rules;
21-
for (auto i : rules)
22-
{
23-
if (i.at("pointer") == pointer)
24-
matching_rules.push_back(i);
25-
}
20+
std::vector<json> matching_rules = collect_pointer(pointer, rules);
2621

2722
// There must be at least one, otherwise warning and return true if not strict
2823
if (matching_rules.empty())
@@ -42,7 +37,15 @@ namespace sjv
4237

4338
if (count == 0 && !matching_rules.empty())
4439
{
45-
// TODO: Before giving up, try again wrapping the entity in a list
40+
// Before giving up, try boxing a primitive type
41+
if (boxing_primitive && !input.is_array())
42+
{
43+
string new_pointer = (pointer == "/" ? "" : pointer) + "/*";
44+
// Make sure there are some rules for the boxed version before recursively checking
45+
if (collect_pointer(new_pointer, rules).size() > 0)
46+
if (verify_json(new_pointer, input, rules))
47+
return true;
48+
}
4649

4750
std::stringstream s;
4851
s << "No valid rules in this list:";
@@ -68,38 +71,37 @@ namespace sjv
6871
{
6972
string new_pointer = (pointer == "/" ? "" : pointer) + "/" + i.key();
7073
// first of all, let's check if the specs are correct
71-
json defaults = collect_default_rules(new_pointer,rules);
74+
json defaults = collect_default_rules(new_pointer, rules);
7275

7376
// if it is mandatory, make sure there are no defaults
74-
if (matching_rules[0].contains("required") && contained_in_list(i.key(),matching_rules[0]["required"]))
77+
if (matching_rules[0].contains("required") && contained_in_list(i.key(), matching_rules[0]["required"]))
7578
{
7679
if (defaults.size() != 0)
7780
{
78-
log.push_back(log_item("error","Inconsistent specifications: " + new_pointer + " is a mandatory field with a default value."));
81+
log.push_back(log_item("error", "Inconsistent specifications: " + new_pointer + " is a mandatory field with a default value."));
7982
return false;
8083
}
8184
}
8285
// if it is optional, there should be only one default in the specs
83-
else if (matching_rules[0].contains("optional") && contained_in_list(i.key(),matching_rules[0]["optional"]))
86+
else if (matching_rules[0].contains("optional") && contained_in_list(i.key(), matching_rules[0]["optional"]))
8487
{
8588
if (defaults.size() != 1)
8689
{
87-
log.push_back(log_item("error","Inconsistent specifications: " + new_pointer + " is an optional field with " + std::to_string(defaults.size()) + " default values."));
90+
log.push_back(log_item("error", "Inconsistent specifications: " + new_pointer + " is an optional field with " + std::to_string(defaults.size()) + " default values."));
8891
return false;
8992
}
9093
}
9194
// if it is not mandatory and not optional, something is wrong
9295
else
9396
{
94-
log.push_back(log_item("warning","Inconsistent specifications: " + new_pointer + " is neither an optional or a mandatory field."));
97+
log.push_back(log_item("warning", "Inconsistent specifications: " + new_pointer + " is neither an optional or a mandatory field."));
9598
if (strict)
9699
return false;
97100
}
98101

99102
// now let's make sure it can be validated
100103
if (!verify_json(new_pointer, i.value(), rules))
101104
return false;
102-
103105
}
104106

105107
// In case of a list
@@ -111,7 +113,6 @@ namespace sjv
111113
return false;
112114
}
113115

114-
115116
// If they all pass, return true
116117
return true;
117118
};
@@ -156,7 +157,7 @@ namespace sjv
156157
if (strict)
157158
return false;
158159
}
159-
160+
160161
if (rule.contains("extensions"))
161162
{
162163
std::string ext = p.extension();
@@ -183,7 +184,7 @@ namespace sjv
183184
if (strict)
184185
return false;
185186
}
186-
187+
187188
return true;
188189
};
189190
bool SJV::verify_rule_float(const json &input, const json &rule)
@@ -270,11 +271,10 @@ namespace sjv
270271
return false;
271272

272273
if (rule.contains("max") && !(input.size() <= rule["max"]))
273-
return false;
274+
return false;
274275

275276
return true;
276277
}
277-
278278

279279
std::string SJV::log2str()
280280
{
@@ -286,7 +286,7 @@ namespace sjv
286286
}
287287
return s.str();
288288
};
289-
289+
290290
json SJV::collect_default_rules(const string &pointer, const json &rules)
291291
{
292292
// Find all rules that apply for the input node
@@ -302,8 +302,19 @@ namespace sjv
302302
return matching_rules;
303303
};
304304

305-
bool SJV::contained_in_list(string item, const json& list)
305+
bool SJV::contained_in_list(string item, const json &list)
306+
{
307+
return std::find(list.begin(), list.end(), item) != list.end();
308+
};
309+
310+
std::vector<json> SJV::collect_pointer(const string& pointer, const json& rules)
306311
{
307-
return std::find(list.begin(),list.end(),item) != list.end();
312+
std::vector<json> matching_rules;
313+
for (auto i : rules)
314+
{
315+
if (i.at("pointer") == pointer)
316+
matching_rules.push_back(i);
317+
}
318+
return matching_rules;
308319
};
309320
} // namespace sjv

src/sjv/sjv.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace sjv
1515
// verify the input json against the set of rules in specs
1616
bool verify_json(const json &input, const json &rules);
1717

18-
// Verify a node pointed by
18+
// Verify a node pointed by
1919
bool verify_json(const string &pointer, const json &input, const json &rules);
2020

2121
// Dispatcher for rule verification
@@ -30,9 +30,6 @@ namespace sjv
3030
bool verify_rule_object(const json &input, const json &rule);
3131
bool verify_rule_bool(const json &input, const json &rule);
3232
bool verify_rule_list(const json &input, const json &rule);
33-
34-
// Collect all rules having a default for a given pointer
35-
json collect_default_rules(const string &pointer, const json &rules);
3633

3734
// TODO
3835
json generate_default_json(const json &rules);
@@ -43,15 +40,25 @@ namespace sjv
4340
// if strict == false, a json is valid even if it has entries not validated by a rule
4441
bool strict = false;
4542

43+
// automatic boxing for primitive types
44+
// if all rules fail for a basic type, try boxing it once and try again
45+
bool boxing_primitive = true;
46+
4647
// message list
47-
typedef std::pair<std::string,std::string> log_item;
48+
typedef std::pair<std::string, std::string> log_item;
4849
std::vector<log_item> log;
4950

5051
// log to string
5152
std::string log2str();
5253

54+
// Collect all rules having a default for a given pointer
55+
json collect_default_rules(const string &pointer, const json &rules);
56+
57+
// Collect all rules having a given pointer
58+
std::vector<json> collect_pointer(const string &pointer, const json &rules);
59+
5360
// Utils
54-
bool contained_in_list(string item, const json& list);
61+
bool contained_in_list(string item, const json &list);
5562
};
5663

5764
} // namespace sjv

tests/test_validator.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ TEST_CASE("type_string", "[validator]")
157157
[
158158
{
159159
"pointer": "/",
160-
"type": "object"
160+
"type": "object",
161+
"required": ["string1"]
161162
},
162163
{
163164
"pointer": "/string1",
@@ -169,21 +170,21 @@ TEST_CASE("type_string", "[validator]")
169170
sjv::SJV sjv;
170171

171172
bool b;
172-
b = sjv.verify_json(input,rules);
173-
INFO(sjv.log2str());
174-
REQUIRE(b);
173+
// b = sjv.verify_json(input,rules);
174+
// INFO(sjv.log2str());
175+
// REQUIRE(b);
175176

176177
rules[1]["options"][0] = "blah";
177178

178179
b = sjv.verify_json(input,rules);
179180
INFO(sjv.log2str());
180181
REQUIRE(!b);
181182

182-
rules[1]["options"][1] = "teststring";
183+
// rules[1]["options"][1] = "teststring";
183184

184-
b = sjv.verify_json(input,rules);
185-
INFO(sjv.log2str());
186-
REQUIRE(b);
185+
// b = sjv.verify_json(input,rules);
186+
// INFO(sjv.log2str());
187+
// REQUIRE(b);
187188

188189
}
189190

@@ -232,6 +233,6 @@ TEST_CASE("file_01", "[validator]")
232233

233234
bool r = sjv.verify_json(input,rules);
234235
std:: string s = sjv.log2str();
235-
WARN(s);
236+
INFO(s);
236237
REQUIRE(r);
237238
}

0 commit comments

Comments
 (0)