5
5
#include " src/flags.h"
6
6
7
7
#include < cctype>
8
+ #include < cerrno>
8
9
#include < cstdlib>
9
10
#include < sstream>
10
11
@@ -39,6 +40,7 @@ struct Flag {
39
40
TYPE_INT,
40
41
TYPE_UINT,
41
42
TYPE_FLOAT,
43
+ TYPE_SIZE_T,
42
44
TYPE_STRING,
43
45
TYPE_ARGS
44
46
};
@@ -81,6 +83,11 @@ struct Flag {
81
83
return reinterpret_cast <double *>(valptr_);
82
84
}
83
85
86
+ size_t * size_t_variable () const {
87
+ DCHECK (type_ == TYPE_SIZE_T);
88
+ return reinterpret_cast <size_t *>(valptr_);
89
+ }
90
+
84
91
const char * string_value () const {
85
92
DCHECK (type_ == TYPE_STRING);
86
93
return *reinterpret_cast <const char **>(valptr_);
@@ -119,6 +126,11 @@ struct Flag {
119
126
return *reinterpret_cast <const double *>(defptr_);
120
127
}
121
128
129
+ size_t size_t_default () const {
130
+ DCHECK (type_ == TYPE_SIZE_T);
131
+ return *reinterpret_cast <const size_t *>(defptr_);
132
+ }
133
+
122
134
const char * string_default () const {
123
135
DCHECK (type_ == TYPE_STRING);
124
136
return *reinterpret_cast <const char * const *>(defptr_);
@@ -142,6 +154,8 @@ struct Flag {
142
154
return *uint_variable () == uint_default ();
143
155
case TYPE_FLOAT:
144
156
return *float_variable () == float_default ();
157
+ case TYPE_SIZE_T:
158
+ return *size_t_variable () == size_t_default ();
145
159
case TYPE_STRING: {
146
160
const char * str1 = string_value ();
147
161
const char * str2 = string_default ();
@@ -173,6 +187,9 @@ struct Flag {
173
187
case TYPE_FLOAT:
174
188
*float_variable () = float_default ();
175
189
break ;
190
+ case TYPE_SIZE_T:
191
+ *size_t_variable () = size_t_default ();
192
+ break ;
176
193
case TYPE_STRING:
177
194
set_string_value (string_default (), false );
178
195
break ;
@@ -201,6 +218,8 @@ static const char* Type2String(Flag::FlagType type) {
201
218
case Flag::TYPE_UINT:
202
219
return " uint" ;
203
220
case Flag::TYPE_FLOAT: return " float" ;
221
+ case Flag::TYPE_SIZE_T:
222
+ return " size_t" ;
204
223
case Flag::TYPE_STRING: return " string" ;
205
224
case Flag::TYPE_ARGS: return " arguments" ;
206
225
}
@@ -227,6 +246,9 @@ std::ostream& operator<<(std::ostream& os, const Flag& flag) { // NOLINT
227
246
case Flag::TYPE_FLOAT:
228
247
os << *flag.float_variable ();
229
248
break ;
249
+ case Flag::TYPE_SIZE_T:
250
+ os << *flag.size_t_variable ();
251
+ break ;
230
252
case Flag::TYPE_STRING: {
231
253
const char * str = flag.string_value ();
232
254
os << (str ? str : " nullptr" );
@@ -358,6 +380,27 @@ static Flag* FindFlag(const char* name) {
358
380
return nullptr ;
359
381
}
360
382
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
+ }
361
404
362
405
// static
363
406
int FlagList::SetFlagsFromCommandLine (int * argc,
@@ -422,27 +465,21 @@ int FlagList::SetFlagsFromCommandLine(int* argc,
422
465
case Flag::TYPE_INT:
423
466
*flag->int_variable () = static_cast <int >(strtol (value, &endp, 10 ));
424
467
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 ())) {
437
471
return_code = j;
438
- break ;
439
472
}
440
- *flag->uint_variable () = static_cast <unsigned int >(val);
441
473
break ;
442
- }
443
474
case Flag::TYPE_FLOAT:
444
475
*flag->float_variable () = strtod (value, &endp);
445
476
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 ;
446
483
case Flag::TYPE_STRING:
447
484
flag->set_string_value (value ? StrDup (value) : nullptr , true );
448
485
break ;
0 commit comments