blob: b4337d127312c83af90f2fecda5e441833f74698 [file] [log] [blame]
scroggo@google.com161e1ba2013-03-04 16:41:06 +00001/*
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
10SkFlagInfo* SkFlags::gHead;
11SkString SkFlags::gUsage;
12
13void SkFlags::SetUsage(const char* usage) {
14 gUsage.set(usage);
15}
16
17// Maximum line length for the help message.
18#define LINE_LENGTH 80
19
20void SkFlags::ParseCommandLine(int argc, char** argv) {
21 // Only allow calling this function once.
22 static bool gOnce;
23 if (gOnce) {
24 SkDebugf("ParseCommandLine should only be called once at the beginning"
25 " of main!\n");
26 SkASSERT(false);
27 return;
28 }
29 gOnce = true;
30
31 bool helpPrinted = false;
32 // Loop over argv, starting with 1, since the first is just the name of the program.
33 for (int i = 1; i < argc; i++) {
34 if (0 == strcmp("-h", argv[i]) || 0 == strcmp("--h", argv[i])
35 || 0 == strcmp("-help", argv[i]) || 0 == strcmp("--help", argv[i])) {
36 // Print help message.
37 SkDebugf("%s\n%s\n", argv[0], gUsage.c_str());
38 SkDebugf("Flags:\n");
39 SkFlagInfo* flag = SkFlags::gHead;
40 while (flag != NULL) {
41 SkDebugf("\t--%s:\ttype: %s\tdefault: %s\n", flag->name().c_str(),
42 flag->typeAsString().c_str(), flag->defaultValue().c_str());
43 const SkString& help = flag->help();
44 size_t length = help.size();
45 const char* currLine = help.c_str();
46 const char* stop = currLine + length;
47 while (currLine < stop) {
48 if (strlen(currLine) < LINE_LENGTH) {
49 // Only one line length's worth of text left.
50 SkDebugf("\t\t%s\n", currLine);
51 break;
52 }
53 int lineBreak = SkStrFind(currLine, "\n");
54 if (lineBreak < 0 || lineBreak > LINE_LENGTH) {
55 // No line break within line length. Will need to insert one.
56 // Find a space before the line break.
57 int spaceIndex = LINE_LENGTH - 1;
58 while (spaceIndex > 0 && currLine[spaceIndex] != ' ') {
59 spaceIndex--;
60 }
61 int gap;
62 if (0 == spaceIndex) {
63 // No spaces on the entire line. Go ahead and break mid word.
64 spaceIndex = LINE_LENGTH;
65 gap = 0;
66 } else {
67 // Skip the space on the next line
68 gap = 1;
69 }
70 SkDebugf("\t\t%.*s\n", spaceIndex, currLine);
71 currLine += spaceIndex + gap;
72 } else {
73 // the line break is within the limit. Break there.
74 lineBreak++;
75 SkDebugf("\t\t%.*s", lineBreak, currLine);
76 currLine += lineBreak;
77 }
78 }
79 SkDebugf("\n");
80 flag = flag->next();
81 }
82 helpPrinted = true;
83 }
84 if (!helpPrinted) {
85 bool flagMatched = false;
86 SkFlagInfo* flag = gHead;
87 while (flag != NULL) {
88 if (flag->match(argv[i])) {
89 flagMatched = true;
90 switch (flag->getFlagType()) {
91 case SkFlagInfo::kBool_FlagType:
92 // Handled by match, above
93 break;
94 case SkFlagInfo::kString_FlagType:
95 flag->resetStrings();
96 // Add all arguments until another flag is reached.
97 while (i+1 < argc && !SkStrStartsWith(argv[i+1], '-')) {
98 i++;
99 flag->append(argv[i]);
100 }
101 break;
102 case SkFlagInfo::kInt_FlagType:
103 i++;
104 flag->setInt(atoi(argv[i]));
105 break;
106 case SkFlagInfo::kDouble_FlagType:
107 i++;
108 flag->setDouble(atof(argv[i]));
109 break;
110 default:
111 SkASSERT(!"Invalid flag type");
112 }
113 break;
114 }
115 flag = flag->next();
116 }
117 if (!flagMatched) {
118 SkDebugf("skipping unknown flag %s\n", argv[i]);
119 }
120 }
121 }
122 // Since all of the flags have been set, release the memory used by each
123 // flag. FLAGS_x can still be used after this.
124 SkFlagInfo* flag = gHead;
125 gHead = NULL;
126 while (flag != NULL) {
127 SkFlagInfo* next = flag->next();
128 SkDELETE(flag);
129 flag = next;
130 }
131 if (helpPrinted) {
132 exit(0);
133 }
134}