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