OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2013 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "SkFlags.h" | |
9 | |
10 static bool string_is_in(const char* target, const char* set[], size_t len) { | |
11 for (size_t i = 0; i < len; i++) { | |
12 if (0 == strcmp(target, set[i])) { | |
13 return true; | |
14 } | |
15 } | |
16 return false; | |
17 } | |
18 | |
19 /** | |
20 * Check to see whether string represents a boolean value. | |
21 * @param string C style string to parse. | |
22 * @param result Pointer to a boolean which will be set to the value in the str
ing, if the | |
23 * string represents a boolean. | |
24 * @param boolean True if the string represents a boolean, false otherwise. | |
25 */ | |
26 static bool parse_bool_arg(const char* string, bool* result) { | |
27 static const char* trueValues[] = { "1", "TRUE", "true" }; | |
28 if (string_is_in(string, trueValues, SK_ARRAY_COUNT(trueValues))) { | |
29 *result = true; | |
30 return true; | |
31 } | |
32 static const char* falseValues[] = { "0", "FALSE", "false" }; | |
33 if (string_is_in(string, falseValues, SK_ARRAY_COUNT(falseValues))) { | |
34 *result = false; | |
35 return true; | |
36 } | |
37 SkDebugf("Parameter \"%s\" not supported.\n", string); | |
38 return false; | |
39 } | |
40 | |
41 bool SkFlagInfo::match(const char* string) { | |
42 if (SkStrStartsWith(string, '-') && strlen(string) > 1) { | |
43 string++; | |
44 // Allow one or two dashes | |
45 if (SkStrStartsWith(string, '-') && strlen(string) > 1) { | |
46 string++; | |
47 } | |
48 if (kBool_FlagType == fFlagType) { | |
49 // In this case, go ahead and set the value. | |
50 if (fName.equals(string) || fShortName.equals(string)) { | |
51 *fBoolValue = true; | |
52 return true; | |
53 } | |
54 if (SkStrStartsWith(string, "no") && strlen(string) > 2) { | |
55 string += 2; | |
56 if (fName.equals(string) || fShortName.equals(string)) { | |
57 *fBoolValue = false; | |
58 return true; | |
59 } | |
60 return false; | |
61 } | |
62 int equalIndex = SkStrFind(string, "="); | |
63 if (equalIndex > 0) { | |
64 // The string has an equal sign. Check to see if the string matc
hes. | |
65 SkString flag(string, equalIndex); | |
66 if (flag.equals(fName) || flag.equals(fShortName)) { | |
67 // Check to see if the remainder beyond the equal sign is tr
ue or false: | |
68 string += equalIndex + 1; | |
69 parse_bool_arg(string, fBoolValue); | |
70 return true; | |
71 } | |
72 } | |
73 } | |
74 return fName.equals(string) || fShortName.equals(string); | |
75 } else { | |
76 // Has no dash | |
77 return false; | |
78 } | |
79 return false; | |
80 } | |
81 | |
82 SkFlagInfo* SkFlags::gHead; | |
83 SkString SkFlags::gUsage; | |
84 | |
85 void SkFlags::SetUsage(const char* usage) { | |
86 gUsage.set(usage); | |
87 } | |
88 | |
89 // Maximum line length for the help message. | |
90 #define LINE_LENGTH 80 | |
91 | |
92 static void print_help_for_flag(const SkFlagInfo* flag) { | |
93 SkDebugf("\t--%s", flag->name().c_str()); | |
94 const SkString& shortName = flag->shortName(); | |
95 if (shortName.size() > 0) { | |
96 SkDebugf(" or -%s", shortName.c_str()); | |
97 } | |
98 SkDebugf(":\ttype: %s", flag->typeAsString().c_str()); | |
99 if (flag->defaultValue().size() > 0) { | |
100 SkDebugf("\tdefault: %s", flag->defaultValue().c_str()); | |
101 } | |
102 SkDebugf("\n"); | |
103 const SkString& help = flag->help(); | |
104 size_t length = help.size(); | |
105 const char* currLine = help.c_str(); | |
106 const char* stop = currLine + length; | |
107 while (currLine < stop) { | |
108 if (strlen(currLine) < LINE_LENGTH) { | |
109 // Only one line length's worth of text left. | |
110 SkDebugf("\t\t%s\n", currLine); | |
111 break; | |
112 } | |
113 int lineBreak = SkStrFind(currLine, "\n"); | |
114 if (lineBreak < 0 || lineBreak > LINE_LENGTH) { | |
115 // No line break within line length. Will need to insert one. | |
116 // Find a space before the line break. | |
117 int spaceIndex = LINE_LENGTH - 1; | |
118 while (spaceIndex > 0 && currLine[spaceIndex] != ' ') { | |
119 spaceIndex--; | |
120 } | |
121 int gap; | |
122 if (0 == spaceIndex) { | |
123 // No spaces on the entire line. Go ahead and break mid word. | |
124 spaceIndex = LINE_LENGTH; | |
125 gap = 0; | |
126 } else { | |
127 // Skip the space on the next line | |
128 gap = 1; | |
129 } | |
130 SkDebugf("\t\t%.*s\n", spaceIndex, currLine); | |
131 currLine += spaceIndex + gap; | |
132 } else { | |
133 // the line break is within the limit. Break there. | |
134 lineBreak++; | |
135 SkDebugf("\t\t%.*s", lineBreak, currLine); | |
136 currLine += lineBreak; | |
137 } | |
138 } | |
139 SkDebugf("\n"); | |
140 } | |
141 | |
142 void SkFlags::ParseCommandLine(int argc, char** argv) { | |
143 // Only allow calling this function once. | |
144 static bool gOnce; | |
145 if (gOnce) { | |
146 SkDebugf("ParseCommandLine should only be called once at the beginning" | |
147 " of main!\n"); | |
148 SkASSERT(false); | |
149 return; | |
150 } | |
151 gOnce = true; | |
152 | |
153 bool helpPrinted = false; | |
154 // Loop over argv, starting with 1, since the first is just the name of the
program. | |
155 for (int i = 1; i < argc; i++) { | |
156 if (0 == strcmp("-h", argv[i]) || 0 == strcmp("--h", argv[i]) | |
157 || 0 == strcmp("-help", argv[i]) || 0 == strcmp("--help", argv[i
])) { | |
158 // Print help message. | |
159 SkTDArray<const char*> helpFlags; | |
160 for (int j = i + 1; j < argc; j++) { | |
161 if (SkStrStartsWith(argv[j], '-')) { | |
162 break; | |
163 } | |
164 helpFlags.append(1, &argv[j]); | |
165 } | |
166 if (0 == helpFlags.count()) { | |
167 // Only print general help message if help for specific flags is
not requested. | |
168 SkDebugf("%s\n%s\n", argv[0], gUsage.c_str()); | |
169 } | |
170 SkDebugf("Flags:\n"); | |
171 SkFlagInfo* flag = SkFlags::gHead; | |
172 while (flag != NULL) { | |
173 // If no flags followed --help, print them all | |
174 bool printFlag = 0 == helpFlags.count(); | |
175 if (!printFlag) { | |
176 for (int k = 0; k < helpFlags.count(); k++) { | |
177 if (flag->name().equals(helpFlags[k]) || | |
178 flag->shortName().equals(helpFlags[k])) { | |
179 printFlag = true; | |
180 helpFlags.remove(k); | |
181 break; | |
182 } | |
183 } | |
184 } | |
185 if (printFlag) { | |
186 print_help_for_flag(flag); | |
187 } | |
188 flag = flag->next(); | |
189 } | |
190 if (helpFlags.count() > 0) { | |
191 SkDebugf("Requested help for unrecognized flags:\n"); | |
192 for (int k = 0; k < helpFlags.count(); k++) { | |
193 SkDebugf("\t--%s\n", helpFlags[k]); | |
194 } | |
195 } | |
196 helpPrinted = true; | |
197 } | |
198 if (!helpPrinted) { | |
199 bool flagMatched = false; | |
200 SkFlagInfo* flag = gHead; | |
201 while (flag != NULL) { | |
202 if (flag->match(argv[i])) { | |
203 flagMatched = true; | |
204 switch (flag->getFlagType()) { | |
205 case SkFlagInfo::kBool_FlagType: | |
206 // Can be handled by match, above, but can also be s
et by the next | |
207 // string. | |
208 if (i+1 < argc && !SkStrStartsWith(argv[i+1], '-'))
{ | |
209 i++; | |
210 bool value; | |
211 if (parse_bool_arg(argv[i], &value)) { | |
212 flag->setBool(value); | |
213 } | |
214 } | |
215 break; | |
216 case SkFlagInfo::kString_FlagType: | |
217 flag->resetStrings(); | |
218 // Add all arguments until another flag is reached. | |
219 while (i+1 < argc && !SkStrStartsWith(argv[i+1], '-'
)) { | |
220 i++; | |
221 flag->append(argv[i]); | |
222 } | |
223 break; | |
224 case SkFlagInfo::kInt_FlagType: | |
225 i++; | |
226 flag->setInt(atoi(argv[i])); | |
227 break; | |
228 case SkFlagInfo::kDouble_FlagType: | |
229 i++; | |
230 flag->setDouble(atof(argv[i])); | |
231 break; | |
232 default: | |
233 SkASSERT(!"Invalid flag type"); | |
234 } | |
235 break; | |
236 } | |
237 flag = flag->next(); | |
238 } | |
239 if (!flagMatched) { | |
240 SkDebugf("Got unknown flag \"%s\". Exiting.\n", argv[i]); | |
241 exit(-1); | |
242 } | |
243 } | |
244 } | |
245 // Since all of the flags have been set, release the memory used by each | |
246 // flag. FLAGS_x can still be used after this. | |
247 SkFlagInfo* flag = gHead; | |
248 gHead = NULL; | |
249 while (flag != NULL) { | |
250 SkFlagInfo* next = flag->next(); | |
251 SkDELETE(flag); | |
252 flag = next; | |
253 } | |
254 if (helpPrinted) { | |
255 exit(0); | |
256 } | |
257 } | |
OLD | NEW |