1 #ifndef _DECOMMANDLINE_HPP
2 #define _DECOMMANDLINE_HPP
3 /*-------------------------------------------------------------------------
4 * drawElements C++ Base Library
5 * -----------------------------
7 * Copyright 2014 The Android Open Source Project
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * \brief Command line parser.
24 *//*--------------------------------------------------------------------*/
40 //! Default parsing function
41 template<typename ValueType>
42 void parseType (const char* src, ValueType* dst);
51 template<typename OptName>
54 typedef typename OptName::ValueType ValueType;
55 typedef void (*ParseFunc) (const char* src, ValueType* dst);
57 // \note All assumed to point to static memory.
58 const char* shortName;
60 const char* description;
61 const char* defaultValue; //!< Default value (parsed from string), or null if should not be set
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.
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)
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_)
87 , namedValues (DE_NULL)
88 , namedValuesEnd(DE_NULL)
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_)
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_))
118 template<class Option>
121 typedef typename Option::ValueType ValueType;
124 //! Default value lookup
125 template<typename ValueType>
126 inline void getTypeDefault (ValueType* dst)
131 template<> void getTypeDefault<bool> (bool* dst);
133 template<typename T> inline bool isBoolean (void) { return false; }
134 template<> inline bool isBoolean<bool> (void) { return true; }
136 //! Is argument boolean-only value?
137 template<class Option> inline bool isBooleanOpt (void) { return isBoolean<typename OptTraits<Option>::ValueType>(); }
146 // TypedFieldMap implementation
149 struct TypedFieldTraits
151 // Generic implementation for cmdline.
152 typedef typename OptTraits<Name>::ValueType ValueType;
155 template<class Value>
156 struct TypedFieldValueTraits
158 static void destroy (void* value) { delete (Value*)value; }
164 TypedFieldMap (void);
165 ~TypedFieldMap (void);
167 bool empty (void) const { return m_fields.empty(); }
170 template<typename Name>
171 void set (typename TypedFieldTraits<Name>::ValueType* value);
173 template<typename Name>
174 void set (const typename TypedFieldTraits<Name>::ValueType& value);
176 template<typename Name>
177 bool contains (void) const;
179 template<typename Name>
180 const typename TypedFieldTraits<Name>::ValueType&
184 TypedFieldMap (const TypedFieldMap&);
185 TypedFieldMap& operator= (const TypedFieldMap&);
187 typedef void (*DestroyFunc) (void*);
192 DestroyFunc destructor;
194 Entry (void) : value(DE_NULL), destructor(0) {}
195 Entry (void* value_, DestroyFunc destructor_) : value(value_), destructor(destructor_) {}
198 typedef std::map<const std::type_info*, Entry> Map;
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);
207 template<typename Name>
208 inline void TypedFieldMap::set (typename TypedFieldTraits<Name>::ValueType* value)
210 set(&typeid(Name), Entry(value, &TypedFieldValueTraits<typename TypedFieldTraits<Name>::ValueType>::destroy));
213 template<typename Name>
214 void TypedFieldMap::set (const typename TypedFieldTraits<Name>::ValueType& value)
216 typename TypedFieldTraits<Name>::ValueType* copy = new typename TypedFieldTraits<Name>::ValueType(value);
229 template<typename Name>
230 inline bool TypedFieldMap::contains (void) const
232 return contains(&typeid(Name));
235 template<typename Name>
236 inline const typename TypedFieldTraits<Name>::ValueType& TypedFieldMap::get (void) const
238 return *static_cast<typename TypedFieldTraits<Name>::ValueType*>(get(&typeid(Name)).value);
243 typedef void (*GenericParseFunc) (const char* src, void* dst);
251 template<class OptType>
252 void addOption (const Option<OptType>& option);
254 bool parse (int numArgs, const char* const* args, CommandLine* dst, std::ostream& err) const;
256 void help (std::ostream& dst) const;
259 Parser (const Parser&);
260 Parser& operator= (const Parser&);
264 typedef void (*DispatchParseFunc) (const OptInfo* info, const char* src, TypedFieldMap* dst);
265 typedef void (*SetDefaultFunc) (TypedFieldMap* dst);
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.
275 GenericParseFunc parse;
277 const void* namedValues;
278 const void* namedValuesEnd;
279 size_t namedValueStride;
281 DispatchParseFunc dispatchParse;
282 SetDefaultFunc setDefault;
285 : shortName (DE_NULL)
287 , description (DE_NULL)
288 , defaultValue (DE_NULL)
291 , namedValues (DE_NULL)
292 , namedValuesEnd (DE_NULL)
293 , namedValueStride (0)
294 , dispatchParse (DE_NULL)
295 , setDefault (DE_NULL)
299 void addOption (const OptInfo& option);
301 template<typename OptName>
302 static void dispatchParse (const OptInfo* info, const char* src, TypedFieldMap* dst);
304 vector<OptInfo> m_options;
307 template<class OptType>
308 inline Parser& operator<< (Parser& parser, const Option<OptType>& option)
310 parser.addOption(option);
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);
317 template<typename OptType>
318 void Parser::dispatchParse (const OptInfo* info, const char* src, TypedFieldMap* dst)
320 typename OptTraits<OptType>::ValueType* value = new typename OptTraits<OptType>::ValueType();
323 DE_ASSERT((!!info->parse) != (!!info->namedValues));
326 ((typename Option<OptType>::ParseFunc)(info->parse))(src, value);
330 const void* match = findNamedValueMatch(src, info->namedValues, info->namedValuesEnd, info->namedValueStride);
331 *value = static_cast<const NamedValue<typename OptTraits<OptType>::ValueType>*>(match)->value;
333 dst->set<OptType>(value);
342 template<typename OptType>
343 void dispatchSetDefault (TypedFieldMap* dst)
345 typename OptTraits<OptType>::ValueType* value = new typename OptTraits<OptType>::ValueType();
348 getTypeDefault<typename OptTraits<OptType>::ValueType>(value);
349 dst->set<OptType>(value);
358 template<typename OptType>
359 const char* getNamedValueName (const void* value)
361 const NamedValue<typename OptTraits<OptType>::ValueType>* typedVal = static_cast<const NamedValue<typename OptTraits<OptType>::ValueType> >(value);
362 return typedVal->name;
365 template<typename OptType>
366 void setFromNamedValue (const void* value, TypedFieldMap* dst)
368 const NamedValue<typename OptTraits<OptType>::ValueType>* typedVal = static_cast<const NamedValue<typename OptTraits<OptType>::ValueType> >(value);
369 dst->set<OptType>(typedVal->value);
372 template<class OptType>
373 void Parser::addOption (const Option<OptType>& option)
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>;
389 opt.setDefault = dispatchSetDefault<OptType>;
397 CommandLine (void) {}
398 ~CommandLine (void) {}
402 const TypedFieldMap& getOptions (void) const { return m_options; }
403 const vector<string>& getArgs (void) const { return m_args; }
405 template<typename Option>
406 bool hasOption (void) const { return m_options.contains<Option>(); }
408 template<typename Option>
409 const typename TypedFieldTraits<Option>::ValueType&
410 getOption (void) const { return m_options.get<Option>(); }
413 TypedFieldMap m_options;
414 vector<string> m_args;
421 using detail::Parser;
422 using detail::CommandLine;
424 void selfTest (void);
429 #define DE_DECLARE_COMMAND_LINE_OPT(NAME, TYPE) struct NAME { typedef TYPE ValueType; }
431 #endif // _DECOMMANDLINE_HPP