Merge "Report tests using Draw*BaseVertex as NotSupported" am: f96636fdfa
[platform/upstream/VK-GL-CTS.git] / framework / delibs / decpp / deCommandLine.hpp
1 #ifndef _DECOMMANDLINE_HPP
2 #define _DECOMMANDLINE_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements C++ Base Library
5  * -----------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Command line parser.
24  *//*--------------------------------------------------------------------*/
25
26 #include "deDefs.hpp"
27
28 #include <map>
29 #include <string>
30 #include <vector>
31 #include <ostream>
32 #include <typeinfo>
33 #include <stdexcept>
34
35 namespace de
36 {
37 namespace cmdline
38 {
39
40 //! Default parsing function
41 template<typename ValueType>
42 void parseType (const char* src, ValueType* dst);
43
44 template<typename T>
45 struct NamedValue
46 {
47         const char*     name;
48         T                       value;
49 };
50
51 template<typename OptName>
52 struct Option
53 {
54         typedef typename OptName::ValueType ValueType;
55         typedef void (*ParseFunc) (const char* src, ValueType* dst);
56
57         // \note All assumed to point to static memory.
58         const char*                                             shortName;
59         const char*                                             longName;
60         const char*                                             description;
61         const char*                                             defaultValue;           //!< Default value (parsed from string), or null if should not be set
62
63         // \note Either parse or namedValues must be null.
64         ParseFunc                                               parse;                          //!< Custom parsing function or null.
65         const NamedValue<ValueType>*    namedValues;            //!< Named values or null.
66         const NamedValue<ValueType>*    namedValuesEnd;         //!< Named value list end.
67
68         //! Construct generic option (string, int, boolean).
69         Option (const char* shortName_, const char* longName_, const char* description_, const char* defaultValue_ = DE_NULL)
70                 : shortName             (shortName_)
71                 , longName              (longName_)
72                 , description   (description_)
73                 , defaultValue  (defaultValue_)
74                 , parse                 (parseType<ValueType>)
75                 , namedValues   (DE_NULL)
76                 , namedValuesEnd(0)
77         {
78         }
79
80         //! Option with custom parsing function.
81         Option (const char* shortName_, const char* longName_, const char* description_, ParseFunc parse_, const char* defaultValue_ = DE_NULL)
82                 : shortName             (shortName_)
83                 , longName              (longName_)
84                 , description   (description_)
85                 , defaultValue  (defaultValue_)
86                 , parse                 (parse_)
87                 , namedValues   (DE_NULL)
88                 , namedValuesEnd(DE_NULL)
89         {
90         }
91
92         //! Option that uses named values.
93         Option (const char* shortName_, const char* longName_, const char* description_, const NamedValue<ValueType>* namedValues_, const NamedValue<ValueType>* namedValuesEnd_, const char* defaultValue_ = DE_NULL)
94                 : shortName             (shortName_)
95                 , longName              (longName_)
96                 , description   (description_)
97                 , defaultValue  (defaultValue_)
98                 , parse                 ((ParseFunc)DE_NULL)
99                 , namedValues   (namedValues_)
100                 , namedValuesEnd(namedValuesEnd_)
101         {
102         }
103
104         //! Option that uses named values.
105         template<size_t NumNamedValues>
106         Option (const char* shortName_, const char* longName_, const char* description_, const NamedValue<ValueType> (&namedValues_)[NumNamedValues], const char* defaultValue_ = DE_NULL)
107                 : shortName             (shortName_)
108                 , longName              (longName_)
109                 , description   (description_)
110                 , defaultValue  (defaultValue_)
111                 , parse                 ((ParseFunc)DE_NULL)
112                 , namedValues   (DE_ARRAY_BEGIN(namedValues_))
113                 , namedValuesEnd(DE_ARRAY_END(namedValues_))
114         {
115         }
116 };
117
118 template<class Option>
119 struct OptTraits
120 {
121         typedef typename Option::ValueType ValueType;
122 };
123
124 //! Default value lookup
125 template<typename ValueType>
126 inline void getTypeDefault (ValueType* dst)
127 {
128         *dst = ValueType();
129 }
130
131 template<> void getTypeDefault<bool> (bool* dst);
132
133 template<typename T>    inline bool isBoolean           (void) { return false;  }
134 template<>                              inline bool isBoolean<bool>     (void) { return true;   }
135
136 //! Is argument boolean-only value?
137 template<class Option>  inline bool isBooleanOpt        (void) { return isBoolean<typename OptTraits<Option>::ValueType>(); }
138
139 namespace detail
140 {
141
142 using std::string;
143 using std::vector;
144 using std::map;
145
146 // TypedFieldMap implementation
147
148 template<class Name>
149 struct TypedFieldTraits
150 {
151         // Generic implementation for cmdline.
152         typedef typename OptTraits<Name>::ValueType     ValueType;
153 };
154
155 template<class Value>
156 struct TypedFieldValueTraits
157 {
158         static void destroy (void* value) { delete (Value*)value; }
159 };
160
161 class TypedFieldMap
162 {
163 public:
164                                                 TypedFieldMap                   (void);
165                                                 ~TypedFieldMap                  (void);
166
167         bool                            empty                                   (void) const    { return m_fields.empty();      }
168         void                            clear                                   (void);
169
170         template<typename Name>
171         void                            set                                             (typename TypedFieldTraits<Name>::ValueType* value);
172
173         template<typename Name>
174         void                            set                                             (const typename TypedFieldTraits<Name>::ValueType& value);
175
176         template<typename Name>
177         bool                            contains                                (void) const;
178
179         template<typename Name>
180         const typename TypedFieldTraits<Name>::ValueType&
181                                                 get                                             (void) const;
182
183 private:
184                                                 TypedFieldMap                   (const TypedFieldMap&);
185         TypedFieldMap&          operator=                               (const TypedFieldMap&);
186
187         typedef void (*DestroyFunc) (void*);
188
189         struct Entry
190         {
191                 void*                   value;
192                 DestroyFunc             destructor;
193
194                 Entry (void) : value(DE_NULL), destructor(0) {}
195                 Entry (void* value_, DestroyFunc destructor_) : value(value_), destructor(destructor_) {}
196         };
197
198         typedef std::map<const std::type_info*, Entry> Map;
199
200         bool                            contains                                (const std::type_info* key) const;
201         const Entry&            get                                             (const std::type_info* key) const;
202         void                            set                                             (const std::type_info* key, const Entry& value);
203
204         Map                                     m_fields;
205 };
206
207 template<typename Name>
208 inline void TypedFieldMap::set (typename TypedFieldTraits<Name>::ValueType* value)
209 {
210         set(&typeid(Name), Entry(value, &TypedFieldValueTraits<typename TypedFieldTraits<Name>::ValueType>::destroy));
211 }
212
213 template<typename Name>
214 void TypedFieldMap::set (const typename TypedFieldTraits<Name>::ValueType& value)
215 {
216         typename TypedFieldTraits<Name>::ValueType* copy = new typename TypedFieldTraits<Name>::ValueType(value);
217
218         try
219         {
220                 set<Name>(copy);
221         }
222         catch (...)
223         {
224                 delete copy;
225                 throw;
226         }
227 }
228
229 template<typename Name>
230 inline bool TypedFieldMap::contains (void) const
231 {
232         return contains(&typeid(Name));
233 }
234
235 template<typename Name>
236 inline const typename TypedFieldTraits<Name>::ValueType& TypedFieldMap::get (void) const
237 {
238         return *static_cast<typename TypedFieldTraits<Name>::ValueType*>(get(&typeid(Name)).value);
239 }
240
241 class CommandLine;
242
243 typedef void (*GenericParseFunc) (const char* src, void* dst);
244
245 class Parser
246 {
247 public:
248                                         Parser                          (void);
249                                         ~Parser                         (void);
250
251         template<class OptType>
252         void                    addOption                       (const Option<OptType>& option);
253
254         bool                    parse                           (int numArgs, const char* const* args, CommandLine* dst, std::ostream& err) const;
255
256         void                    help                            (std::ostream& dst) const;
257
258 private:
259                                         Parser                          (const Parser&);
260         Parser&                 operator=                       (const Parser&);
261
262         struct OptInfo;
263
264         typedef void            (*DispatchParseFunc)            (const OptInfo* info, const char* src, TypedFieldMap* dst);
265         typedef void            (*SetDefaultFunc)                       (TypedFieldMap* dst);
266
267         struct OptInfo
268         {
269                 const char*                             shortName;
270                 const char*                             longName;
271                 const char*                             description;
272                 const char*                             defaultValue;
273                 bool                                    isFlag;                 //!< Set true for bool typed arguments that do not used named values.
274
275                 GenericParseFunc                parse;
276
277                 const void*                             namedValues;
278                 const void*                             namedValuesEnd;
279                 size_t                                  namedValueStride;
280
281                 DispatchParseFunc               dispatchParse;
282                 SetDefaultFunc                  setDefault;
283
284                 OptInfo (void)
285                         : shortName                     (DE_NULL)
286                         , longName                      (DE_NULL)
287                         , description           (DE_NULL)
288                         , defaultValue          (DE_NULL)
289                         , isFlag                        (false)
290                         , parse                         (DE_NULL)
291                         , namedValues           (DE_NULL)
292                         , namedValuesEnd        (DE_NULL)
293                         , namedValueStride      (0)
294                         , dispatchParse         (DE_NULL)
295                         , setDefault            (DE_NULL)
296                 {}
297         };
298
299         void                    addOption                       (const OptInfo& option);
300
301         template<typename OptName>
302         static void             dispatchParse           (const OptInfo* info, const char* src, TypedFieldMap* dst);
303
304         vector<OptInfo> m_options;
305 };
306
307 template<class OptType>
308 inline Parser& operator<< (Parser& parser, const Option<OptType>& option)
309 {
310         parser.addOption(option);
311         return parser;
312 }
313
314 //! Find match by name. Throws exception if no match is found.
315 const void* findNamedValueMatch (const char* src, const void* namedValues, const void* namedValuesEnd, size_t stride);
316
317 template<typename OptType>
318 void Parser::dispatchParse (const OptInfo* info, const char* src, TypedFieldMap* dst)
319 {
320         typename OptTraits<OptType>::ValueType* value = new typename OptTraits<OptType>::ValueType();
321         try
322         {
323                 DE_ASSERT((!!info->parse) != (!!info->namedValues));
324                 if (info->parse)
325                 {
326                         ((typename Option<OptType>::ParseFunc)(info->parse))(src, value);
327                 }
328                 else
329                 {
330                         const void* match = findNamedValueMatch(src, info->namedValues, info->namedValuesEnd, info->namedValueStride);
331                         *value = static_cast<const NamedValue<typename OptTraits<OptType>::ValueType>*>(match)->value;
332                 }
333                 dst->set<OptType>(value);
334         }
335         catch (...)
336         {
337                 delete value;
338                 throw;
339         }
340 }
341
342 template<typename OptType>
343 void dispatchSetDefault (TypedFieldMap* dst)
344 {
345         typename OptTraits<OptType>::ValueType* value = new typename OptTraits<OptType>::ValueType();
346         try
347         {
348                 getTypeDefault<typename OptTraits<OptType>::ValueType>(value);
349                 dst->set<OptType>(value);
350         }
351         catch (...)
352         {
353                 delete value;
354                 throw;
355         }
356 }
357
358 template<typename OptType>
359 const char* getNamedValueName (const void* value)
360 {
361         const NamedValue<typename OptTraits<OptType>::ValueType>* typedVal = static_cast<const NamedValue<typename OptTraits<OptType>::ValueType> >(value);
362         return typedVal->name;
363 }
364
365 template<typename OptType>
366 void setFromNamedValue (const void* value, TypedFieldMap* dst)
367 {
368         const NamedValue<typename OptTraits<OptType>::ValueType>* typedVal = static_cast<const NamedValue<typename OptTraits<OptType>::ValueType> >(value);
369         dst->set<OptType>(typedVal->value);
370 }
371
372 template<class OptType>
373 void Parser::addOption (const Option<OptType>& option)
374 {
375         OptInfo opt;
376
377         opt.shortName                   = option.shortName;
378         opt.longName                    = option.longName;
379         opt.description                 = option.description;
380         opt.defaultValue                = option.defaultValue;
381         opt.isFlag                              = isBooleanOpt<OptType>() && !option.namedValues;
382         opt.parse                               = (GenericParseFunc)option.parse;
383         opt.namedValues                 = (const void*)option.namedValues;
384         opt.namedValuesEnd              = (const void*)option.namedValuesEnd;
385         opt.namedValueStride    = sizeof(*option.namedValues);
386         opt.dispatchParse               = dispatchParse<OptType>;
387
388         if (opt.isFlag)
389                 opt.setDefault          = dispatchSetDefault<OptType>;
390
391         addOption(opt);
392 }
393
394 class CommandLine
395 {
396 public:
397                                                                 CommandLine             (void) {}
398                                                                 ~CommandLine    (void) {}
399
400         void                                            clear                   (void);
401
402         const TypedFieldMap&            getOptions              (void) const    { return m_options;     }
403         const vector<string>&           getArgs                 (void) const    { return m_args;        }
404
405         template<typename Option>
406         bool                                            hasOption               (void) const    { return m_options.contains<Option>();  }
407
408         template<typename Option>
409         const typename TypedFieldTraits<Option>::ValueType&
410                                                                 getOption               (void) const    { return m_options.get<Option>();               }
411
412 private:
413         TypedFieldMap                           m_options;
414         vector<string>                          m_args;
415
416         friend class Parser;
417 };
418
419 } // detail
420
421 using detail::Parser;
422 using detail::CommandLine;
423
424 void selfTest (void);
425
426 } // cmdline
427 } // de
428
429 #define DE_DECLARE_COMMAND_LINE_OPT(NAME, TYPE) struct NAME { typedef TYPE ValueType; }
430
431 #endif // _DECOMMANDLINE_HPP