C++ Client-Side SDK
LaunchDarkly SDK
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 
11 namespace launchdarkly {
12 
42 class 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 
425 bool operator==(Value const& lhs, Value const& rhs);
426 bool operator!=(Value const& lhs, Value const& rhs);
427 
428 bool operator==(Value::Array const& lhs, Value::Array const& rhs);
429 bool operator!=(Value::Array const& lhs, Value::Array const& rhs);
430 
431 bool operator==(Value::Object const& lhs, Value::Object const& rhs);
432 bool 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  */
437 bool 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  */
442 bool 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  */
447 bool 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  */
452 bool 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
Definition: value.hpp:49
Definition: value.hpp:118