1212#include < iostream>
1313#include < set>
1414#include < type_traits>
15+ #include < array>
1516
16- #define BINDING_PAIR (T, field ) {#field, &T::field}
17- #define BINDING_TYPE (T, field ) decltype (T::field)
17+ // #define BINDING_PAIR(T, field) {#field, &T::field}
18+ // #define BINDING_TYPE(T, field) decltype(T::field)
1819
19- // Recursive expansion
20- #define EXPAND_BINDING_PAIRS_1 (T, f1 ) \
21- BINDING_PAIR (T, f1)
20+ // // Recursive expansion
21+ // #define EXPAND_BINDING_PAIRS_1(T, f1) \
22+ // BINDING_PAIR(T, f1)
2223
23- #define EXPAND_BINDING_PAIRS_2 (T, f1, ...) \
24- BINDING_PAIR (T, f1), EXPAND_BINDING_PAIRS_1(T, __VA_ARGS__)
24+ // #define EXPAND_BINDING_PAIRS_2(T, f1, ...) \
25+ // BINDING_PAIR(T, f1), EXPAND_BINDING_PAIRS_1(T, __VA_ARGS__)
2526
26- #define EXPAND_BINDING_PAIRS_3 (T, f1, ...) \
27- BINDING_PAIR (T, f1), EXPAND_BINDING_PAIRS_2(T, __VA_ARGS__)
27+ // #define EXPAND_BINDING_PAIRS_3(T, f1, ...) \
28+ // BINDING_PAIR(T, f1), EXPAND_BINDING_PAIRS_2(T, __VA_ARGS__)
2829
29- #define EXPAND_BINDING_PAIRS_4 (T, f1, ...) \
30- BINDING_PAIR (T, f1), EXPAND_BINDING_PAIRS_3(T, __VA_ARGS__)
30+ // #define EXPAND_BINDING_PAIRS_4(T, f1, ...) \
31+ // BINDING_PAIR(T, f1), EXPAND_BINDING_PAIRS_3(T, __VA_ARGS__)
3132
32- #define EXPAND_BINDING_PAIRS_5 (T, f1, ...) \
33- BINDING_PAIR (T, f1), EXPAND_BINDING_PAIRS_4(T, __VA_ARGS__)
33+ // #define EXPAND_BINDING_PAIRS_5(T, f1, ...) \
34+ // BINDING_PAIR(T, f1), EXPAND_BINDING_PAIRS_4(T, __VA_ARGS__)
3435
35- #define GET_MACRO (_1,_2,_3,_4,_5,NAME ,...) NAME
36- #define MAKE_BINDING_PAIRS (T, ...) \
37- GET_MACRO (__VA_ARGS__, EXPAND_BINDING_PAIRS_5 , EXPAND_BINDING_PAIRS_4 , EXPAND_BINDING_PAIRS_3 , EXPAND_BINDING_PAIRS_2 , EXPAND_BINDING_PAIRS_1 )(T, __VA_ARGS__)
36+ // #define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
37+ // #define MAKE_BINDING_PAIRS(T, ...) \
38+ // GET_MACRO(__VA_ARGS__, EXPAND_BINDING_PAIRS_5, EXPAND_BINDING_PAIRS_4, EXPAND_BINDING_PAIRS_3, EXPAND_BINDING_PAIRS_2, EXPAND_BINDING_PAIRS_1)(T, __VA_ARGS__)
3839
39- #define EXPAND_BINDING_TYPES_1 (T, f1 ) \
40- BINDING_TYPE (T, f1)
40+ // #define EXPAND_BINDING_TYPES_1(T, f1) \
41+ // BINDING_TYPE(T, f1)
4142
42- #define EXPAND_BINDING_TYPES_2 (T, f1, ...) \
43- BINDING_TYPE (T, f1), EXPAND_BINDING_TYPES_1(T, __VA_ARGS__)
43+ // #define EXPAND_BINDING_TYPES_2(T, f1, ...) \
44+ // BINDING_TYPE(T, f1), EXPAND_BINDING_TYPES_1(T, __VA_ARGS__)
4445
45- #define EXPAND_BINDING_TYPES_3 (T, f1, ...) \
46- BINDING_TYPE (T, f1), EXPAND_BINDING_TYPES_2(T, __VA_ARGS__)
46+ // #define EXPAND_BINDING_TYPES_3(T, f1, ...) \
47+ // BINDING_TYPE(T, f1), EXPAND_BINDING_TYPES_2(T, __VA_ARGS__)
4748
48- #define EXPAND_BINDING_TYPES_4 (T, f1, ...) \
49- BINDING_TYPE (T, f1), EXPAND_BINDING_TYPES_3(T, __VA_ARGS__)
49+ // #define EXPAND_BINDING_TYPES_4(T, f1, ...) \
50+ // BINDING_TYPE(T, f1), EXPAND_BINDING_TYPES_3(T, __VA_ARGS__)
5051
51- #define EXPAND_BINDING_TYPES_5 (T, f1, ...) \
52- BINDING_TYPE (T, f1), EXPAND_BINDING_TYPES_4(T, __VA_ARGS__)
52+ // #define EXPAND_BINDING_TYPES_5(T, f1, ...) \
53+ // BINDING_TYPE(T, f1), EXPAND_BINDING_TYPES_4(T, __VA_ARGS__)
5354
54- #define MAKE_BINDING_TYPES (T, ...) \
55- GET_MACRO (__VA_ARGS__, EXPAND_BINDING_TYPES_5 , EXPAND_BINDING_TYPES_4 , EXPAND_BINDING_TYPES_3 , EXPAND_BINDING_TYPES_2 , EXPAND_BINDING_TYPES_1 )(T, __VA_ARGS__)
55+ // #define MAKE_BINDING_TYPES(T, ...) \
56+ // GET_MACRO(__VA_ARGS__, EXPAND_BINDING_TYPES_5, EXPAND_BINDING_TYPES_4, EXPAND_BINDING_TYPES_3, EXPAND_BINDING_TYPES_2, EXPAND_BINDING_TYPES_1)(T, __VA_ARGS__)
5657
57- #define DEFINE_BINDINGS (procedure_name, ...) \
58- template <> \
59- Bindings<Audit##procedure_name##Params, MAKE_BINDING_TYPES (Audit##procedure_name##Params, __VA_ARGS__)> GetBindings<Audit##procedure_name##Params, MAKE_BINDING_TYPES (procedure_name, __VA_ARGS__)>() { \
60- return Bindings<Audit##procedure_name##Params, MAKE_BINDING_TYPES (Audit##procedure_name##Params, __VA_ARGS__)>{ \
61- MAKE_BINDING_PAIRS (Audit##procedure_name##Params, __VA_ARGS__) \
62- }; \
63- }
58+ // #define DEFINE_BINDINGS(procedure_name, ...) \
59+ // template<> \
60+ // Bindings<Audit##procedure_name##Params, MAKE_BINDING_TYPES(Audit##procedure_name##Params, __VA_ARGS__)> GetBindings<Audit##procedure_name##Params, MAKE_BINDING_TYPES(procedure_name, __VA_ARGS__)>() { \
61+ // return Bindings<Audit##procedure_name##Params, MAKE_BINDING_TYPES(Audit##procedure_name##Params, __VA_ARGS__)>{ \
62+ // MAKE_BINDING_PAIRS(Audit##procedure_name##Params, __VA_ARGS__) \
63+ // }; \
64+ // }
6465
65- #define DEFINE_AUDIT_HANDLER (procedure_name ) \
66- Result<Status> Audit##procedure_name##Handler(/* const*/ ParameterMap/* &*/ args, IndicatorsTree& indicators, ContextInterface& context) \
67- { \
68- auto params = ParseArguments<Audit##procedure_name##Params>(args); \
69- if (!params.HasValue ()) \
70- { \
71- return params.Error (); \
72- } \
73- return Audit##procedure_name (params.Value (), indicators, context); \
74- }
66+ // #define DEFINE_AUDIT_HANDLER(procedure_name) \
67+ // Result<Status> Audit##procedure_name##Handler(/*const*/ ParameterMap /*&*/ args, IndicatorsTree& indicators, ContextInterface& context) \
68+ // { \
69+ // auto params = ParseArguments<Audit##procedure_name##Params>(args); \
70+ // if (!params.HasValue()) \
71+ // { \
72+ // return params.Error(); \
73+ // } \
74+ // return Audit##procedure_name(params.Value(), indicators, context); \
75+ // }
7576
76- #define DEFINE_GETBINDINGS_SPECIALIZATION (T, ...) \
77- template <> \
78- Bindings<T, TYPES > GetBindings<T, TYPES >() { \
79- return Bindings<T, TYPES >{ \
80- __VA_ARGS__ \
81- }; \
82- }
77+ // #define DEFINE_GETBINDINGS_SPECIALIZATION(T, ...) \
78+ // template<> \
79+ // Bindings<T, TYPES> GetBindings<T, TYPES>() { \
80+ // return Bindings<T, TYPES>{ \
81+ // __VA_ARGS__ \
82+ // }; \
83+ // }
8384
8485namespace ComplianceEngine
8586{
@@ -187,100 +188,112 @@ inline Optional<Error> ParseValue(const std::map<std::string, std::string>& args
187188 return Optional<Error>();
188189}
189190
190- template <typename T, typename ... Args>
191- struct Bindings ;
192-
193- // Primary template for zero arguments
194- template <typename T>
195- struct Bindings <T>
191+ // template <typename T, typename... Args>
192+ // struct Bindings;
193+
194+ // // Primary template for zero arguments
195+ // template <typename T>
196+ // struct Bindings<T>
197+ // {
198+ // // Empty specialization for no parameters
199+ // Optional<Error> ParseArguments(T& result, const std::map<std::string, std::string>& args) const
200+ // {
201+ // UNUSED(result);
202+ // UNUSED(args);
203+ // return Optional<Error>();
204+ // }
205+ // static constexpr std::size_t Size()
206+ // {
207+ // return 0;
208+ // }
209+ // Bindings() = default;
210+ // std::set<std::string> GetFieldNames() const
211+ // {
212+ // return std::set<std::string>();
213+ // }
214+ // };
215+
216+ // // Partial specialization for one or more arguments
217+ // template <typename T, typename Arg1, typename... Args>
218+ // struct Bindings<T, Arg1, Args...>
219+ // {
220+ // std::string name;
221+ // Arg1 T::* member;
222+ // Bindings<T, Args...> other;
223+
224+ // Bindings(std::pair<const char*, Arg1 T::*> arg1, std::pair<const char*, Args T::*>... otherArgs)
225+ // : name{arg1.first},
226+ // member{arg1.second},
227+ // other{otherArgs...}
228+ // {
229+ // }
230+
231+ // Optional<Error> ParseArguments(T& result, const std::map<std::string, std::string>& args) const
232+ // {
233+ // std::cerr << "[" << __func__ << ":" << __LINE__ << "] "
234+ // << "field: '" << name << "'" << std::endl;
235+ // auto error = ParseValue(args, name, result.*member);
236+ // if (error.HasValue())
237+ // {
238+ // return error.Value();
239+ // }
240+
241+ // // Recurse to the rest of the arguments
242+ // error = other.ParseArguments(result, args);
243+ // if (error.HasValue())
244+ // {
245+ // return error.Value();
246+ // }
247+
248+ // // No error
249+ // return Optional<Error>();
250+ // }
251+
252+ // static constexpr std::size_t Size()
253+ // {
254+ // return 1 + Bindings<T, Args...>::Size();
255+ // }
256+
257+ // std::set<std::string> GetFieldNames() const
258+ // {
259+ // auto otherNames = other.GetFieldNames();
260+ // otherNames.insert(name);
261+ // return otherNames;
262+ // }
263+ // };
264+
265+ // Each procedure provides specialization for this structure
266+ template <typename Params>
267+ struct Bindings
196268{
197- // Empty specialization for no parameters
198- Optional<Error> ParseArguments (T& result, const std::map<std::string, std::string>& args) const
199- {
200- UNUSED (result);
201- UNUSED (args);
202- return Optional<Error>();
203- }
204- static constexpr std::size_t Size ()
205- {
206- return 0 ;
207- }
208- Bindings () = default ;
209- std::set<std::string> GetFieldNames () const
210- {
211- return std::set<std::string>();
212- }
269+ static constexpr const size_t size = 0 ;
270+ static constexpr const char * names[] = {};
271+ static constexpr const std::tuple<> members = {};
213272};
214273
215- // Partial specialization for one or more arguments
216- template <typename T, typename Arg1, typename ... Args>
217- struct Bindings <T, Arg1, Args...>
274+ template <typename Params>
275+ std::set<std::string> GetFieldNames ()
218276{
219- std::string name;
220- Arg1 T::* member;
221- Bindings<T, Args...> other;
222-
223- Bindings (std::pair<const char *, Arg1 T::*> arg1, std::pair<const char *, Args T::*>... otherArgs)
224- : name{arg1.first },
225- member{arg1.second },
226- other{otherArgs...}
227- {
228- }
229-
230- Optional<Error> ParseArguments (T& result, const std::map<std::string, std::string>& args) const
231- {
232- std::cerr << " [" << __func__ << " :" << __LINE__ << " ] "
233- << " field: '" << name << " '" << std::endl;
234- auto error = ParseValue (args, name, result.*member);
235- if (error.HasValue ())
236- {
237- return error.Value ();
238- }
239-
240- // Recurse to the rest of the arguments
241- error = other.ParseArguments (result, args);
242- if (error.HasValue ())
243- {
244- return error.Value ();
245- }
246-
247- // No error
248- return Optional<Error>();
249- }
250-
251- static constexpr std::size_t Size ()
252- {
253- return 1 + Bindings<T, Args...>::Size ();
254- }
255-
256- std::set<std::string> GetFieldNames () const
257- {
258- auto otherNames = other.GetFieldNames ();
259- otherNames.insert (name);
260- return otherNames;
261- }
262- };
263-
264- // Each procedure should have its own set of bindings, see ProcedureMap.h/cpp for specializations
265- template <typename Params, typename ...Args>
266- Bindings<Params, Args...> GetBindings ();
277+ static const auto names = Bindings<Params>::names;
278+ return std::set<std::string>(names, names + Bindings<Params>::size);
279+ }
267280
268- template <typename T, typename ... Args >
281+ template <typename T>
269282Result<T> ParseArguments (const std::map<std::string, std::string>& args)
270283{
271284 static_assert (std::is_default_constructible<T>::value, " The parameters structure must be default constructible" );
272285 // static_assert(HasBindings<T>::value, "The parameters structure must provide a GetBinding() static method");
273286
274287 // Static as the bindings are immutable and we don't need to recreate them all the time
275- static const auto bindings = GetBindings <T>();
288+ static const auto bindings = Bindings <T>();
276289
277290 // Find arguments that are unsupported
278- if (bindings.Size () < args.size ())
291+ if (bindings.size < args.size ())
279292 {
280293 return Error (" Too many arguments provided" , EINVAL );
281294 }
282295
283- static const auto fields = bindings. GetFieldNames ();
296+ static const auto fields = GetFieldNames<T> ();
284297 for (const auto & arg : args)
285298 {
286299 if (fields.end () == fields.find (arg.first ))
@@ -291,13 +304,23 @@ Result<T> ParseArguments(const std::map<std::string, std::string>& args)
291304
292305 // T must be default constructible for this feature to work
293306 T result;
294- // Recursively consume arguments
295- auto error = bindings.ParseArguments (result, args);
296- if (error.HasValue ())
307+ for (std::size_t i = 0 ; i < bindings.size ; ++i)
297308 {
298- return error.Value ();
309+ const std::string name = bindings.names [i];
310+ auto error = ParseValue (args, name, result.*bindings.members [i]);
311+ if (error.HasValue ())
312+ {
313+ return error.Value ();
314+ }
299315 }
300316
317+ // Recursively consume arguments
318+ // auto error = bindings.ParseArguments(result, args);
319+ // if (error.HasValue())
320+ // {
321+ // return error.Value();
322+ // }
323+
301324 return result;
302325}
303326
@@ -312,7 +335,7 @@ struct ProcedureHandler
312335
313336 Result<Status> operator ()(const std::map<std::string, std::string>& args, IndicatorsTree& indicators, ContextInterface& context) const
314337 {
315- auto params = ParseArguments<Params>(args, GetBindings<Params>() );
338+ auto params = ParseArguments<Params>(args);
316339 if (!params.HasValue ())
317340 {
318341 return params.Error ();
0 commit comments