1
+ #include < iostream>
2
+ #include < set>
3
+ #include < map>
4
+ #include < string>
5
+ #include < sstream>
6
+ #include " pybind11_json/pybind11_json.hpp"
7
+ #include " nlohmann/json.hpp"
8
+
9
+ struct InputGuard {
10
+ public:
11
+ InputGuard (const nlohmann::json &j) {
12
+ process_json (j);
13
+
14
+ this ->dict_key_present = false ;
15
+ }
16
+
17
+ ~InputGuard () {}
18
+
19
+ void check_used_inputs () {
20
+ for (auto item : this ->used_inputs ) {
21
+ if (!item.second ) {
22
+ std::string err = std::string (" WARNING: \" " ) + item.first + std::string (" \" parameter remains unused." );
23
+ throw std::runtime_error (err);
24
+ }
25
+ }
26
+ }
27
+
28
+ void mark_used_input (const std::string &input_name) {
29
+ if (this ->prefixes .find (input_name) == this ->prefixes .end ()) {
30
+ std::string prefix = combine_str_vec (this ->curr_prefix );
31
+
32
+ if (!prefix.empty ()) {
33
+ this ->used_inputs [prefix + " /" + input_name] = true ;
34
+ }
35
+ else {
36
+ this ->used_inputs [input_name] = true ;
37
+ }
38
+ }
39
+ }
40
+
41
+ void update_dict_key (std::string dict_key) {
42
+ this ->curr_dict_key = dict_key;
43
+ }
44
+
45
+ void check_read_line (std::string line) {
46
+ if (line == " mode_name" ) {
47
+ if (this ->dict_key_present ) {
48
+ this ->curr_prefix .pop_back ();
49
+ }
50
+ this ->curr_prefix .push_back (this ->curr_dict_key );
51
+ this ->dict_key_present = true ;
52
+ }
53
+ else if (line.empty ()) {
54
+ this ->curr_prefix .pop_back ();
55
+ this ->dict_key_present = false ;
56
+ }
57
+ }
58
+
59
+ void open_spec_file (std::string spec_file_name) {
60
+ this ->curr_prefix .push_back (spec_file_name);
61
+ }
62
+
63
+ void close_spec_file () {
64
+ this ->curr_prefix .pop_back ();
65
+ }
66
+
67
+ private:
68
+ std::map<std::string, bool > used_inputs;
69
+
70
+ std::set<std::string> prefixes;
71
+ std::string curr_dict_key;
72
+ std::vector<std::string> curr_prefix;
73
+
74
+ bool dict_key_present;
75
+
76
+ void process_json (const nlohmann::json &j) {
77
+ nlohmann::json flat = j.flatten ();
78
+
79
+ // JSON Pointer, as in a string syntax for identifying a specific value in JSON
80
+ std::vector<std::string> json_pointers;
81
+
82
+ for (auto f : flat.items ()) {
83
+ json_pointers.push_back (clean_string (f.key ()));
84
+ }
85
+
86
+ std::set<std::string> json_pointers_set (json_pointers.begin (), json_pointers.end ());
87
+
88
+ for (auto s : json_pointers_set) {
89
+ this ->used_inputs [s] = false ;
90
+ }
91
+
92
+ get_prefixes (json_pointers_set);
93
+ }
94
+
95
+ std::string clean_string (std::string str) {
96
+ bool after_slash = false ;
97
+
98
+ for (size_t i = 0 ; i < str.size (); i++) {
99
+ if (str.at (i) == ' /' && i+1 < str.size ()) {
100
+ if (isdigit (str.at (i+1 ))) {
101
+ after_slash = true ;
102
+ str.erase (i, 1 );
103
+ i -= 1 ;
104
+ }
105
+ }
106
+ else if (isdigit (str.at (i)) && after_slash) {
107
+ str.erase (i, 1 );
108
+ i -= 1 ;
109
+ }
110
+ else {
111
+ after_slash = false ;
112
+ }
113
+ }
114
+
115
+ str.erase (0 , 1 );
116
+
117
+ return str;
118
+ }
119
+
120
+ std::string combine_str_vec (std::vector<std::string> vec) {
121
+ if (vec.size () == 0 ) return " " ;
122
+
123
+ std::string temp = vec[0 ];
124
+
125
+ for (size_t i = 1 ; i < vec.size (); i++) {
126
+ temp += " /" ;
127
+ temp += vec[i];
128
+ }
129
+
130
+ return temp;
131
+ }
132
+
133
+ void get_prefixes (std::set<std::string> json_pointers_set) {
134
+ std::string temp;
135
+ std::vector<std::string> temp_vec;
136
+
137
+ for (auto s : json_pointers_set) {
138
+ std::stringstream line (s);
139
+
140
+ while (getline (line, temp, ' /' )) {
141
+ temp_vec.push_back (temp);
142
+ }
143
+
144
+ if (temp_vec.size () > 1 ) {
145
+ temp_vec.pop_back ();
146
+
147
+ for (auto v : temp_vec) {
148
+ this ->prefixes .insert (v);
149
+ }
150
+ }
151
+
152
+ temp_vec.clear ();
153
+ }
154
+ }
155
+ };
0 commit comments