82 {
83 public:
84 enum FlagType {
86 kInteger,
88 kString,
89 kFlagHandler,
90 kOptionHandler,
91 kNumFlagTypes
92 };
93
94 Flag(
const char*
name,
const char* comment,
void* addr, FlagType
type)
95 : name_(
name), comment_(comment), addr_(
addr), type_(
type) {}
96 Flag(
const char*
name,
const char* comment, FlagHandler handler)
98 comment_(comment),
99 flag_handler_(handler),
100 type_(kFlagHandler) {}
101 Flag(
const char*
name,
const char* comment, OptionHandler handler)
103 comment_(comment),
104 option_handler_(handler),
105 type_(kOptionHandler) {}
106
107 void Print() {
108 if (IsUnrecognized()) {
109 OS::PrintErr("%s: unrecognized\n", name_);
110 return;
111 }
112 switch (type_) {
114 OS::Print("%s: %s (%s)\n", name_, *this->bool_ptr_ ? "true" : "false",
115 comment_);
116 break;
117 }
118 case kInteger: {
119 OS::Print("%s: %d (%s)\n", name_, *this->int_ptr_, comment_);
120 break;
121 }
123 OS::Print(
"%s: %" Pu64 " (%s)\n", name_, *this->uint64_ptr_, comment_);
124 break;
125 }
126 case kString: {
127 if (*this->charp_ptr_ != nullptr) {
128 OS::Print("%s: '%s' (%s)\n", name_, *this->charp_ptr_, comment_);
129 } else {
130 OS::Print("%s: (null) (%s)\n", name_, comment_);
131 }
132 break;
133 }
134 case kOptionHandler:
135 case kFlagHandler: {
136 OS::Print("%s: (%s)\n", name_, comment_);
137 break;
138 }
139 default:
141 break;
142 }
143 }
144
145 bool IsUnrecognized() const {
146 return (type_ == kBoolean) && (bool_ptr_ == nullptr);
147 }
148
149 const char* name_;
150 const char* comment_;
151
152
153
154 Utils::CStringUniquePtr string_value_ =
155 Utils::CreateCStringUniquePtr(nullptr);
156 union {
157 void* addr_;
158 bool* bool_ptr_;
159 int* int_ptr_;
160 uint64_t* uint64_ptr_;
164 };
165 const FlagType type_;
166 bool changed_ = false;
167};
168
169Flag* Flags::Lookup(
const char*
name) {
170 for (intptr_t i = 0; i < num_flags_; i++) {
171 Flag*
flag = flags_[i];
172 if (strcmp(
flag->name_,
name) == 0) {
174 }
175 }
176 return nullptr;
177}
178
179bool Flags::IsSet(
const char*
name) {
181 return (
flag !=
nullptr) && (
flag->type_ == Flag::kBoolean) &&
182 (
flag->bool_ptr_ !=
nullptr) && (*
flag->bool_ptr_ ==
true);
183}
184
185void Flags::Cleanup() {
187 initialized_ = false;
188}
189
190void Flags::AddFlag(Flag*
flag) {
192 if (num_flags_ == capacity_) {
193 if (flags_ == nullptr) {
194 capacity_ = 256;
195 flags_ = new Flag*[capacity_];
196 } else {
197 intptr_t new_capacity = capacity_ * 2;
198 Flag** new_flags = new Flag*[new_capacity];
199 for (intptr_t i = 0; i < num_flags_; i++) {
200 new_flags[i] = flags_[i];
201 }
202 delete[] flags_;
203 flags_ = new_flags;
204 capacity_ = new_capacity;
205 }
206 }
207 flags_[num_flags_++] =
flag;
208}
209
210bool Flags::Register_bool(bool* addr,
212 bool default_value,
213 const char* comment) {
215 if (
flag !=
nullptr) {
217 return default_value;
218 }
219 flag =
new Flag(
name, comment, addr, Flag::kBoolean);
221 return default_value;
222}
223
224int Flags::Register_int(int* addr,
226 int default_value,
227 const char* comment) {
229
230 Flag*
flag =
new Flag(
name, comment, addr, Flag::kInteger);
232
233 return default_value;
234}
235
236uint64_t Flags::Register_uint64_t(uint64_t* addr,
238 uint64_t default_value,
239 const char* comment) {
241
242 Flag*
flag =
new Flag(
name, comment, addr, Flag::kUint64);
244
245 return default_value;
246}
247
248const char* Flags::Register_charp(
charp* addr,
250 const char* default_value,
251 const char* comment) {
253 Flag*
flag =
new Flag(
name, comment, addr, Flag::kString);
255 return default_value;
256}
257
258bool Flags::RegisterFlagHandler(FlagHandler handler,
260 const char* comment) {
262 Flag*
flag =
new Flag(
name, comment, handler);
264 return false;
265}
266
267bool Flags::RegisterOptionHandler(OptionHandler handler,
269 const char* comment) {
271 Flag*
flag =
new Flag(
name, comment, handler);
273 return false;
274}
275
277 intptr_t
len = strlen(
s);
278 for (intptr_t i = 0; i <
len; i++) {
281 }
282 }
283}
284
285bool Flags::SetFlagFromString(Flag*
flag,
const char* argument) {
287 switch (
flag->type_) {
288 case Flag::kBoolean: {
289 if (strcmp(argument, "true") == 0) {
290 *
flag->bool_ptr_ =
true;
291 } else if (strcmp(argument, "false") == 0) {
292 *
flag->bool_ptr_ =
false;
293 } else {
294 return false;
295 }
296 break;
297 }
298 case Flag::kString: {
299 flag->string_value_.reset(argument ==
nullptr ?
nullptr
300 : Utils::StrDup(argument));
301 *
flag->charp_ptr_ =
flag->string_value_.get();
302 break;
303 }
304 case Flag::kInteger: {
305 char* endptr = nullptr;
306 const intptr_t
len = strlen(argument);
308 if ((len > 2) && (argument[0] == '0') && (argument[1] == 'x')) {
310 }
311 int val = strtol(argument, &endptr,
base);
312 if (endptr == argument + len) {
313 *
flag->int_ptr_ = val;
314 } else {
315 return false;
316 }
317 break;
318 }
319 case Flag::kUint64: {
320 char* endptr = nullptr;
321 const intptr_t
len = strlen(argument);
323 if ((len > 2) && (argument[0] == '0') && (argument[1] == 'x')) {
325 }
326 int64_t val = strtoll(argument, &endptr,
base);
327 if (endptr == argument + len) {
328 *
flag->uint64_ptr_ =
static_cast<uint64_t
>(val);
329 } else {
330 return false;
331 }
332 break;
333 }
334 case Flag::kFlagHandler: {
335 if (strcmp(argument, "true") == 0) {
336 (
flag->flag_handler_)(
true);
337 } else if (strcmp(argument, "false") == 0) {
338 (
flag->flag_handler_)(
false);
339 } else {
340 return false;
341 }
342 flag->string_value_.reset(Utils::StrDup(argument));
343 break;
344 }
345 case Flag::kOptionHandler: {
346 flag->string_value_.reset(Utils::StrDup(argument));
347 (
flag->option_handler_)(argument);
348 break;
349 }
350 default: {
352 return false;
353 }
354 }
355 flag->changed_ =
true;
356 return true;
357}
358
359void Flags::Parse(const char* option) {
360
361 const char*
equals = option;
364 }
365
366 const char* argument = nullptr;
367
368
370
371
372 const char* const kNo1Prefix = "no_";
373 const char* const kNo2Prefix = "no-";
374 const intptr_t kNo1PrefixLen = strlen(kNo1Prefix);
375 const intptr_t kNo2PrefixLen = strlen(kNo2Prefix);
376 if (strncmp(option, kNo1Prefix, kNo1PrefixLen) == 0) {
377 option += kNo1PrefixLen;
378 argument = "false";
379 } else if (strncmp(option, kNo2Prefix, kNo2PrefixLen) == 0) {
380 option += kNo2PrefixLen;
381 argument = "false";
382 } else {
383 argument = "true";
384 }
385 } else {
386
388 }
389
390
391 intptr_t name_len =
equals - option;
392 char*
name =
new char[name_len + 1];
393 strncpy(
name, option, name_len);
394 name[name_len] =
'\0';
396
398 if (
flag ==
nullptr) {
399
400 char* new_flag = new char[name_len + 1];
401 strncpy(new_flag, option, name_len);
402 new_flag[name_len] = '\0';
404 Flags::Register_bool(nullptr, new_flag, true, nullptr);
405 } else {
406
407
408 if (!
flag->IsUnrecognized()) {
409 if (!SetFlagFromString(
flag, argument)) {
410 OS::PrintErr("Ignoring flag: %s is an invalid value for flag %s\n",
412 }
413 }
414 }
415
417}
418
420 const char* prefix,
421 intptr_t prefix_length) {
422 intptr_t name_length = strlen(
name);
423 return ((name_length > prefix_length) &&
424 (strncmp(
name, prefix, prefix_length) == 0));
425}
426
427int Flags::CompareFlagNames(
const void*
left,
const void*
right) {
428 const Flag* left_flag = *
reinterpret_cast<const Flag* const*
>(
left);
429 const Flag* right_flag = *
reinterpret_cast<const Flag* const*
>(
right);
430 return strcmp(left_flag->name_, right_flag->name_);
431}
432
433char* Flags::ProcessCommandLineFlags(int number_of_vm_flags,
434 const char** vm_flags) {
435 if (initialized_) {
436 return Utils::StrDup("Flags already set");
437 }
438
439 qsort(flags_, num_flags_, sizeof flags_[0], CompareFlagNames);
440
441 const char*
const kPrefix =
"--";
442 const intptr_t kPrefixLen = strlen(kPrefix);
443
444 int i = 0;
445 while ((i < number_of_vm_flags) &&
447 const char* option = vm_flags[i] + kPrefixLen;
449 i++;
450 }
451
452 if (!FLAG_ignore_unrecognized_flags) {
453 int unrecognized_count = 0;
454 TextBuffer
error(64);
455 for (intptr_t j = 0; j < num_flags_; j++) {
456 Flag*
flag = flags_[j];
457 if (
flag->IsUnrecognized()) {
458 if (unrecognized_count == 0) {
459 error.Printf(
"Unrecognized flags: %s",
flag->name_);
460 } else {
462 }
463 unrecognized_count++;
464 }
465 }
466 if (unrecognized_count > 0) {
467 return error.Steal();
468 }
469 }
470 if (FLAG_print_flags) {
471 PrintFlags();
472 }
473
474 initialized_ = true;
475 return nullptr;
476}
477
478bool Flags::SetFlag(
const char*
name,
const char* value,
const char**
error) {
480 if (
flag ==
nullptr) {
481 *
error =
"Cannot set flag: flag not found";
482 return false;
483 }
484 if (!SetFlagFromString(
flag, value)) {
485 *
error =
"Cannot set flag: invalid value";
486 return false;
487 }
488 return true;
489}
490
491void Flags::PrintFlags() {
492 OS::Print("Flag settings:\n");
493 for (intptr_t i = 0; i < num_flags_; ++i) {
494 flags_[i]->Print();
495 }
496}
497
498#ifndef PRODUCT
499void Flags::PrintFlagToJSONArray(JSONArray* jsarr,
const Flag*
flag) {
500 if (
flag->IsUnrecognized()) {
501 return;
502 }
503 JSONObject jsflag(jsarr);
504 jsflag.AddProperty(
"name",
flag->name_);
505 jsflag.AddProperty(
"comment",
flag->comment_);
506 jsflag.AddProperty(
"modified",
flag->changed_);
507 switch (
flag->type_) {
508 case Flag::kBoolean: {
509 jsflag.AddProperty("_flagType", "Bool");
510 jsflag.AddProperty("valueAsString",
511 (*
flag->bool_ptr_ ?
"true" :
"false"));
512 break;
513 }
514 case Flag::kInteger: {
515 jsflag.AddProperty("_flagType", "Int");
516 jsflag.AddPropertyF(
"valueAsString",
"%d", *
flag->int_ptr_);
517 break;
518 }
519 case Flag::kUint64: {
520 jsflag.AddProperty("_flagType", "UInt64");
521 jsflag.AddPropertyF(
"valueAsString",
"%" Pu64, *
flag->uint64_ptr_);
522 break;
523 }
524 case Flag::kString: {
525 jsflag.AddProperty("_flagType", "String");
526 if (
flag->charp_ptr_ !=
nullptr) {
527 jsflag.AddPropertyF(
"valueAsString",
"%s", *
flag->charp_ptr_);
528 } else {
529
530 }
531 break;
532 }
533 case Flag::kFlagHandler: {
534 jsflag.AddProperty("_flagType", "Bool");
535 const char*
value =
flag->string_value_.get();
536 jsflag.AddProperty(
"valueAsString", value ==
nullptr ?
"false" :
value);
537 break;
538 }
539 case Flag::kOptionHandler: {
540 jsflag.AddProperty("_flagType", "String");
541 if (
flag->string_value_ !=
nullptr) {
542 jsflag.AddProperty(
"valueAsString",
flag->string_value_.get());
543 } else {
544
545 }
546 break;
547 }
548 default:
550 break;
551 }
552}
553
554void Flags::PrintJSON(JSONStream* js) {
555 JSONObject jsobj(js);
556 jsobj.AddProperty("type", "FlagList");
557 JSONArray jsarr(&jsobj, "flags");
558 for (intptr_t i = 0; i < num_flags_; ++i) {
559 PrintFlagToJSONArray(&jsarr, flags_[i]);
560 }
561}
562#endif
563
564}
static bool equals(T *a, T *b)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
FlutterSemanticsFlag flag
const uint8_t uint32_t uint32_t GError ** error
void(* FlagHandler)(bool value)
void(* OptionHandler)(const char *value)
static void Normalize(char *s)
static bool IsValidFlag(const char *name, const char *prefix, intptr_t prefix_length)
bool Parse(const skjson::Value &, T *)