Coverage Report

Created: 2023-09-25 06:27

/src/abseil-cpp/absl/flags/commandlineflag.h
Line
Count
Source (jump to first uncovered line)
1
//
2
// Copyright 2020 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
// -----------------------------------------------------------------------------
17
// File: commandlineflag.h
18
// -----------------------------------------------------------------------------
19
//
20
// This header file defines the `CommandLineFlag`, which acts as a type-erased
21
// handle for accessing metadata about the Abseil Flag in question.
22
//
23
// Because an actual Abseil flag is of an unspecified type, you should not
24
// manipulate or interact directly with objects of that type. Instead, use the
25
// CommandLineFlag type as an intermediary.
26
#ifndef ABSL_FLAGS_COMMANDLINEFLAG_H_
27
#define ABSL_FLAGS_COMMANDLINEFLAG_H_
28
29
#include <memory>
30
#include <string>
31
32
#include "absl/base/config.h"
33
#include "absl/base/internal/fast_type_id.h"
34
#include "absl/flags/internal/commandlineflag.h"
35
#include "absl/strings/string_view.h"
36
#include "absl/types/optional.h"
37
38
namespace absl {
39
ABSL_NAMESPACE_BEGIN
40
namespace flags_internal {
41
class PrivateHandleAccessor;
42
}  // namespace flags_internal
43
44
// CommandLineFlag
45
//
46
// This type acts as a type-erased handle for an instance of an Abseil Flag and
47
// holds reflection information pertaining to that flag. Use CommandLineFlag to
48
// access a flag's name, location, help string etc.
49
//
50
// To obtain an absl::CommandLineFlag, invoke `absl::FindCommandLineFlag()`
51
// passing it the flag name string.
52
//
53
// Example:
54
//
55
//   // Obtain reflection handle for a flag named "flagname".
56
//   const absl::CommandLineFlag* my_flag_data =
57
//        absl::FindCommandLineFlag("flagname");
58
//
59
//   // Now you can get flag info from that reflection handle.
60
//   std::string flag_location = my_flag_data->Filename();
61
//   ...
62
class CommandLineFlag {
63
 public:
64
0
  constexpr CommandLineFlag() = default;
65
66
  // Not copyable/assignable.
67
  CommandLineFlag(const CommandLineFlag&) = delete;
68
  CommandLineFlag& operator=(const CommandLineFlag&) = delete;
69
70
  // absl::CommandLineFlag::IsOfType()
71
  //
72
  // Return true iff flag has type T.
73
  template <typename T>
74
  inline bool IsOfType() const {
75
    return TypeId() == base_internal::FastTypeId<T>();
76
  }
77
78
  // absl::CommandLineFlag::TryGet()
79
  //
80
  // Attempts to retrieve the flag value. Returns value on success,
81
  // absl::nullopt otherwise.
82
  template <typename T>
83
  absl::optional<T> TryGet() const {
84
    if (IsRetired() || !IsOfType<T>()) {
85
      return absl::nullopt;
86
    }
87
88
    // Implementation notes:
89
    //
90
    // We are wrapping a union around the value of `T` to serve three purposes:
91
    //
92
    //  1. `U.value` has correct size and alignment for a value of type `T`
93
    //  2. The `U.value` constructor is not invoked since U's constructor does
94
    //     not do it explicitly.
95
    //  3. The `U.value` destructor is invoked since U's destructor does it
96
    //     explicitly. This makes `U` a kind of RAII wrapper around non default
97
    //     constructible value of T, which is destructed when we leave the
98
    //     scope. We do need to destroy U.value, which is constructed by
99
    //     CommandLineFlag::Read even though we left it in a moved-from state
100
    //     after std::move.
101
    //
102
    // All of this serves to avoid requiring `T` being default constructible.
103
    union U {
104
      T value;
105
      U() {}
106
      ~U() { value.~T(); }
107
    };
108
    U u;
109
110
    Read(&u.value);
111
    // allow retired flags to be "read", so we can report invalid access.
112
    if (IsRetired()) {
113
      return absl::nullopt;
114
    }
115
    return std::move(u.value);
116
  }
117
118
  // absl::CommandLineFlag::Name()
119
  //
120
  // Returns name of this flag.
121
  virtual absl::string_view Name() const = 0;
122
123
  // absl::CommandLineFlag::Filename()
124
  //
125
  // Returns name of the file where this flag is defined.
126
  virtual std::string Filename() const = 0;
127
128
  // absl::CommandLineFlag::Help()
129
  //
130
  // Returns help message associated with this flag.
131
  virtual std::string Help() const = 0;
132
133
  // absl::CommandLineFlag::IsRetired()
134
  //
135
  // Returns true iff this object corresponds to retired flag.
136
  virtual bool IsRetired() const;
137
138
  // absl::CommandLineFlag::DefaultValue()
139
  //
140
  // Returns the default value for this flag.
141
  virtual std::string DefaultValue() const = 0;
142
143
  // absl::CommandLineFlag::CurrentValue()
144
  //
145
  // Returns the current value for this flag.
146
  virtual std::string CurrentValue() const = 0;
147
148
  // absl::CommandLineFlag::ParseFrom()
149
  //
150
  // Sets the value of the flag based on specified string `value`. If the flag
151
  // was successfully set to new value, it returns true. Otherwise, sets `error`
152
  // to indicate the error, leaves the flag unchanged, and returns false.
153
  bool ParseFrom(absl::string_view value, std::string* error);
154
155
 protected:
156
  ~CommandLineFlag() = default;
157
158
 private:
159
  friend class flags_internal::PrivateHandleAccessor;
160
161
  // Sets the value of the flag based on specified string `value`. If the flag
162
  // was successfully set to new value, it returns true. Otherwise, sets `error`
163
  // to indicate the error, leaves the flag unchanged, and returns false. There
164
  // are three ways to set the flag's value:
165
  //  * Update the current flag value
166
  //  * Update the flag's default value
167
  //  * Update the current flag value if it was never set before
168
  // The mode is selected based on `set_mode` parameter.
169
  virtual bool ParseFrom(absl::string_view value,
170
                         flags_internal::FlagSettingMode set_mode,
171
                         flags_internal::ValueSource source,
172
                         std::string& error) = 0;
173
174
  // Returns id of the flag's value type.
175
  virtual flags_internal::FlagFastTypeId TypeId() const = 0;
176
177
  // Interface to save flag to some persistent state. Returns current flag state
178
  // or nullptr if flag does not support saving and restoring a state.
179
  virtual std::unique_ptr<flags_internal::FlagStateInterface> SaveState() = 0;
180
181
  // Copy-construct a new value of the flag's type in a memory referenced by
182
  // the dst based on the current flag's value.
183
  virtual void Read(void* dst) const = 0;
184
185
  // To be deleted. Used to return true if flag's current value originated from
186
  // command line.
187
  virtual bool IsSpecifiedOnCommandLine() const = 0;
188
189
  // Validates supplied value using validator or parseflag routine
190
  virtual bool ValidateInputValue(absl::string_view value) const = 0;
191
192
  // Checks that flags default value can be converted to string and back to the
193
  // flag's value type.
194
  virtual void CheckDefaultValueParsingRoundtrip() const = 0;
195
};
196
197
ABSL_NAMESPACE_END
198
}  // namespace absl
199
200
#endif  // ABSL_FLAGS_COMMANDLINEFLAG_H_