Coverage Report

Created: 2024-09-23 06:29

/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
63
// These are only used as constexpr global objects.
64
// They do not use a virtual destructor to simplify their implementation.
65
// They are not destroyed except at program exit, so leaks do not matter.
66
#if defined(__GNUC__) && !defined(__clang__)
67
#pragma GCC diagnostic push
68
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
69
#endif
70
class CommandLineFlag {
71
 public:
72
0
  constexpr CommandLineFlag() = default;
73
74
  // Not copyable/assignable.
75
  CommandLineFlag(const CommandLineFlag&) = delete;
76
  CommandLineFlag& operator=(const CommandLineFlag&) = delete;
77
78
  // absl::CommandLineFlag::IsOfType()
79
  //
80
  // Return true iff flag has type T.
81
  template <typename T>
82
  inline bool IsOfType() const {
83
    return TypeId() == base_internal::FastTypeId<T>();
84
  }
85
86
  // absl::CommandLineFlag::TryGet()
87
  //
88
  // Attempts to retrieve the flag value. Returns value on success,
89
  // absl::nullopt otherwise.
90
  template <typename T>
91
  absl::optional<T> TryGet() const {
92
    if (IsRetired() || !IsOfType<T>()) {
93
      return absl::nullopt;
94
    }
95
96
    // Implementation notes:
97
    //
98
    // We are wrapping a union around the value of `T` to serve three purposes:
99
    //
100
    //  1. `U.value` has correct size and alignment for a value of type `T`
101
    //  2. The `U.value` constructor is not invoked since U's constructor does
102
    //     not do it explicitly.
103
    //  3. The `U.value` destructor is invoked since U's destructor does it
104
    //     explicitly. This makes `U` a kind of RAII wrapper around non default
105
    //     constructible value of T, which is destructed when we leave the
106
    //     scope. We do need to destroy U.value, which is constructed by
107
    //     CommandLineFlag::Read even though we left it in a moved-from state
108
    //     after std::move.
109
    //
110
    // All of this serves to avoid requiring `T` being default constructible.
111
    union U {
112
      T value;
113
      U() {}
114
      ~U() { value.~T(); }
115
    };
116
    U u;
117
118
    Read(&u.value);
119
    // allow retired flags to be "read", so we can report invalid access.
120
    if (IsRetired()) {
121
      return absl::nullopt;
122
    }
123
    return std::move(u.value);
124
  }
125
126
  // absl::CommandLineFlag::Name()
127
  //
128
  // Returns name of this flag.
129
  virtual absl::string_view Name() const = 0;
130
131
  // absl::CommandLineFlag::Filename()
132
  //
133
  // Returns name of the file where this flag is defined.
134
  virtual std::string Filename() const = 0;
135
136
  // absl::CommandLineFlag::Help()
137
  //
138
  // Returns help message associated with this flag.
139
  virtual std::string Help() const = 0;
140
141
  // absl::CommandLineFlag::IsRetired()
142
  //
143
  // Returns true iff this object corresponds to retired flag.
144
  virtual bool IsRetired() const;
145
146
  // absl::CommandLineFlag::DefaultValue()
147
  //
148
  // Returns the default value for this flag.
149
  virtual std::string DefaultValue() const = 0;
150
151
  // absl::CommandLineFlag::CurrentValue()
152
  //
153
  // Returns the current value for this flag.
154
  virtual std::string CurrentValue() const = 0;
155
156
  // absl::CommandLineFlag::ParseFrom()
157
  //
158
  // Sets the value of the flag based on specified string `value`. If the flag
159
  // was successfully set to new value, it returns true. Otherwise, sets `error`
160
  // to indicate the error, leaves the flag unchanged, and returns false.
161
  bool ParseFrom(absl::string_view value, std::string* error);
162
163
 protected:
164
  ~CommandLineFlag() = default;
165
166
 private:
167
  friend class flags_internal::PrivateHandleAccessor;
168
169
  // Sets the value of the flag based on specified string `value`. If the flag
170
  // was successfully set to new value, it returns true. Otherwise, sets `error`
171
  // to indicate the error, leaves the flag unchanged, and returns false. There
172
  // are three ways to set the flag's value:
173
  //  * Update the current flag value
174
  //  * Update the flag's default value
175
  //  * Update the current flag value if it was never set before
176
  // The mode is selected based on `set_mode` parameter.
177
  virtual bool ParseFrom(absl::string_view value,
178
                         flags_internal::FlagSettingMode set_mode,
179
                         flags_internal::ValueSource source,
180
                         std::string& error) = 0;
181
182
  // Returns id of the flag's value type.
183
  virtual flags_internal::FlagFastTypeId TypeId() const = 0;
184
185
  // Interface to save flag to some persistent state. Returns current flag state
186
  // or nullptr if flag does not support saving and restoring a state.
187
  virtual std::unique_ptr<flags_internal::FlagStateInterface> SaveState() = 0;
188
189
  // Copy-construct a new value of the flag's type in a memory referenced by
190
  // the dst based on the current flag's value.
191
  virtual void Read(void* dst) const = 0;
192
193
  // To be deleted. Used to return true if flag's current value originated from
194
  // command line.
195
  virtual bool IsSpecifiedOnCommandLine() const = 0;
196
197
  // Validates supplied value using validator or parseflag routine
198
  virtual bool ValidateInputValue(absl::string_view value) const = 0;
199
200
  // Checks that flags default value can be converted to string and back to the
201
  // flag's value type.
202
  virtual void CheckDefaultValueParsingRoundtrip() const = 0;
203
};
204
#if defined(__GNUC__) && !defined(__clang__)
205
#pragma GCC diagnostic pop
206
#endif
207
208
ABSL_NAMESPACE_END
209
}  // namespace absl
210
211
#endif  // ABSL_FLAGS_COMMANDLINEFLAG_H_