55#include " src/flags.h"
66
77#include < cctype>
8+ #include < cerrno>
89#include < cstdlib>
910#include < sstream>
1011
@@ -39,6 +40,7 @@ struct Flag {
3940 TYPE_INT,
4041 TYPE_UINT,
4142 TYPE_FLOAT,
43+ TYPE_SIZE_T,
4244 TYPE_STRING,
4345 TYPE_ARGS
4446 };
@@ -81,6 +83,11 @@ struct Flag {
8183 return reinterpret_cast <double *>(valptr_);
8284 }
8385
86+ size_t * size_t_variable () const {
87+ DCHECK (type_ == TYPE_SIZE_T);
88+ return reinterpret_cast <size_t *>(valptr_);
89+ }
90+
8491 const char * string_value () const {
8592 DCHECK (type_ == TYPE_STRING);
8693 return *reinterpret_cast <const char **>(valptr_);
@@ -119,6 +126,11 @@ struct Flag {
119126 return *reinterpret_cast <const double *>(defptr_);
120127 }
121128
129+ size_t size_t_default () const {
130+ DCHECK (type_ == TYPE_SIZE_T);
131+ return *reinterpret_cast <const size_t *>(defptr_);
132+ }
133+
122134 const char * string_default () const {
123135 DCHECK (type_ == TYPE_STRING);
124136 return *reinterpret_cast <const char * const *>(defptr_);
@@ -142,6 +154,8 @@ struct Flag {
142154 return *uint_variable () == uint_default ();
143155 case TYPE_FLOAT:
144156 return *float_variable () == float_default ();
157+ case TYPE_SIZE_T:
158+ return *size_t_variable () == size_t_default ();
145159 case TYPE_STRING: {
146160 const char * str1 = string_value ();
147161 const char * str2 = string_default ();
@@ -173,6 +187,9 @@ struct Flag {
173187 case TYPE_FLOAT:
174188 *float_variable () = float_default ();
175189 break ;
190+ case TYPE_SIZE_T:
191+ *size_t_variable () = size_t_default ();
192+ break ;
176193 case TYPE_STRING:
177194 set_string_value (string_default (), false );
178195 break ;
@@ -201,6 +218,8 @@ static const char* Type2String(Flag::FlagType type) {
201218 case Flag::TYPE_UINT:
202219 return " uint" ;
203220 case Flag::TYPE_FLOAT: return " float" ;
221+ case Flag::TYPE_SIZE_T:
222+ return " size_t" ;
204223 case Flag::TYPE_STRING: return " string" ;
205224 case Flag::TYPE_ARGS: return " arguments" ;
206225 }
@@ -227,6 +246,9 @@ std::ostream& operator<<(std::ostream& os, const Flag& flag) { // NOLINT
227246 case Flag::TYPE_FLOAT:
228247 os << *flag.float_variable ();
229248 break ;
249+ case Flag::TYPE_SIZE_T:
250+ os << *flag.size_t_variable ();
251+ break ;
230252 case Flag::TYPE_STRING: {
231253 const char * str = flag.string_value ();
232254 os << (str ? str : " nullptr" );
@@ -358,6 +380,27 @@ static Flag* FindFlag(const char* name) {
358380 return nullptr ;
359381}
360382
383+ template <typename T>
384+ bool TryParseUnsigned (Flag* flag, const char * arg, const char * value,
385+ char ** endp, T* out_val) {
386+ // We do not use strtoul because it accepts negative numbers.
387+ // Rejects values >= 2**63 when T is 64 bits wide but that
388+ // seems like an acceptable trade-off.
389+ uint64_t max = static_cast <uint64_t >(std::numeric_limits<T>::max ());
390+ errno = 0 ;
391+ int64_t val = static_cast <int64_t >(strtoll (value, endp, 10 ));
392+ if (val < 0 || static_cast <uint64_t >(val) > max || errno != 0 ) {
393+ PrintF (stderr,
394+ " Error: Value for flag %s of type %s is out of bounds "
395+ " [0-%" PRIu64
396+ " ]\n "
397+ " Try --help for options\n " ,
398+ arg, Type2String (flag->type ()), max);
399+ return false ;
400+ }
401+ *out_val = static_cast <T>(val);
402+ return true ;
403+ }
361404
362405// static
363406int FlagList::SetFlagsFromCommandLine (int * argc,
@@ -422,27 +465,21 @@ int FlagList::SetFlagsFromCommandLine(int* argc,
422465 case Flag::TYPE_INT:
423466 *flag->int_variable () = static_cast <int >(strtol (value, &endp, 10 ));
424467 break ;
425- case Flag::TYPE_UINT: {
426- // We do not use strtoul because it accepts negative numbers.
427- int64_t val = static_cast <int64_t >(strtoll (value, &endp, 10 ));
428- if (val < 0 || val > std::numeric_limits<unsigned int >::max ()) {
429- PrintF (stderr,
430- " Error: Value for flag %s of type %s is out of bounds "
431- " [0-%" PRIu64
432- " ]\n "
433- " Try --help for options\n " ,
434- arg, Type2String (flag->type ()),
435- static_cast <uint64_t >(
436- std::numeric_limits<unsigned int >::max ()));
468+ case Flag::TYPE_UINT:
469+ if (!TryParseUnsigned (flag, arg, value, &endp,
470+ flag->uint_variable ())) {
437471 return_code = j;
438- break ;
439472 }
440- *flag->uint_variable () = static_cast <unsigned int >(val);
441473 break ;
442- }
443474 case Flag::TYPE_FLOAT:
444475 *flag->float_variable () = strtod (value, &endp);
445476 break ;
477+ case Flag::TYPE_SIZE_T:
478+ if (!TryParseUnsigned (flag, arg, value, &endp,
479+ flag->size_t_variable ())) {
480+ return_code = j;
481+ }
482+ break ;
446483 case Flag::TYPE_STRING:
447484 flag->set_string_value (value ? StrDup (value) : nullptr , true );
448485 break ;
0 commit comments