C++ Client-Side SDK
LaunchDarkly SDK
Loading...
Searching...
No Matches
value.hpp
1#pragma once
2
3#include <cstddef>
4#include <map>
5#include <optional>
6#include <ostream>
7#include <string>
8#include <variant>
9#include <vector>
10
11namespace launchdarkly {
12
42class Value final {
43 public:
47 class Array {
48 public:
49 struct Iterator {
50 using iterator_category = std::bidirectional_iterator_tag;
51 using difference_type = std::ptrdiff_t;
52 using value_type = Value;
53 using pointer = value_type const*;
54 using reference = value_type const&;
55
56 Iterator(std::vector<Value>::const_iterator iterator);
57
58 reference operator*() const;
59 pointer operator->();
60 Iterator& operator++();
61 Iterator operator++(int);
62
63 Iterator& operator--();
64 Iterator operator--(int);
65
66 friend bool operator==(Iterator const& lhs, Iterator const& rhs) {
67 return lhs.iterator_ == rhs.iterator_;
68 };
69
70 friend bool operator!=(Iterator const& lhs, Iterator const& rhs) {
71 return lhs.iterator_ != rhs.iterator_;
72 };
73
74 private:
75 std::vector<Value>::const_iterator iterator_;
76 };
77
78 friend std::ostream& operator<<(std::ostream& out, Array const& arr) {
79 out << "[";
80 bool first = true;
81 for (auto const& item : arr.vec_) {
82 if (first) {
83 first = false;
84 } else {
85 out << ", ";
86 }
87 out << item;
88 }
89 out << "]";
90 return out;
91 }
92
97 Array(std::vector<Value> vec);
98 Array(std::initializer_list<Value> values) : vec_(values) {}
99 Array() = default;
100
101 Value const& operator[](std::size_t index) const;
102
103 [[nodiscard]] std::size_t Size() const;
104
105 [[nodiscard]] Iterator begin() const;
106
107 [[nodiscard]] Iterator end() const;
108
109 private:
110 std::vector<Value> vec_;
111 };
112
116 class Object {
117 public:
118 struct Iterator {
119 using iterator_category = std::forward_iterator_tag;
120 using difference_type = std::ptrdiff_t;
121
122 using value_type = std::pair<std::string const, Value>;
123 using pointer = value_type const*;
124 using reference = value_type const&;
125
126 Iterator(std::map<std::string, Value>::const_iterator iterator);
127
128 reference operator*() const;
129 pointer operator->();
130 Iterator& operator++();
131 Iterator operator++(int);
132
133 friend bool operator==(Iterator const& lhs, Iterator const& rhs) {
134 return rhs.it_ == lhs.it_;
135 };
136 friend bool operator!=(Iterator const& lhs, Iterator const& rhs) {
137 return lhs.it_ != rhs.it_;
138 };
139
140 private:
141 std::map<std::string, Value>::const_iterator it_;
142 };
143
144 friend std::ostream& operator<<(std::ostream& out, Object const& obj) {
145 out << "{";
146 bool first = true;
147 for (auto const& pair : obj.map_) {
148 if (first) {
149 first = false;
150 } else {
151 out << ", ";
152 }
153 out << "{" << pair.first << ", " << pair.second << "}";
154 }
155 out << "}";
156 return out;
157 }
158
163 Object(std::map<std::string, Value> map) : map_(std::move(map)) {}
164 Object() = default;
165 Object(std::initializer_list<std::pair<std::string, Value>> values);
166
167 /*
168 * Get the Value with the specified key.
169 *
170 * This operates like `.at` on a map, and accessing out of bounds
171 * is invalid.
172 */
173 Value const& operator[](std::string const& key) const;
174
179 [[nodiscard]] std::size_t Size() const;
180
186 [[nodiscard]] std::size_t Count(std::string const& key) const;
187
188 [[nodiscard]] Iterator begin() const;
189
190 [[nodiscard]] Iterator end() const;
191
197 [[nodiscard]] Iterator Find(std::string const& key) const;
198
199 private:
200 std::map<std::string, Value> map_;
201 };
202
207 Value(char const* str);
208
209 enum class Type { kNull, kBool, kNumber, kString, kObject, kArray };
210
214 Value();
215
216 Value(Value const& val) = default;
217 Value(Value&&) = default;
218 Value& operator=(Value const&) = default;
219 Value& operator=(Value&&) = default;
220
225 Value(bool boolean);
226
231 Value(double num);
232
237 Value(int num);
238
243 Value(std::string str);
244
249 Value(std::vector<Value> arr);
250
251 Value(Array arr);
252
253 Value(Object obj);
254
259 Value(std::map<std::string, Value> obj);
260
267 Value(std::initializer_list<Value> values);
268
273 Value(std::optional<std::string> opt_string);
274
278 [[nodiscard]] Type Type() const;
279
287 [[nodiscard]] bool IsNull() const;
288
294 [[nodiscard]] bool IsBool() const;
295
303 [[nodiscard]] bool IsNumber() const;
304
310 [[nodiscard]] bool IsString() const;
311
317 [[nodiscard]] bool IsArray() const;
318
324 [[nodiscard]] bool IsObject() const;
325
332 [[nodiscard]] bool AsBool() const;
333
340 [[nodiscard]] int AsInt() const;
341
342 [[nodiscard]] double AsDouble() const;
343
350 [[nodiscard]] std::string const& AsString() const;
351
358 [[nodiscard]] Array const& AsArray() const;
359
366 [[nodiscard]] Object const& AsObject() const;
367
368 ~Value() = default;
369
374 static Value const& Null();
375
376 friend std::ostream& operator<<(std::ostream& out, Value const& value) {
377 switch (value.Type()) {
378 case Type::kNull:
379 out << "null()";
380 break;
381 case Type::kBool:
382 out << "bool("
383 << (std::get<bool>(value.storage_) ? "true" : "false")
384 << ")";
385 break;
386 case Type::kNumber:
387 out << "number(" << std::get<double>(value.storage_) << ")";
388 break;
389 case Type::kString:
390 out << "string(" << std::get<std::string>(value.storage_)
391 << ")";
392 break;
393 case Type::kObject:
394 out << "object(" << std::get<Object>(value.storage_) << ")";
395 break;
396 case Type::kArray:
397 out << "array(" << std::get<Array>(value.storage_) << ")";
398 break;
399 }
400 return out;
401 }
402
403 operator bool() const { return AsBool(); }
404
405 operator std::string() const { return AsString(); }
406
407 operator double() const { return AsDouble(); }
408
409 operator int() const { return AsInt(); }
410
411 private:
412 struct null_type {};
413
414 std::variant<null_type, bool, double, std::string, Array, Object> storage_;
415
416 // Empty constants used when accessing the wrong type.
417 // These are not inline static const because of this bug:
418 // https://developercommunity.visualstudio.com/t/inline-static-destructors-are-called-multiple-time/1157794
419 static std::string const empty_string_;
420 static Array const empty_vector_;
421 static Object const empty_map_;
422 static Value const null_value_;
423};
424
425bool operator==(Value const& lhs, Value const& rhs);
426bool operator!=(Value const& lhs, Value const& rhs);
427
428bool operator==(Value::Array const& lhs, Value::Array const& rhs);
429bool operator!=(Value::Array const& lhs, Value::Array const& rhs);
430
431bool operator==(Value::Object const& lhs, Value::Object const& rhs);
432bool operator!=(Value::Object const& lhs, Value::Object const& rhs);
433
434/* Returns true if both values are numbers and lhs < rhs. Returns false if
435 * either value is not a number.
436 */
437bool operator<(Value const& lhs, Value const& rhs);
438
439/* Returns true if both values are numbers and lhs > rhs. Returns false if
440 * either value is not a number.
441 */
442bool operator>(Value const& lhs, Value const& rhs);
443
444/* Returns true if both values are numbers and lhs <= rhs. Returns false if
445 * either value is not a number.
446 */
447bool operator<=(Value const& lhs, Value const& rhs);
448
449/* Returns true if both values are numbers and lhs >= rhs. Returns false if
450 * either value is not a number.
451 */
452bool operator>=(Value const& lhs, Value const& rhs);
453
454} // namespace launchdarkly
Definition value.hpp:47
Array(std::vector< Value > vec)
Definition value.cpp:191
Definition value.hpp:116
Iterator Find(std::string const &key) const
Definition value.cpp:228
Object(std::map< std::string, Value > map)
Definition value.hpp:163
std::size_t Size() const
Definition value.cpp:216
std::size_t Count(std::string const &key) const
Definition value.cpp:232
Definition value.hpp:42
Object const & AsObject() const
Definition value.cpp:121
bool IsNumber() const
Definition value.cpp:64
int AsInt() const
Definition value.cpp:93
Value()
Definition value.cpp:13
Array const & AsArray() const
Definition value.cpp:114
bool IsArray() const
Definition value.cpp:72
bool IsObject() const
Definition value.cpp:76
std::string const & AsString() const
Definition value.cpp:107
bool IsNull() const
Definition value.cpp:56
bool IsBool() const
Definition value.cpp:60
bool AsBool() const
Definition value.cpp:86
bool IsString() const
Definition value.cpp:68
static Value const & Null()
Definition value.cpp:80