• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_COMMANDLINEFLAG_H_
17 #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
18 
19 #include <stddef.h>
20 #include <stdint.h>
21 
22 #include <memory>
23 #include <string>
24 #include <typeinfo>
25 
26 #include "absl/base/config.h"
27 #include "absl/base/macros.h"
28 #include "absl/flags/config.h"
29 #include "absl/flags/marshalling.h"
30 #include "absl/strings/string_view.h"
31 #include "absl/types/optional.h"
32 
33 namespace absl {
34 ABSL_NAMESPACE_BEGIN
35 namespace flags_internal {
36 
37 // An alias for flag static type id. Values of type identify the flag value type
38 // simialarly to typeid(T), but without relying on RTTI being available. In most
39 // cases this id is enough to uniquely identify the flag's value type. In a few
40 // cases we'll have to resort to using actual RTTI implementation if it is
41 // available.
42 using FlagStaticTypeId = void* (*)();
43 
44 // Address of this function template is used in current implementation as a flag
45 // static type id.
46 template <typename T>
FlagStaticTypeIdGen()47 void* FlagStaticTypeIdGen() {
48 #if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI)
49   return const_cast<std::type_info*>(&typeid(T));
50 #else
51   return nullptr;
52 #endif
53 }
54 
55 // Options that control SetCommandLineOptionWithMode.
56 enum FlagSettingMode {
57   // update the flag's value unconditionally (can call this multiple times).
58   SET_FLAGS_VALUE,
59   // update the flag's value, but *only if* it has not yet been updated
60   // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
61   SET_FLAG_IF_DEFAULT,
62   // set the flag's default value to this.  If the flag has not been updated
63   // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
64   // change the flag's current value to the new default value as well.
65   SET_FLAGS_DEFAULT
66 };
67 
68 // Options that control SetFromString: Source of a value.
69 enum ValueSource {
70   // Flag is being set by value specified on a command line.
71   kCommandLine,
72   // Flag is being set by value specified in the code.
73   kProgrammaticChange,
74 };
75 
76 // Handle to FlagState objects. Specific flag state objects will restore state
77 // of a flag produced this flag state from method CommandLineFlag::SaveState().
78 class FlagStateInterface {
79  public:
~FlagStateInterface()80   virtual ~FlagStateInterface() {}
81 
82   // Restores the flag originated this object to the saved state.
83   virtual void Restore() const = 0;
84 };
85 
86 // Holds all information for a flag.
87 class CommandLineFlag {
88  public:
89   constexpr CommandLineFlag() = default;
90 
91   // Not copyable/assignable.
92   CommandLineFlag(const CommandLineFlag&) = delete;
93   CommandLineFlag& operator=(const CommandLineFlag&) = delete;
94 
95   // Non-polymorphic access methods.
96 
97   // Return true iff flag has type T.
98   template <typename T>
IsOfType()99   inline bool IsOfType() const {
100     return TypeId() == &flags_internal::FlagStaticTypeIdGen<T>;
101   }
102 
103   // Attempts to retrieve the flag value. Returns value on success,
104   // absl::nullopt otherwise.
105   template <typename T>
Get()106   absl::optional<T> Get() const {
107     if (IsRetired() || !IsOfType<T>()) {
108       return absl::nullopt;
109     }
110 
111     // Implementation notes:
112     //
113     // We are wrapping a union around the value of `T` to serve three purposes:
114     //
115     //  1. `U.value` has correct size and alignment for a value of type `T`
116     //  2. The `U.value` constructor is not invoked since U's constructor does
117     //     not do it explicitly.
118     //  3. The `U.value` destructor is invoked since U's destructor does it
119     //     explicitly. This makes `U` a kind of RAII wrapper around non default
120     //     constructible value of T, which is destructed when we leave the
121     //     scope. We do need to destroy U.value, which is constructed by
122     //     CommandLineFlag::Read even though we left it in a moved-from state
123     //     after std::move.
124     //
125     // All of this serves to avoid requiring `T` being default constructible.
126     union U {
127       T value;
128       U() {}
129       ~U() { value.~T(); }
130     };
131     U u;
132 
133     Read(&u.value);
134     return std::move(u.value);
135   }
136 
137   // Polymorphic access methods
138 
139   // Returns name of this flag.
140   virtual absl::string_view Name() const = 0;
141   // Returns name of the file where this flag is defined.
142   virtual std::string Filename() const = 0;
143   // Returns name of the flag's value type for some built-in types or empty
144   // std::string.
145   virtual absl::string_view Typename() const = 0;
146   // Returns help message associated with this flag.
147   virtual std::string Help() const = 0;
148   // Returns true iff this object corresponds to retired flag.
IsRetired()149   virtual bool IsRetired() const { return false; }
150   // Returns true iff this is a handle to an Abseil Flag.
IsAbseilFlag()151   virtual bool IsAbseilFlag() const { return true; }
152   // Returns id of the flag's value type.
153   virtual FlagStaticTypeId TypeId() const = 0;
154   virtual bool IsModified() const = 0;
155   virtual bool IsSpecifiedOnCommandLine() const = 0;
156   virtual std::string DefaultValue() const = 0;
157   virtual std::string CurrentValue() const = 0;
158 
159   // Interfaces to operate on validators.
160   virtual bool ValidateInputValue(absl::string_view value) const = 0;
161 
162   // Interface to save flag to some persistent state. Returns current flag state
163   // or nullptr if flag does not support saving and restoring a state.
164   virtual std::unique_ptr<FlagStateInterface> SaveState() = 0;
165 
166   // Sets the value of the flag based on specified std::string `value`. If the flag
167   // was successfully set to new value, it returns true. Otherwise, sets `error`
168   // to indicate the error, leaves the flag unchanged, and returns false. There
169   // are three ways to set the flag's value:
170   //  * Update the current flag value
171   //  * Update the flag's default value
172   //  * Update the current flag value if it was never set before
173   // The mode is selected based on `set_mode` parameter.
174   virtual bool SetFromString(absl::string_view value,
175                              flags_internal::FlagSettingMode set_mode,
176                              flags_internal::ValueSource source,
177                              std::string* error) = 0;
178 
179   // Checks that flags default value can be converted to std::string and back to the
180   // flag's value type.
181   virtual void CheckDefaultValueParsingRoundtrip() const = 0;
182 
183  protected:
184   ~CommandLineFlag() = default;
185 
186  private:
187   // Copy-construct a new value of the flag's type in a memory referenced by
188   // the dst based on the current flag's value.
189   virtual void Read(void* dst) const = 0;
190 };
191 
192 // This macro is the "source of truth" for the list of supported flag built-in
193 // types.
194 #define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \
195   A(bool)                                    \
196   A(short)                                   \
197   A(unsigned short)                          \
198   A(int)                                     \
199   A(unsigned int)                            \
200   A(long)                                    \
201   A(unsigned long)                           \
202   A(long long)                               \
203   A(unsigned long long)                      \
204   A(double)                                  \
205   A(float)                                   \
206   A(std::string)                             \
207   A(std::vector<std::string>)
208 
209 }  // namespace flags_internal
210 ABSL_NAMESPACE_END
211 }  // namespace absl
212 
213 #endif  // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
214