| 1 | // | 
|---|
| 2 | // Copyright 2019 The Abseil Authors. | 
|---|
| 3 | // | 
|---|
| 4 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|---|
| 5 | // you may not use this file except in compliance with the License. | 
|---|
| 6 | // You may obtain a copy of the License at | 
|---|
| 7 | // | 
|---|
| 8 | //      https://www.apache.org/licenses/LICENSE-2.0 | 
|---|
| 9 | // | 
|---|
| 10 | // Unless required by applicable law or agreed to in writing, software | 
|---|
| 11 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|---|
| 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|---|
| 13 | // See the License for the specific language governing permissions and | 
|---|
| 14 | // limitations under the License. | 
|---|
| 15 |  | 
|---|
| 16 | #ifndef ABSL_FLAGS_INTERNAL_REGISTRY_H_ | 
|---|
| 17 | #define ABSL_FLAGS_INTERNAL_REGISTRY_H_ | 
|---|
| 18 |  | 
|---|
| 19 | #include <functional> | 
|---|
| 20 | #include <map> | 
|---|
| 21 | #include <string> | 
|---|
| 22 |  | 
|---|
| 23 | #include "absl/base/macros.h" | 
|---|
| 24 | #include "absl/flags/internal/commandlineflag.h" | 
|---|
| 25 |  | 
|---|
| 26 | // -------------------------------------------------------------------- | 
|---|
| 27 | // Global flags registry API. | 
|---|
| 28 |  | 
|---|
| 29 | namespace absl { | 
|---|
| 30 | namespace flags_internal { | 
|---|
| 31 |  | 
|---|
| 32 | // CommandLineFlagInfo holds all information for a flag. | 
|---|
| 33 | struct CommandLineFlagInfo { | 
|---|
| 34 | std::string name;           // the name of the flag | 
|---|
| 35 | std::string type;           // DO NOT use. Use flag->IsOfType<T>() instead. | 
|---|
| 36 | std::string description;    // the "help text" associated with the flag | 
|---|
| 37 | std::string current_value;  // the current value, as a std::string | 
|---|
| 38 | std::string default_value;  // the default value, as a std::string | 
|---|
| 39 | std::string filename;       // 'cleaned' version of filename holding the flag | 
|---|
| 40 | bool has_validator_fn;  // true if RegisterFlagValidator called on this flag | 
|---|
| 41 |  | 
|---|
| 42 | bool is_default;  // true if the flag has the default value and | 
|---|
| 43 | // has not been set explicitly from the cmdline | 
|---|
| 44 | // or via SetCommandLineOption. | 
|---|
| 45 |  | 
|---|
| 46 | // nullptr for ABSL_FLAG.  A pointer to the flag's current value | 
|---|
| 47 | // otherwise.  E.g., for DEFINE_int32(foo, ...), flag_ptr will be | 
|---|
| 48 | // &FLAGS_foo. | 
|---|
| 49 | const void* flag_ptr; | 
|---|
| 50 | }; | 
|---|
| 51 |  | 
|---|
| 52 | //----------------------------------------------------------------------------- | 
|---|
| 53 |  | 
|---|
| 54 | void FillCommandLineFlagInfo(CommandLineFlag* flag, | 
|---|
| 55 | CommandLineFlagInfo* result); | 
|---|
| 56 |  | 
|---|
| 57 | //----------------------------------------------------------------------------- | 
|---|
| 58 |  | 
|---|
| 59 | CommandLineFlag* FindCommandLineFlag(absl::string_view name); | 
|---|
| 60 | CommandLineFlag* FindCommandLineV1Flag(const void* flag_ptr); | 
|---|
| 61 | CommandLineFlag* FindRetiredFlag(absl::string_view name); | 
|---|
| 62 |  | 
|---|
| 63 | // Executes specified visitor for each non-retired flag in the registry. | 
|---|
| 64 | // Requires the caller hold the registry lock. | 
|---|
| 65 | void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor); | 
|---|
| 66 | // Executes specified visitor for each non-retired flag in the registry. While | 
|---|
| 67 | // callback are executed, the registry is locked and can't be changed. | 
|---|
| 68 | void ForEachFlag(std::function<void(CommandLineFlag*)> visitor); | 
|---|
| 69 |  | 
|---|
| 70 | //----------------------------------------------------------------------------- | 
|---|
| 71 |  | 
|---|
| 72 | // Store the list of all flags in *OUTPUT, sorted by file. | 
|---|
| 73 | void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT); | 
|---|
| 74 |  | 
|---|
| 75 | //----------------------------------------------------------------------------- | 
|---|
| 76 |  | 
|---|
| 77 | bool RegisterCommandLineFlag(CommandLineFlag*, const void* ptr = nullptr); | 
|---|
| 78 |  | 
|---|
| 79 | //----------------------------------------------------------------------------- | 
|---|
| 80 | // Retired registrations: | 
|---|
| 81 | // | 
|---|
| 82 | // Retired flag registrations are treated specially. A 'retired' flag is | 
|---|
| 83 | // provided only for compatibility with automated invocations that still | 
|---|
| 84 | // name it.  A 'retired' flag: | 
|---|
| 85 | //   - is not bound to a C++ FLAGS_ reference. | 
|---|
| 86 | //   - has a type and a value, but that value is intentionally inaccessible. | 
|---|
| 87 | //   - does not appear in --help messages. | 
|---|
| 88 | //   - is fully supported by _all_ flag parsing routines. | 
|---|
| 89 | //   - consumes args normally, and complains about type mismatches in its | 
|---|
| 90 | //     argument. | 
|---|
| 91 | //   - emits a complaint but does not die (e.g. LOG(ERROR)) if it is | 
|---|
| 92 | //     accessed by name through the flags API for parsing or otherwise. | 
|---|
| 93 | // | 
|---|
| 94 | // The registrations for a flag happen in an unspecified order as the | 
|---|
| 95 | // initializers for the namespace-scope objects of a program are run. | 
|---|
| 96 | // Any number of weak registrations for a flag can weakly define the flag. | 
|---|
| 97 | // One non-weak registration will upgrade the flag from weak to non-weak. | 
|---|
| 98 | // Further weak registrations of a non-weak flag are ignored. | 
|---|
| 99 | // | 
|---|
| 100 | // This mechanism is designed to support moving dead flags into a | 
|---|
| 101 | // 'graveyard' library.  An example migration: | 
|---|
| 102 | // | 
|---|
| 103 | //   0: Remove references to this FLAGS_flagname in the C++ codebase. | 
|---|
| 104 | //   1: Register as 'retired' in old_lib. | 
|---|
| 105 | //   2: Make old_lib depend on graveyard. | 
|---|
| 106 | //   3: Add a redundant 'retired' registration to graveyard. | 
|---|
| 107 | //   4: Remove the old_lib 'retired' registration. | 
|---|
| 108 | //   5: Eventually delete the graveyard registration entirely. | 
|---|
| 109 | // | 
|---|
| 110 | // Returns bool to enable use in namespace-scope initializers. | 
|---|
| 111 | // For example: | 
|---|
| 112 | // | 
|---|
| 113 | //   static const bool dummy = base::RetiredFlag<int32_t>("myflag"); | 
|---|
| 114 | // | 
|---|
| 115 | // Or to declare several at once: | 
|---|
| 116 | // | 
|---|
| 117 | //   static bool dummies[] = { | 
|---|
| 118 | //       base::RetiredFlag<std::string>("some_string_flag"), | 
|---|
| 119 | //       base::RetiredFlag<double>("some_double_flag"), | 
|---|
| 120 | //       base::RetiredFlag<int32_t>("some_int32_flag") | 
|---|
| 121 | //   }; | 
|---|
| 122 |  | 
|---|
| 123 | // Retire flag with name "name" and type indicated by ops. | 
|---|
| 124 | bool Retire(FlagOpFn ops, FlagMarshallingOpFn marshalling_ops, | 
|---|
| 125 | const char* name); | 
|---|
| 126 |  | 
|---|
| 127 | // Registered a retired flag with name 'flag_name' and type 'T'. | 
|---|
| 128 | template <typename T> | 
|---|
| 129 | inline bool RetiredFlag(const char* flag_name) { | 
|---|
| 130 | return flags_internal::Retire(flags_internal::FlagOps<T>, | 
|---|
| 131 | flags_internal::FlagMarshallingOps<T>, | 
|---|
| 132 | flag_name); | 
|---|
| 133 | } | 
|---|
| 134 |  | 
|---|
| 135 | // If the flag is retired, returns true and indicates in |*type_is_bool| | 
|---|
| 136 | // whether the type of the retired flag is a bool. | 
|---|
| 137 | // Only to be called by code that needs to explicitly ignore retired flags. | 
|---|
| 138 | bool IsRetiredFlag(absl::string_view name, bool* type_is_bool); | 
|---|
| 139 |  | 
|---|
| 140 | //----------------------------------------------------------------------------- | 
|---|
| 141 | // Saves the states (value, default value, whether the user has set | 
|---|
| 142 | // the flag, registered validators, etc) of all flags, and restores | 
|---|
| 143 | // them when the FlagSaver is destroyed. | 
|---|
| 144 | // | 
|---|
| 145 | // This class is thread-safe.  However, its destructor writes to | 
|---|
| 146 | // exactly the set of flags that have changed value during its | 
|---|
| 147 | // lifetime, so concurrent _direct_ access to those flags | 
|---|
| 148 | // (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe. | 
|---|
| 149 |  | 
|---|
| 150 | class FlagSaver { | 
|---|
| 151 | public: | 
|---|
| 152 | FlagSaver(); | 
|---|
| 153 | ~FlagSaver(); | 
|---|
| 154 |  | 
|---|
| 155 | FlagSaver(const FlagSaver&) = delete; | 
|---|
| 156 | void operator=(const FlagSaver&) = delete; | 
|---|
| 157 |  | 
|---|
| 158 | // Prevents saver from restoring the saved state of flags. | 
|---|
| 159 | void Ignore(); | 
|---|
| 160 |  | 
|---|
| 161 | private: | 
|---|
| 162 | class FlagSaverImpl* impl_;  // we use pimpl here to keep API steady | 
|---|
| 163 | }; | 
|---|
| 164 |  | 
|---|
| 165 | }  // namespace flags_internal | 
|---|
| 166 | }  // namespace absl | 
|---|
| 167 |  | 
|---|
| 168 | #endif  // ABSL_FLAGS_INTERNAL_REGISTRY_H_ | 
|---|
| 169 |  | 
|---|