libfilezilla
json.hpp
Go to the documentation of this file.
1 #ifndef LIBFILEZILLA_JSON_HEADER
2 #define LIBFILEZILLA_JSON_HEADER
3 
7 #include "string.hpp"
8 
9 #include <map>
10 #include <type_traits>
11 #include <variant>
12 
13 namespace fz {
14 
16 enum class json_type {
17  none,
18  null,
19  object,
20  array,
21  string,
22  number,
23  boolean
24 };
25 
26 class buffer;
27 
30 class FZ_PUBLIC_SYMBOL json final
31 {
32 public:
33  json() noexcept = default;
34  json(json const&) = default;
35  json(json &&) noexcept = default;
36 
38  explicit json(json_type t);
39 
40  json_type type() const {
41  return static_cast<json_type>(value_.index());
42  }
43 
45  std::string string_value() const;
46 
48  std::wstring wstring_value() const {
49  return fz::to_wstring_from_utf8(string_value());
50  }
51 
52 
54  template<typename T, std::enable_if_t<std::is_integral_v<typename std::decay_t<T>>, int> = 0>
55  T number_value() const {
56  return static_cast<T>(number_value_integer());
57  }
58 
60  template<typename T, std::enable_if_t<std::is_floating_point_v<typename std::decay_t<T>>, int> = 0>
61  T number_value() const {
62  return static_cast<T>(number_value_double());
63  }
64 
66  bool bool_value() const;
67 
69  void erase(std::string const& name);
70 
72  json const& operator[](std::string const& name) const;
73 
80  json& operator[](std::string const& name);
81 
83  json const& operator[](size_t i) const;
84 
91  json& operator[](size_t i);
92 
94  size_t children() const;
95 
97  template<typename Bool, std::enable_if_t<std::is_same_v<bool, typename std::decay_t<Bool>>, int> = 0>
98  json& operator=(Bool b) {
99  value_ = b;
100  return *this;
101  }
102 
104  template<typename T, std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<bool, typename std::decay_t<T>>, int> = 0>
105  json& operator=(T n) {
106  value_.emplace<std::size_t(json_type::number)>(fz::to_string(n));
107  return *this;
108  }
109 
114  json& operator=(std::string_view const& v);
115 
117  json& operator=(std::wstring_view const& v) {
118  return *this = to_utf8(v);
119  }
120 
121  json& operator=(json const&);
122  json& operator=(json &&) noexcept;
123 
124  explicit operator bool() const { return type() != json_type::none; }
125 
126  bool has_non_null_value() const {
127  return type() != fz::json_type::none && type() != fz::json_type::null;
128  }
129 
130  bool is_null() const { return type() == fz::json_type::null; }
131  bool is_object() const { return type() == fz::json_type::object; }
132  bool is_array() const { return type() == fz::json_type::array; }
133  bool is_number() const { return type() == fz::json_type::number; }
134  bool is_boolean() const { return type() == fz::json_type::boolean; }
135 
141  std::string to_string(bool pretty = false, size_t depth = 0) const;
142 
150  void to_string(std::string & ret, bool pretty = false, size_t depth = 0) const;
151 
156  static json parse(std::string_view const& v, size_t max_depth = 20);
157  static json parse(fz::buffer const& b, size_t max_depth = 20);
158 
159  void clear();
160 
161 private:
162  void to_string_impl(std::string & ret, bool pretty = false, size_t depth = 0) const;
163 
164  uint64_t number_value_integer() const;
165  double number_value_double() const;
166 
167  bool FZ_PRIVATE_SYMBOL check_type(json_type t);
168  void FZ_PRIVATE_SYMBOL set_type(json_type t);
169 
170  static json FZ_PRIVATE_SYMBOL parse(char const*& p, char const* end, size_t max_depth);
171 
172  typedef std::variant<
173  std::monostate, // json_type::none
174  std::nullptr_t, // json_type::null
175  std::map<std::string, json, std::less<>>, // json_type::object
176  std::vector<json>, // json_type::array
177  std::string, // json_type::string,
178  std::string, // json_type::number,
179  bool // json_type::boolean
180  > value_type;
181  value_type value_;
182 };
183 
184 template <bool isconst>
185 struct json_array_iterator final {
186  using json_ref_t = std::conditional_t<isconst, json const&, json &>;
187 
188  struct sentinel final {};
189 
190  json_array_iterator(json_ref_t j)
191  // 0 if it's an array, -1 otherwise
192  : idx_((j.type() == json_type::array)-1)
193  , json_(j)
194  {}
195 
196  json_array_iterator & operator++()
197  {
198  ++idx_;
199 
200  return *this;
201  }
202 
203  json_ref_t operator*() const
204  {
205  return json_[idx_];
206  }
207 
208  bool operator!=(json_array_iterator::sentinel const&) const
209  {
210  return idx_ < json_.children();
211  }
212 
213 private:
214  std::size_t idx_;
215  json_ref_t json_;
216 };
217 
218 inline json_array_iterator<false> begin(json &j) { return {j}; }
219 inline json_array_iterator<false>::sentinel end(json &) { return {}; }
220 
221 inline json_array_iterator<true> begin(json const& j) { return {j}; }
222 inline json_array_iterator<true>::sentinel end(json const&) { return {}; }
223 
224 }
225 
226 #endif
json & operator=(T n)
Sets type to number and assigns value.
Definition: json.hpp:105
std::wstring wstring_value() const
Returns string, number and boolean values as wstring.
Definition: json.hpp:48
std::string to_utf8(std::string_view const &in)
Converts from std::string in native encoding into std::string in UTF-8.
The explicit null value.
Definition: json.hpp:185
std::wstring to_wstring_from_utf8(std::string_view const &in)
Converts from std::string in UTF-8 into std::wstring.
Definition: json.hpp:188
String types and assorted functions.
json parser/builder
Definition: json.hpp:30
The namespace used by libfilezilla.
Definition: apply.hpp:17
json_type
Types of JSON values.
Definition: json.hpp:16
json & operator=(std::wstring_view const &v)
Sets type to string and assigns value.
Definition: json.hpp:117
The buffer class is a simple buffer where data can be appended at the end and consumed at the front...
Definition: buffer.hpp:26
Not a JSON value.
json & operator=(Bool b)
Sets type to boolean and assigns value.
Definition: json.hpp:98
T number_value() const
Returns number and string values as the passed integer type.
Definition: json.hpp:55
std::string to_string(std::wstring_view const &in)
Converts from std::wstring into std::string in system encoding.