Allow more options for setting boolean flag values in SkFlags.

Now booleans can be set using
--boolean=true or --boolean true (as well as other options).

Review URL: https://codereview.chromium.org/12961003

git-svn-id: http://skia.googlecode.com/svn/trunk@8285 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tools/SkFlags.cpp b/tools/SkFlags.cpp
index 2d124b6..9635b82 100644
--- a/tools/SkFlags.cpp
+++ b/tools/SkFlags.cpp
@@ -7,6 +7,78 @@
 
 #include "SkFlags.h"
 
+static bool string_is_in(const char* target, const char* set[], size_t len) {
+    for (size_t i = 0; i < len; i++) {
+        if (0 == strcmp(target, set[i])) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/**
+ *  Check to see whether string represents a boolean value.
+ *  @param string C style string to parse.
+ *  @param result Pointer to a boolean which will be set to the value in the string, if the
+ *      string represents a boolean.
+ *  @param boolean True if the string represents a boolean, false otherwise.
+ */
+static bool parse_bool_arg(const char* string, bool* result) {
+    static const char* trueValues[] = { "1", "TRUE", "true" };
+    if (string_is_in(string, trueValues, SK_ARRAY_COUNT(trueValues))) {
+        *result = true;
+        return true;
+    }
+    static const char* falseValues[] = { "0", "FALSE", "false" };
+    if (string_is_in(string, falseValues, SK_ARRAY_COUNT(falseValues))) {
+        *result = false;
+        return true;
+    }
+    SkDebugf("Parameter \"%s\" not supported.\n", string);
+    return false;
+}
+
+bool SkFlagInfo::match(const char* string) {
+    if (SkStrStartsWith(string, '-') && strlen(string) > 1) {
+        string++;
+        // Allow one or two dashes
+        if (SkStrStartsWith(string, '-') && strlen(string) > 1) {
+            string++;
+        }
+        if (kBool_FlagType == fFlagType) {
+            // In this case, go ahead and set the value.
+            if (fName.equals(string) || fShortName.equals(string)) {
+                *fBoolValue = true;
+                return true;
+            }
+            if (SkStrStartsWith(string, "no") && strlen(string) > 2) {
+                string += 2;
+                if (fName.equals(string) || fShortName.equals(string)) {
+                    *fBoolValue = false;
+                    return true;
+                }
+                return false;
+            }
+            int equalIndex = SkStrFind(string, "=");
+            if (equalIndex > 0) {
+                // The string has an equal sign. Check to see if the string matches.
+                SkString flag(string, equalIndex);
+                if (flag.equals(fName) || flag.equals(fShortName)) {
+                    // Check to see if the remainder beyond the equal sign is true or false:
+                    string += equalIndex + 1;
+                    parse_bool_arg(string, fBoolValue);
+                    return true;
+                }
+            }
+        }
+        return fName.equals(string) || fShortName.equals(string);
+    } else {
+        // Has no dash
+        return false;
+    }
+    return false;
+}
+
 SkFlagInfo* SkFlags::gHead;
 SkString SkFlags::gUsage;
 
@@ -131,7 +203,15 @@
                     flagMatched = true;
                     switch (flag->getFlagType()) {
                         case SkFlagInfo::kBool_FlagType:
-                            // Handled by match, above
+                            // Can be handled by match, above, but can also be set by the next
+                            // string.
+                            if (i+1 < argc && !SkStrStartsWith(argv[i+1], '-')) {
+                                i++;
+                                bool value;
+                                if (parse_bool_arg(argv[i], &value)) {
+                                    flag->setBool(value);
+                                }
+                            }
                             break;
                         case SkFlagInfo::kString_FlagType:
                             flag->resetStrings();
diff --git a/tools/SkFlags.h b/tools/SkFlags.h
index a2d4c97..c510707 100644
--- a/tools/SkFlags.h
+++ b/tools/SkFlags.h
@@ -37,8 +37,13 @@
  *
  *  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. (Single dashes are also permitted for this and other flags.) The
- *  helpString will be printed if the help flag (-h or -help) is used.
+ *  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
  *
@@ -227,38 +232,19 @@
     }
 
     /**
-     *  Returns true if the string matches this flag. For a bool, also sets the
-     *  value, since a bool is specified as true or false by --name or --noname.
+     *  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) {
-        if (SkStrStartsWith(string, '-') && strlen(string) > 1) {
-            string++;
-            // Allow one or two dashes
-            if (SkStrStartsWith(string, '-') && strlen(string) > 1) {
-                string++;
-            }
-            if (kBool_FlagType == fFlagType) {
-                // In this case, go ahead and set the value.
-                if (fName.equals(string) || fShortName.equals(string)) {
-                    *fBoolValue = true;
-                    return true;
-                }
-                if (SkStrStartsWith(string, "no") && strlen(string) > 2) {
-                    string += 2;
-                    if (fName.equals(string) || fShortName.equals(string)) {
-                        *fBoolValue = false;
-                        return true;
-                    }
-                    return false;
-                }
-            }
-            return fName.equals(string) || fShortName.equals(string);
-        } else {
-            // Has no dash
-            return false;
-        }
-        return false;
-    }
+    bool match(const char* string);
 
     FlagTypes getFlagType() const { return fFlagType; }
 
@@ -294,6 +280,14 @@
         }
     }
 
+    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; }