* Reduce .o size by decomposing switches (jyrki)
* Document how to change the default flag value (csilvers)
* Add a windows-specific README (csilvers)
* A few comment updates (wojtekm)
git-svn-id: https://gflags.googlecode.com/svn/trunk@39 6586e3c6-dcc4-952a-343f-ff74eb82781d
diff --git a/Makefile.am b/Makefile.am
index 01e3431..16002d9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -34,7 +34,7 @@
## Add your documentation files (in doc/) in addition to these
## top-level boilerplate files. Also add a TODO file if you have one.
dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \
- doc/designstyle.css doc/gflags.html
+ README_windows.txt doc/designstyle.css doc/gflags.html
## The libraries (.so's) you want to install
lib_LTLIBRARIES =
diff --git a/Makefile.in b/Makefile.in
index b0390d2..3eaf258 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -307,7 +307,7 @@
googleinclude_HEADERS = src/google/gflags.h src/google/gflags_completions.h
bin_SCRIPTS = src/gflags_completions.sh
dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \
- doc/designstyle.css doc/gflags.html
+ README_windows.txt doc/designstyle.css doc/gflags.html
lib_LTLIBRARIES = libgflags.la libgflags_nothreads.la
WINDOWS_PROJECTS = google-gflags.sln \
diff --git a/README b/README
index b49fac9..7422982 100644
--- a/README
+++ b/README
@@ -6,5 +6,4 @@
See INSTALL for (generic) installation instructions for C++: basically
./configure && make && make install
-You can also compile this under Windows, if you want. The solution
-file (for VC 7.1 and later) is in this directory.
+See README_windows.txt for instructions on using under windows.
diff --git a/README_windows.txt b/README_windows.txt
new file mode 100644
index 0000000..33f839b
--- /dev/null
+++ b/README_windows.txt
@@ -0,0 +1,20 @@
+You can compile this under Windows, if you want. The solution file
+(for VC 7.1 and later) is in this directory.
+
+I've been told the following steps work to compile this under win64:
+ 1) Open the provided solution file
+ 2) Click on the Win32 target (on the right of Debug/Release)
+ 3) Choose Configuration Manager
+ 4) In Active Solution Platforms, choose New...
+ 5) In "Type of select the new platform", choose x64.
+ In "Copy settings from:" choose Win32.
+ 6) Ok and then Close
+
+I don't know very much about how to install DLLs on Windows, so you'll
+have to figure out that part for yourself. If you choose to just
+re-use the existing .sln, make sure you set the IncludeDir's
+appropriately! Look at the properties for libgflags.dll.
+
+You can also link gflags code in statically. For this to work, you'll
+need to add "/D GFLAGS_DLL_DECL=" to the compile line of every
+gflags .cc file.
diff --git a/doc/gflags.html b/doc/gflags.html
index cf0c4b3..fe202d1 100644
--- a/doc/gflags.html
+++ b/doc/gflags.html
@@ -47,6 +47,7 @@
<dd> <a href="#together">Putting It Together: How to Set Up Flags</a> </dd>
<dd> <a href="#commandline">Setting Flags on the Command Line</a> </dd>
<dd> <a href="#varz">Setting Flags at Runtime</a> </dd>
+ <dd> <a href="#default">Changing the Default Flag Value</a> </dd>
<dd> <a href="#special">Special Flags</a> </dd>
<dd> <a href="#api">The API</a> </dd>
<dd> <br/> </dd>
@@ -348,6 +349,26 @@
single dash, as in <code>ls -la</code>.</p>
+
+<h2> <A name=default>Changing the Default Flag Value</A> </h2>
+
+<p>Sometimes a flag is defined in a library, and you want to change
+its default value in one application but not others. It's simple to
+do this: just assign a new value to the flag in <code>main()</code>,
+before calling <code>ParseCommandLineFlags()</code>:</p>
+<pre>
+ DECLARE_bool(lib_verbose); // mylib has a lib_verbose flag, default is false
+ int main(int argc, char** argv) {
+ FLAGS_lib_verbose = true; // in my app, I want a verbose lib by default
+ ParseCommandLineFlags(...);
+ }
+</pre>
+
+<p>For this application, users can still set the flag value on the
+commandline, but if they do not, the flag's value will default to
+true.</p>
+
+
<h2> <A name="special">Special Flags</code> </h2>
<p>There are a few flags defined by the commandlineflags module
diff --git a/src/gflags.cc b/src/gflags.cc
index d233e50..01067a4 100644
--- a/src/gflags.cc
+++ b/src/gflags.cc
@@ -143,6 +143,8 @@
# define PRIu64 "llu"
#endif
+typedef unsigned char uint8;
+
// Special flags, type 1: the 'recursive' flags. They set another flag's val.
DEFINE_string(flagfile, "",
"load flags from file");
@@ -235,8 +237,15 @@
friend bool TryParseLocked(const CommandLineFlag*, FlagValue*,
const char*, string*); // for New(), CopyFrom()
- enum ValueType {FV_BOOL, FV_INT32, FV_INT64, FV_UINT64, FV_DOUBLE, FV_STRING};
-
+ enum ValueType {
+ FV_BOOL = 0,
+ FV_INT32 = 1,
+ FV_INT64 = 2,
+ FV_UINT64 = 3,
+ FV_DOUBLE = 4,
+ FV_STRING = 5,
+ FV_MAX_INDEX = 5,
+ };
const char* TypeName() const;
bool Equal(const FlagValue& x) const;
FlagValue* New() const; // creates a new one with default value
@@ -249,9 +258,8 @@
// (*validate_fn)(bool) for a bool flag).
bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const;
-
void* value_buffer_; // points to the buffer holding our data
- ValueType type_; // how to interpret value_
+ uint32 type_; // how to interpret value_
FlagValue(const FlagValue&); // no copying!
void operator=(const FlagValue&);
@@ -265,13 +273,12 @@
#define SET_VALUE_AS(type, value) VALUE_AS(type) = (value)
FlagValue::FlagValue(void* valbuf, const char* type) : value_buffer_(valbuf) {
- if (strcmp(type, "bool") == 0) type_ = FV_BOOL;
- else if (strcmp(type, "int32") == 0) type_ = FV_INT32;
- else if (strcmp(type, "int64") == 0) type_ = FV_INT64;
- else if (strcmp(type, "uint64") == 0) type_ = FV_UINT64;
- else if (strcmp(type, "double") == 0) type_ = FV_DOUBLE;
- else if (strcmp(type, "string") == 0) type_ = FV_STRING;
- else assert(false); // Unknown typename
+ for (type_ = 0; type_ <= FV_MAX_INDEX; ++type_) {
+ if (!strcmp(type, TypeName())) {
+ break;
+ }
+ }
+ assert(type_ <= FV_MAX_INDEX); // Unknown typename
}
FlagValue::~FlagValue() {
@@ -405,15 +412,20 @@
}
const char* FlagValue::TypeName() const {
- switch (type_) {
- case FV_BOOL: return "bool";
- case FV_INT32: return "int32";
- case FV_INT64: return "int64";
- case FV_UINT64: return "uint64";
- case FV_DOUBLE: return "double";
- case FV_STRING: return "string";
- default: assert(false); return ""; // unknown type
+ static const char types[] =
+ "bool\0xx"
+ "int32\0x"
+ "int64\0x"
+ "uint64\0"
+ "double\0"
+ "string";
+ if (type_ > FV_MAX_INDEX) {
+ assert(false);
+ return "";
}
+ // Directly indexing the strigns in the 'types' string, each of them
+ // is 7 bytes long.
+ return &types[type_ * 7];
}
bool FlagValue::Equal(const FlagValue& x) const {
@@ -431,13 +443,14 @@
}
FlagValue* FlagValue::New() const {
+ const char *type = TypeName();
switch (type_) {
- case FV_BOOL: return new FlagValue(new bool(false), "bool");
- case FV_INT32: return new FlagValue(new int32(0), "int32");
- case FV_INT64: return new FlagValue(new int64(0), "int64");
- case FV_UINT64: return new FlagValue(new uint64(0), "uint64");
- case FV_DOUBLE: return new FlagValue(new double(0.0), "double");
- case FV_STRING: return new FlagValue(new string, "string");
+ case FV_BOOL: return new FlagValue(new bool(false), type);
+ case FV_INT32: return new FlagValue(new int32(0), type);
+ case FV_INT64: return new FlagValue(new int64(0), type);
+ case FV_UINT64: return new FlagValue(new uint64(0), type);
+ case FV_DOUBLE: return new FlagValue(new double(0.0), type);
+ case FV_STRING: return new FlagValue(new string, type);
default: assert(false); return NULL; // unknown type
}
}
@@ -456,15 +469,19 @@
}
int FlagValue::ValueSize() const {
- switch (type_) {
- case FV_BOOL: return sizeof(bool);
- case FV_INT32: return sizeof(int32);
- case FV_INT64: return sizeof(int64);
- case FV_UINT64: return sizeof(uint64);
- case FV_DOUBLE: return sizeof(double);
- case FV_STRING: return sizeof(string);
- default: assert(false); return 0; // unknown type
+ if (type_ > FV_MAX_INDEX) {
+ assert(false); // unknown type
+ return 0;
}
+ static const uint8 valuesize[] = {
+ sizeof(bool),
+ sizeof(int32),
+ sizeof(int64),
+ sizeof(uint64),
+ sizeof(double),
+ sizeof(string),
+ };
+ return valuesize[type_];
}
// --------------------------------------------------------------------
diff --git a/src/gflags/gflags.h.in b/src/gflags/gflags.h.in
index 2d38071..889c3fa 100644
--- a/src/gflags/gflags.h.in
+++ b/src/gflags/gflags.h.in
@@ -124,7 +124,8 @@
// DEFINE_string, etc. at the bottom of this file. You may also find
// it useful to register a validator with the flag. This ensures that
// when the flag is parsed from the commandline, or is later set via
-// SetCommandLineOption, we call the validation function.
+// SetCommandLineOption, we call the validation function. It is _not_
+// called when you assign the value to the flag directly using the = operator.
//
// The validation function should return true if the flag value is valid, and
// false otherwise. If the function returns false for the new setting of the
@@ -180,7 +181,9 @@
std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag
bool has_validator_fn; // true if RegisterFlagValidator called on flag
- bool is_default; // true if the flag has default value
+ bool is_default; // true if the flag has the default value and
+ // has not been set explicitly from the cmdline
+ // or via SetCommandLineOption
};
// Using this inside of a validator is a recipe for a deadlock.
diff --git a/src/windows/gflags/gflags.h b/src/windows/gflags/gflags.h
index 38bc3c3..191c6e3 100644
--- a/src/windows/gflags/gflags.h
+++ b/src/windows/gflags/gflags.h
@@ -99,12 +99,26 @@
#endif
// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef GFLAGS_DLL_DECL
-# ifdef _WIN32
+#if defined(_WIN32)
+# ifndef GFLAGS_DLL_DECL
# define GFLAGS_DLL_DECL __declspec(dllimport)
-# else
+# endif
+# ifndef GFLAGS_DLL_DECLARE_FLAG
+# define GFLAGS_DLL_DECLARE_FLAG __declspec(import)
+# endif
+# ifndef GFLAGS_DLL_DEFINE_FLAG
+# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
+# endif
+#else
+# ifndef GFLAGS_DLL_DECL
# define GFLAGS_DLL_DECL
# endif
+# ifndef GFLAGS_DLL_DECLARE_FLAG
+# define GFLAGS_DLL_DECLARE_FLAG
+# endif
+# ifndef GFLAGS_DLL_DEFINE_FLAG
+# define GFLAGS_DLL_DEFINE_FLAG
+# endif
#endif
namespace google {
@@ -133,7 +147,8 @@
// DEFINE_string, etc. at the bottom of this file. You may also find
// it useful to register a validator with the flag. This ensures that
// when the flag is parsed from the commandline, or is later set via
-// SetCommandLineOption, we call the validation function.
+// SetCommandLineOption, we call the validation function. It is _not_
+// called when you assign the value to the flag directly using the = operator.
//
// The validation function should return true if the flag value is valid, and
// false otherwise. If the function returns false for the new setting of the
@@ -189,7 +204,9 @@
std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag
bool has_validator_fn; // true if RegisterFlagValidator called on flag
- bool is_default; // true if the flag has default value
+ bool is_default; // true if the flag has the default value and
+ // has not been set explicitly from the cmdline
+ // or via SetCommandLineOption
};
// Using this inside of a validator is a recipe for a deadlock.
@@ -471,7 +488,7 @@
namespace fL##shorttype { \
static const type FLAGS_nono##name = value; \
/* We always want to export defined variables, dll or no */ \
- __declspec(dllexport) type FLAGS_##name = FLAGS_nono##name; \
+ GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
type FLAGS_no##name = FLAGS_nono##name; \
static ::google::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
@@ -482,7 +499,7 @@
#define DECLARE_VARIABLE(type, shorttype, name) \
namespace fL##shorttype { \
/* We always want to import declared variables, dll or no */ \
- extern __declspec(dllimport) type FLAGS_##name; \
+ extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; \
} \
using fL##shorttype::FLAGS_##name
@@ -528,7 +545,7 @@
// try to avoid crashes in that case, we use a char buffer to store
// the string, which we can static-initialize, and then placement-new
// into it later. It's not perfect, but the best we can do.
-#define DECLARE_string(name) namespace fLS { extern __declspec(dllimport) std::string& FLAGS_##name; } \
+#define DECLARE_string(name) namespace fLS { extern GFLAGS_DLL_DECLARE_FLAG std::string& FLAGS_##name; } \
using fLS::FLAGS_##name
// We need to define a var named FLAGS_no##name so people don't define
@@ -545,7 +562,7 @@
static ::google::FlagRegisterer o_##name( \
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
s_##name[0].s, new (s_##name[1].s) std::string(*FLAGS_no##name)); \
- extern __declspec(dllexport) std::string& FLAGS_##name; \
+ extern GFLAGS_DLL_DEFINE_FLAG std::string& FLAGS_##name; \
using fLS::FLAGS_##name; \
std::string& FLAGS_##name = *FLAGS_no##name; \
} \