mirror of
https://github.com/gflags/gflags.git
synced 2025-04-05 05:25:04 +00:00
Use enum to specify flag value type.
This commit is contained in:
parent
fe57e5af4d
commit
7b43ae0f40
3 changed files with 92 additions and 34 deletions
|
@ -191,7 +191,7 @@ static void ReportError(DieWhenReporting should_die, const char* format, ...) {
|
|||
class CommandLineFlag;
|
||||
class FlagValue {
|
||||
public:
|
||||
FlagValue(void* valbuf, const char* type, bool transfer_ownership_of_value);
|
||||
FlagValue(void* valbuf, FlagValueType type, bool transfer_ownership_of_value);
|
||||
~FlagValue();
|
||||
|
||||
bool ParseFrom(const char* spec);
|
||||
|
@ -201,7 +201,7 @@ class FlagValue {
|
|||
friend class CommandLineFlag; // for many things, including Validate()
|
||||
friend class GFLAGS_NAMESPACE::FlagSaverImpl; // calls New()
|
||||
friend class FlagRegistry; // checks value_buffer_ for flags_by_ptr_ map
|
||||
template <typename T> friend T GetFromEnv(const char*, const char*, T);
|
||||
template <typename T> friend T GetFromEnv(const char*, T);
|
||||
friend bool TryParseLocked(const CommandLineFlag*, FlagValue*,
|
||||
const char*, string*); // for New(), CopyFrom()
|
||||
|
||||
|
@ -215,6 +215,11 @@ class FlagValue {
|
|||
FV_STRING = 6,
|
||||
FV_MAX_INDEX = 6,
|
||||
};
|
||||
|
||||
friend ValueType FromFlagValueType(FlagValueType flag_type);
|
||||
|
||||
FlagValue(void* valbuf, ValueType type, bool transfer_ownership_of_value);
|
||||
|
||||
const char* TypeName() const;
|
||||
bool Equal(const FlagValue& x) const;
|
||||
FlagValue* New() const; // creates a new one with default value
|
||||
|
@ -228,13 +233,19 @@ class FlagValue {
|
|||
bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const;
|
||||
|
||||
void* value_buffer_; // points to the buffer holding our data
|
||||
int8 type_; // how to interpret value_
|
||||
const int8 type_; // how to interpret value_
|
||||
bool owns_value_; // whether to free value on destruct
|
||||
|
||||
FlagValue(const FlagValue&); // no copying!
|
||||
void operator=(const FlagValue&);
|
||||
};
|
||||
|
||||
inline FlagValue::ValueType FromFlagValueType(FlagValueType flag_type) {
|
||||
COMPILE_ASSERT((int)FVT_MAX_INDEX == (int)FlagValue::FV_MAX_INDEX,
|
||||
FlagValueType_enum_is_out_of_sync_with_ValueType_enum);
|
||||
return static_cast<FlagValue::ValueType>(flag_type);
|
||||
}
|
||||
|
||||
|
||||
// This could be a templated method of FlagValue, but doing so adds to the
|
||||
// size of the .o. Since there's no type-safety here anyway, macro is ok.
|
||||
|
@ -242,18 +253,21 @@ class FlagValue {
|
|||
#define OTHER_VALUE_AS(fv, type) *reinterpret_cast<type*>(fv.value_buffer_)
|
||||
#define SET_VALUE_AS(type, value) VALUE_AS(type) = (value)
|
||||
|
||||
FlagValue::FlagValue(void* valbuf, const char* type,
|
||||
FlagValue::FlagValue(void* valbuf, FlagValueType type,
|
||||
bool transfer_ownership_of_value)
|
||||
: value_buffer_(valbuf),
|
||||
type_(FromFlagValueType(type)),
|
||||
owns_value_(transfer_ownership_of_value) {
|
||||
for (type_ = 0; type_ <= FV_MAX_INDEX; ++type_) {
|
||||
if (!strcmp(type, TypeName())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(type_ <= FV_MAX_INDEX); // Unknown typename
|
||||
}
|
||||
|
||||
FlagValue::FlagValue(void* valbuf, FlagValue::ValueType type,
|
||||
bool transfer_ownership_of_value)
|
||||
: value_buffer_(valbuf),
|
||||
type_(type),
|
||||
owns_value_(transfer_ownership_of_value) {
|
||||
}
|
||||
|
||||
FlagValue::~FlagValue() {
|
||||
if (!owns_value_) {
|
||||
return;
|
||||
|
@ -438,7 +452,7 @@ bool FlagValue::Equal(const FlagValue& x) const {
|
|||
}
|
||||
|
||||
FlagValue* FlagValue::New() const {
|
||||
const char *type = TypeName();
|
||||
const ValueType type = static_cast<ValueType>(type_);
|
||||
switch (type_) {
|
||||
case FV_BOOL: return new FlagValue(new bool(false), type, true);
|
||||
case FV_INT32: return new FlagValue(new int32(0), type, true);
|
||||
|
@ -1163,8 +1177,8 @@ string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
|
|||
}
|
||||
|
||||
const string envname = string("FLAGS_") + string(flagname);
|
||||
string envval;
|
||||
if (!SafeGetEnv(envname.c_str(), envval)) {
|
||||
string envval;
|
||||
if (!SafeGetEnv(envname.c_str(), envval)) {
|
||||
if (errors_are_fatal) {
|
||||
error_flags_[flagname] = (string(kError) + envname +
|
||||
" not found in environment\n");
|
||||
|
@ -1362,14 +1376,14 @@ string CommandLineFlagParser::ProcessOptionsFromStringLocked(
|
|||
// --------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
T GetFromEnv(const char *varname, const char* type, T dflt) {
|
||||
T GetFromEnv(const char *varname, T dflt) {
|
||||
std::string valstr;
|
||||
if (SafeGetEnv(varname, valstr)) {
|
||||
FlagValue ifv(new T, type, true);
|
||||
FlagValue ifv(new T, FlagTraits<T>::Type(), true);
|
||||
if (!ifv.ParseFrom(valstr.c_str())) {
|
||||
ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n",
|
||||
varname, valstr.c_str());
|
||||
}
|
||||
}
|
||||
return OTHER_VALUE_AS(ifv, T);
|
||||
} else return dflt;
|
||||
}
|
||||
|
@ -1416,15 +1430,12 @@ bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) {
|
|||
// values in a global destructor.
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
FlagRegisterer::FlagRegisterer(const char* name, const char* type,
|
||||
FlagRegisterer::FlagRegisterer(const char* name, FlagValueType type,
|
||||
const char* help, const char* filename,
|
||||
void* current_storage, void* defvalue_storage) {
|
||||
if (help == NULL)
|
||||
help = "";
|
||||
// FlagValue expects the type-name to not include any namespace
|
||||
// components, so we get rid of those, if any.
|
||||
if (strchr(type, ':'))
|
||||
type = strrchr(type, ':') + 1;
|
||||
|
||||
FlagValue* current = new FlagValue(current_storage, type, false);
|
||||
FlagValue* defvalue = new FlagValue(defvalue_storage, type, false);
|
||||
// Importantly, flag_ will never be deleted, so storage is always good.
|
||||
|
@ -1820,22 +1831,22 @@ bool ReadFromFlagsFile(const string& filename, const char* prog_name,
|
|||
// --------------------------------------------------------------------
|
||||
|
||||
bool BoolFromEnv(const char *v, bool dflt) {
|
||||
return GetFromEnv(v, "bool", dflt);
|
||||
return GetFromEnv(v, dflt);
|
||||
}
|
||||
int32 Int32FromEnv(const char *v, int32 dflt) {
|
||||
return GetFromEnv(v, "int32", dflt);
|
||||
return GetFromEnv(v, dflt);
|
||||
}
|
||||
uint32 Uint32FromEnv(const char *v, uint32 dflt) {
|
||||
return GetFromEnv(v, "uint32", dflt);
|
||||
return GetFromEnv(v, dflt);
|
||||
}
|
||||
int64 Int64FromEnv(const char *v, int64 dflt) {
|
||||
return GetFromEnv(v, "int64", dflt);
|
||||
return GetFromEnv(v, dflt);
|
||||
}
|
||||
uint64 Uint64FromEnv(const char *v, uint64 dflt) {
|
||||
return GetFromEnv(v, "uint64", dflt);
|
||||
return GetFromEnv(v, dflt);
|
||||
}
|
||||
double DoubleFromEnv(const char *v, double dflt) {
|
||||
return GetFromEnv(v, "double", dflt);
|
||||
return GetFromEnv(v, dflt);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
|
@ -429,11 +429,57 @@ extern GFLAGS_DLL_DECL void ShutDownCommandLineFlags();
|
|||
// people can't DECLARE_int32 something that they DEFINE_bool'd
|
||||
// elsewhere.
|
||||
|
||||
enum FlagValueType {
|
||||
FVT_BOOL = 0,
|
||||
FVT_INT32 = 1,
|
||||
FVT_UINT32 = 2,
|
||||
FVT_INT64 = 3,
|
||||
FVT_UINT64 = 4,
|
||||
FVT_DOUBLE = 5,
|
||||
FVT_STRING = 6,
|
||||
FVT_MAX_INDEX = 6
|
||||
};
|
||||
|
||||
template <typename T, const FlagValueType type>
|
||||
class FlagTraitsBase {
|
||||
public:
|
||||
typedef T ValueType;
|
||||
|
||||
static FlagValueType Type() { return type; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class FlagTraits;
|
||||
|
||||
template <>
|
||||
class FlagTraits<bool> : public FlagTraitsBase<bool, FVT_BOOL> {};
|
||||
template <>
|
||||
class FlagTraits<int32> : public FlagTraitsBase<int32, FVT_INT32> {};
|
||||
template <>
|
||||
class FlagTraits<int64> : public FlagTraitsBase<int64, FVT_INT64> {};
|
||||
template <>
|
||||
class FlagTraits<uint32> : public FlagTraitsBase<uint32, FVT_UINT32> {};
|
||||
template <>
|
||||
class FlagTraits<uint64> : public FlagTraitsBase<uint64, FVT_UINT64> {};
|
||||
template <>
|
||||
class FlagTraits<double> : public FlagTraitsBase<double, FVT_DOUBLE> {};
|
||||
template <>
|
||||
class FlagTraits<std::string> : public FlagTraitsBase<std::string, FVT_STRING> {
|
||||
};
|
||||
|
||||
class GFLAGS_DLL_DECL FlagRegisterer {
|
||||
public:
|
||||
FlagRegisterer(const char* name, const char* type,
|
||||
FlagRegisterer(const char* name, FlagValueType type,
|
||||
const char* help, const char* filename,
|
||||
void* current_storage, void* defvalue_storage);
|
||||
|
||||
template <typename T>
|
||||
FlagRegisterer(const char* name, const char* help, const char* filename,
|
||||
T* current_storage, T* defvalue_storage) {
|
||||
// Create a temporary value to call proper constructor.
|
||||
(void)FlagRegisterer(name, FlagTraits<T>::Type(), help, filename,
|
||||
current_storage, defvalue_storage);
|
||||
}
|
||||
};
|
||||
|
||||
// If your application #defines STRIP_FLAG_HELP to a non-zero value
|
||||
|
@ -475,7 +521,7 @@ extern GFLAGS_DLL_DECL const char kStrippedFlagHelp[];
|
|||
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
|
||||
type FLAGS_no##name = FLAGS_nono##name; \
|
||||
static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \
|
||||
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
|
||||
#name, MAYBE_STRIPPED_HELP(help), __FILE__, \
|
||||
&FLAGS_##name, &FLAGS_no##name); \
|
||||
} \
|
||||
using fL##shorttype::FLAGS_##name
|
||||
|
@ -581,7 +627,8 @@ public:
|
|||
dont_pass0toDEFINE_string(s_##name[0].s, \
|
||||
val); \
|
||||
static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \
|
||||
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
|
||||
#name, GFLAGS_NAMESPACE::FlagTraits<std::string>::Type(), \
|
||||
MAYBE_STRIPPED_HELP(txt), __FILE__, \
|
||||
s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
|
||||
static StringFlagDestructor d_##name(s_##name[0].s, s_##name[1].s); \
|
||||
extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \
|
||||
|
|
|
@ -216,7 +216,7 @@ namespace fLI {
|
|||
int32 FLAGS_tldflag1 = FLAGS_nonotldflag1;
|
||||
int32 FLAGS_notldflag1 = FLAGS_nonotldflag1;
|
||||
static FlagRegisterer o_tldflag1(
|
||||
"tldflag1", "int32",
|
||||
"tldflag1", GFLAGS_NAMESPACE::FlagTraits<int32>::Type(),
|
||||
"should show up in --helpshort", "gflags_unittest.cc",
|
||||
&FLAGS_tldflag1, &FLAGS_notldflag1);
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ namespace fLI {
|
|||
int32 FLAGS_tldflag2 = FLAGS_nonotldflag2;
|
||||
int32 FLAGS_notldflag2 = FLAGS_nonotldflag2;
|
||||
static FlagRegisterer o_tldflag2(
|
||||
"tldflag2", "int32",
|
||||
"tldflag2", GFLAGS_NAMESPACE::FlagTraits<int32>::Type(),
|
||||
"should show up in --helpshort", "gflags_unittest.",
|
||||
&FLAGS_tldflag2, &FLAGS_notldflag2);
|
||||
}
|
||||
|
@ -1353,9 +1353,9 @@ TEST(ParseCommandLineFlagsWrongFields,
|
|||
// command line flags' values. If these are on the stack, then when
|
||||
// later tests attempt to save and restore their values, the stack
|
||||
// addresses of these variables will be overwritten... Stack smash!
|
||||
static bool current_storage;
|
||||
static bool defvalue_storage;
|
||||
FlagRegisterer fr("flag_name", "bool", 0, "filename",
|
||||
static int32 current_storage;
|
||||
static int32 defvalue_storage;
|
||||
FlagRegisterer fr("flag_name", NULL, "filename",
|
||||
¤t_storage, &defvalue_storage);
|
||||
CommandLineFlagInfo fi;
|
||||
EXPECT_TRUE(GetCommandLineFlagInfo("flag_name", &fi));
|
||||
|
|
Loading…
Add table
Reference in a new issue