aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/flags/SkCommandLineFlags.h
diff options
context:
space:
mode:
authorGravatar scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-03-21 19:43:15 +0000
committerGravatar scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-03-21 19:43:15 +0000
commitd9ba9a05d6f5766fdb1378b6ed84c0659009a8da (patch)
tree3add5282273525de50f0b77ad7ff276cf91ddd46 /tools/flags/SkCommandLineFlags.h
parentcc9aad5787b52216f46b9d6d95a781240e3e6b6b (diff)
Change the name of SkFlags to SkCommandLineFlags.
This name is more specific to what it actually does. Also move the code into tools/flags, to (slightly) better organize the massive tools folder. Update the programs that use it to use the new names. No functionality changes. BUG=https://code.google.com/p/skia/issues/detail?id=1173 Review URL: https://codereview.chromium.org/12440067 git-svn-id: http://skia.googlecode.com/svn/trunk@8304 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'tools/flags/SkCommandLineFlags.h')
-rw-r--r--tools/flags/SkCommandLineFlags.h368
1 files changed, 368 insertions, 0 deletions
diff --git a/tools/flags/SkCommandLineFlags.h b/tools/flags/SkCommandLineFlags.h
new file mode 100644
index 0000000000..1d4f409fbf
--- /dev/null
+++ b/tools/flags/SkCommandLineFlags.h
@@ -0,0 +1,368 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SK_COMMAND_LINE_FLAGS_H
+#define SK_COMMAND_LINE_FLAGS_H
+
+#include "SkString.h"
+#include "SkTDArray.h"
+
+/**
+ * Including this file (and compiling SkCommandLineFlags.cpp) provides command line
+ * parsing. In order to use it, use the following macros in global
+ * namespace:
+ *
+ * DEFINE_bool(name, defaultValue, helpString);
+ * DEFINE_string(name, defaultValue, helpString);
+ * DEFINE_int32(name, defaultValue, helpString);
+ * DEFINE_double(name, defaultValue, helpString);
+ *
+ * Then, in main, call SkCommandLineFlags::SetUsage() to describe usage and call
+ * SkCommandLineFlags::Parse() to parse the flags. Henceforth, each flag can
+ * be referenced using
+ *
+ * FLAGS_name
+ *
+ * For example, the line
+ *
+ * DEFINE_bool(boolean, false, "The variable boolean does such and such");
+ *
+ * will create the following variable:
+ *
+ * bool FLAGS_boolean;
+ *
+ * which will initially be set to false, and can be set to true by using the
+ * flag "--boolean" on the commandline. "--noboolean" will set FLAGS_boolean
+ * to false. FLAGS_boolean can also be set using "--boolean=true" or
+ * "--boolean true" (where "true" can be replaced by "false", "TRUE", "FALSE",
+ * "1" or "0").
+ *
+ * Single dashes are also permitted for this and other flags.
+ *
+ * The helpString will be printed if the help flag (-h or -help) is used.
+ *
+ * Similarly, the line
+ *
+ * DEFINE_int32(integer, .., ..);
+ *
+ * will create
+ *
+ * int32_t FLAGS_integer;
+ *
+ * and
+ *
+ * DEFINE_double(real, .., ..);
+ *
+ * will create
+ *
+ * double FLAGS_real;
+ *
+ * These flags can be set by specifying, for example, "--integer 7" and
+ * "--real 3.14" on the command line.
+ *
+ * Unlike the others, the line
+ *
+ * DEFINE_string(args, .., ..);
+ *
+ * creates an array:
+ *
+ * SkTDArray<const char*> FLAGS_args;
+ *
+ * If the default value is the empty string, FLAGS_args will default to a size
+ * of zero. Otherwise it will default to a size of 1 with the default string
+ * as its value. All strings that follow the flag on the command line (until
+ * a string that begins with '-') will be entries in the array.
+ *
+ * Any flag can be referenced from another file after using the following:
+ *
+ * DECLARE_x(name);
+ *
+ * (where 'x' is the type specified in the DEFINE).
+ *
+ * Inspired by gflags (https://code.google.com/p/gflags/). Is not quite as
+ * robust as gflags, but suits our purposes. For example, allows creating
+ * a flag -h or -help which will never be used, since SkCommandLineFlags handles it.
+ * SkCommandLineFlags will also allow creating --flag and --noflag. Uses the same input
+ * format as gflags and creates similarly named variables (i.e. FLAGS_name).
+ * Strings are handled differently (resulting variable will be an array of
+ * strings) so that a flag can be followed by multiple parameters.
+ */
+
+
+class SkFlagInfo;
+
+class SkCommandLineFlags {
+
+public:
+ /**
+ * Call to set the help message to be displayed. Should be called before
+ * Parse.
+ */
+ static void SetUsage(const char* usage);
+
+ /**
+ * Call at the beginning of main to parse flags created by DEFINE_x, above.
+ * Must only be called once.
+ */
+ static void Parse(int argc, char** argv);
+
+private:
+ static SkFlagInfo* gHead;
+ static SkString gUsage;
+
+ // For access to gHead.
+ friend class SkFlagInfo;
+};
+
+#define TO_STRING2(s) #s
+#define TO_STRING(s) TO_STRING2(s)
+
+#define DEFINE_bool(name, defaultValue, helpString) \
+bool FLAGS_##name; \
+static bool unused_##name = SkFlagInfo::CreateBoolFlag(TO_STRING(name), \
+ NULL, \
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString)
+
+// bool 2 allows specifying a short name. No check is done to ensure that shortName
+// is actually shorter than name.
+#define DEFINE_bool2(name, shortName, defaultValue, helpString) \
+bool FLAGS_##name; \
+static bool unused_##name = SkFlagInfo::CreateBoolFlag(TO_STRING(name), \
+ TO_STRING(shortName),\
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString)
+
+#define DECLARE_bool(name) extern bool FLAGS_##name;
+
+#define DEFINE_string(name, defaultValue, helpString) \
+SkTDArray<const char*> FLAGS_##name; \
+static bool unused_##name = SkFlagInfo::CreateStringFlag(TO_STRING(name), \
+ NULL, \
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString)
+
+// string2 allows specifying a short name. No check is done to ensure that shortName
+// is actually shorter than name.
+#define DEFINE_string2(name, shortName, defaultValue, helpString) \
+SkTDArray<const char*> FLAGS_##name; \
+static bool unused_##name = SkFlagInfo::CreateStringFlag(TO_STRING(name), \
+ TO_STRING(shortName), \
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString)
+
+#define DECLARE_string(name) extern SkTDArray<const char*> FLAGS_##name;
+
+#define DEFINE_int32(name, defaultValue, helpString) \
+int32_t FLAGS_##name; \
+static bool unused_##name = SkFlagInfo::CreateIntFlag(TO_STRING(name), \
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString)
+
+#define DECLARE_int32(name) extern int32_t FLAGS_##name;
+
+#define DEFINE_double(name, defaultValue, helpString) \
+double FLAGS_##name; \
+static bool unused_##name = SkFlagInfo::CreateDoubleFlag(TO_STRING(name), \
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString)
+
+#define DECLARE_double(name) extern double FLAGS_##name;
+
+class SkFlagInfo {
+
+public:
+ enum FlagTypes {
+ kBool_FlagType,
+ kString_FlagType,
+ kInt_FlagType,
+ kDouble_FlagType,
+ };
+
+ // Create flags of the desired type, and append to the list.
+ static bool CreateBoolFlag(const char* name, const char* shortName, bool* pBool,
+ bool defaultValue, const char* helpString) {
+ SkFlagInfo* info = SkNEW_ARGS(SkFlagInfo, (name, kBool_FlagType, helpString));
+ info->fShortName.set(shortName);
+ info->fBoolValue = pBool;
+ *info->fBoolValue = info->fDefaultBool = defaultValue;
+ return true;
+ }
+
+ static bool CreateStringFlag(const char* name, const char* shortName,
+ SkTDArray<const char*>* pStrings,
+ const char* defaultValue, const char* helpString) {
+ SkFlagInfo* info = SkNEW_ARGS(SkFlagInfo, (name, kString_FlagType, helpString));
+ info->fShortName.set(shortName);
+ info->fDefaultString.set(defaultValue);
+
+ info->fStrings = pStrings;
+ info->fStrings->reset();
+ // If default is "", leave the array empty.
+ if (info->fDefaultString.size() > 0) {
+ info->fStrings->append(1, &defaultValue);
+ }
+ return true;
+ }
+
+ static bool CreateIntFlag(const char* name, int32_t* pInt,
+ int32_t defaultValue, const char* helpString) {
+ SkFlagInfo* info = SkNEW_ARGS(SkFlagInfo, (name, kInt_FlagType, helpString));
+ info->fIntValue = pInt;
+ *info->fIntValue = info->fDefaultInt = defaultValue;
+ return true;
+ }
+
+ static bool CreateDoubleFlag(const char* name, double* pDouble,
+ double defaultValue, const char* helpString) {
+ SkFlagInfo* info = SkNEW_ARGS(SkFlagInfo, (name, kDouble_FlagType, helpString));
+ info->fDoubleValue = pDouble;
+ *info->fDoubleValue = info->fDefaultDouble = defaultValue;
+ return true;
+ }
+
+ /**
+ * Returns true if the string matches this flag.
+ * For a boolean flag, also sets the value, since a boolean flag can be set in a number of ways
+ * without looking at the following string:
+ * --name
+ * --noname
+ * --name=true
+ * --name=false
+ * --name=1
+ * --name=0
+ * --name=TRUE
+ * --name=FALSE
+ */
+ bool match(const char* string);
+
+ FlagTypes getFlagType() const { return fFlagType; }
+
+ void resetStrings() {
+ if (kString_FlagType == fFlagType) {
+ fStrings->reset();
+ } else {
+ SkASSERT(!"Can only call resetStrings on kString_FlagType");
+ }
+ }
+
+ void append(const char* string) {
+ if (kString_FlagType == fFlagType) {
+ fStrings->append(1, &string);
+ } else {
+ SkASSERT(!"Can only append to kString_FlagType");
+ }
+ }
+
+ void setInt(int32_t value) {
+ if (kInt_FlagType == fFlagType) {
+ *fIntValue = value;
+ } else {
+ SkASSERT(!"Can only call setInt on kInt_FlagType");
+ }
+ }
+
+ void setDouble(double value) {
+ if (kDouble_FlagType == fFlagType) {
+ *fDoubleValue = value;
+ } else {
+ SkASSERT(!"Can only call setDouble on kDouble_FlagType");
+ }
+ }
+
+ void setBool(bool value) {
+ if (kBool_FlagType == fFlagType) {
+ *fBoolValue = value;
+ } else {
+ SkASSERT(!"Can only call setBool on kBool_FlagType");
+ }
+ }
+
+ SkFlagInfo* next() { return fNext; }
+
+ const SkString& name() const { return fName; }
+
+ const SkString& shortName() const { return fShortName; }
+
+ const SkString& help() const { return fHelpString; }
+
+ SkString defaultValue() const {
+ SkString result;
+ switch (fFlagType) {
+ case SkFlagInfo::kBool_FlagType:
+ result.printf("%s", fDefaultBool ? "true" : "false");
+ break;
+ case SkFlagInfo::kString_FlagType:
+ return fDefaultString;
+ case SkFlagInfo::kInt_FlagType:
+ result.printf("%i", fDefaultInt);
+ break;
+ case SkFlagInfo::kDouble_FlagType:
+ result.printf("%2.2f", fDefaultDouble);
+ break;
+ default:
+ SkASSERT(!"Invalid flag type");
+ }
+ return result;
+ }
+
+ SkString typeAsString() const {
+ switch (fFlagType) {
+ case SkFlagInfo::kBool_FlagType:
+ return SkString("bool");
+ case SkFlagInfo::kString_FlagType:
+ return SkString("string");
+ case SkFlagInfo::kInt_FlagType:
+ return SkString("int");
+ case SkFlagInfo::kDouble_FlagType:
+ return SkString("double");
+ default:
+ SkASSERT(!"Invalid flag type");
+ return SkString();
+ }
+ }
+
+private:
+ SkFlagInfo(const char* name, FlagTypes type, const char* helpString)
+ : fName(name)
+ , fFlagType(type)
+ , fHelpString(helpString)
+ , fBoolValue(NULL)
+ , fDefaultBool(false)
+ , fIntValue(NULL)
+ , fDefaultInt(0)
+ , fDoubleValue(NULL)
+ , fDefaultDouble(0)
+ , fStrings(NULL) {
+ fNext = SkCommandLineFlags::gHead;
+ SkCommandLineFlags::gHead = this;
+ }
+ // Name of the flag, without initial dashes
+ SkString fName;
+ SkString fShortName;
+ FlagTypes fFlagType;
+ SkString fHelpString;
+ bool* fBoolValue;
+ bool fDefaultBool;
+ int32_t* fIntValue;
+ int32_t fDefaultInt;
+ double* fDoubleValue;
+ double fDefaultDouble;
+ SkTDArray<const char*>* fStrings;
+ // Both for the help string and in case fStrings is empty.
+ SkString fDefaultString;
+
+ // In order to keep a linked list.
+ SkFlagInfo* fNext;
+};
+#endif // SK_COMMAND_LINE_FLAGS_H