libfilezilla
Loading...
Searching...
No Matches
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 <limits.h>
10#include <map>
11#include <optional>
12#include <type_traits>
13#include <variant>
14
15namespace fz {
16
18enum class json_type {
19 none,
22 array,
23 string,
24 number,
25 boolean
26};
27
28class buffer;
29
32class FZ_PUBLIC_SYMBOL json final
33{
34public:
35 json() noexcept = default;
36 json(json const&) = default;
37 json(json &&) noexcept = default;
38
40 explicit json(json_type t);
41
42 json_type type() const {
43 return static_cast<json_type>(value_.index());
44 }
45
47 std::string string_value() const;
48
50 std::wstring wstring_value() const {
52 }
53
54
62 template<typename T, std::enable_if_t<std::is_integral_v<typename std::decay_t<T>>, int> = 0>
63 T number_value(T errorval = {}) const {
64 auto v = number_value_o<T>();
65 if (v) {
66 return *v;
67 }
68 return errorval;
69 }
70
76 template<typename T, std::enable_if_t<std::is_integral_v<typename std::decay_t<T>>, int> = 0>
77 std::optional<T> number_value_o() const {
78 bool constexpr is_signed = std::is_signed_v<typename std::decay_t<T>>;
79 if constexpr (is_signed) {
80 std::optional<int64_t> tmp = number_value_integer_s();
81 if (tmp) {
82 if (tmp >= std::numeric_limits<T>::min() && tmp <= std::numeric_limits<T>::max()) {
83 return static_cast<T>(*tmp);
84 }
85 }
86 }
87 else {
88 std::optional<uint64_t> tmp = number_value_integer_u();
89 if (tmp) {
90 if (tmp <= std::numeric_limits<T>::max()) {
91 return static_cast<T>(*tmp);
92 }
93 }
94 }
95
96 return {};
97 }
98
100 template<typename T, std::enable_if_t<std::is_floating_point_v<typename std::decay_t<T>>, int> = 0>
101 T number_value() const {
102 return static_cast<T>(number_value_double());
103 }
104
106 bool bool_value() const;
107
109 void erase(std::string const& name);
110
112 json const& operator[](std::string const& name) const;
113
120 json& operator[](std::string const& name);
121
123 json const& operator[](size_t i) const;
124
131 json& operator[](size_t i);
132
134 size_t children() const;
135
137 template<typename Bool, std::enable_if_t<std::is_same_v<bool, typename std::decay_t<Bool>>, int> = 0>
138 json& operator=(Bool b) {
139 value_ = b;
140 return *this;
141 }
142
144 template<typename T, std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<bool, typename std::decay_t<T>>, int> = 0>
145 json& operator=(T n) {
146 value_.emplace<std::size_t(json_type::number)>(fz::to_string(n));
147 return *this;
148 }
149
154 json& operator=(std::string_view const& v);
155
157 json& operator=(std::wstring_view const& v) {
158 return *this = to_utf8(v);
159 }
160
161 json& operator=(json const&);
162 json& operator=(json &&) noexcept;
163
164 explicit operator bool() const { return type() != json_type::none; }
165
166 bool has_non_null_value() const {
167 return type() != fz::json_type::none && type() != fz::json_type::null;
168 }
169
170 bool is_null() const { return type() == fz::json_type::null; }
171 bool is_object() const { return type() == fz::json_type::object; }
172 bool is_array() const { return type() == fz::json_type::array; }
173 bool is_number() const { return type() == fz::json_type::number; }
174 bool is_boolean() const { return type() == fz::json_type::boolean; }
175
181 std::string to_string(bool pretty = false, size_t depth = 0) const;
182
190 void to_string(std::string & ret, bool pretty = false, size_t depth = 0) const;
191
196 static json parse(std::string_view const& v, size_t max_depth = 20);
197 static json parse(fz::buffer const& b, size_t max_depth = 20);
198
199 void clear();
200
201private:
202 void to_string_impl(std::string & ret, bool pretty = false, size_t depth = 0) const;
203
204 std::optional<int64_t> number_value_integer_s() const;
205 std::optional<uint64_t> number_value_integer_u() const;
206 double number_value_double() const;
207
208 bool FZ_PRIVATE_SYMBOL check_type(json_type t);
209 void FZ_PRIVATE_SYMBOL set_type(json_type t);
210
211 static json FZ_PRIVATE_SYMBOL parse(char const*& p, char const* end, size_t max_depth);
212
213 typedef std::variant<
214 std::monostate, // json_type::none
215 std::nullptr_t, // json_type::null
216 std::map<std::string, json, std::less<>>, // json_type::object
217 std::vector<json>, // json_type::array
218 std::string, // json_type::string,
219 std::string, // json_type::number,
220 bool // json_type::boolean
221 > value_type;
222 value_type value_;
223};
224
225template <bool isconst>
226struct json_array_iterator final {
227 using json_ref_t = std::conditional_t<isconst, json const&, json &>;
228
229 struct sentinel final {};
230
231 json_array_iterator(json_ref_t j)
232 // 0 if it's an array, -1 otherwise
233 : idx_((j.type() == json_type::array)-1)
234 , json_(j)
235 {}
236
237 json_array_iterator & operator++()
238 {
239 ++idx_;
240
241 return *this;
242 }
243
244 json_ref_t operator*() const
245 {
246 return json_[idx_];
247 }
248
249 bool operator!=(json_array_iterator::sentinel const&) const
250 {
251 return idx_ < json_.children();
252 }
253
254private:
255 std::size_t idx_;
256 json_ref_t json_;
257};
258
259inline json_array_iterator<false> begin(json &j) { return {j}; }
260inline json_array_iterator<false>::sentinel end(json &) { return {}; }
261
262inline json_array_iterator<true> begin(json const& j) { return {j}; }
263inline json_array_iterator<true>::sentinel end(json const&) { return {}; }
264
265}
266
267#endif
The buffer class is a simple buffer where data can be appended at the end and consumed at the front....
Definition buffer.hpp:27
json parser/builder
Definition json.hpp:33
static json parse(std::string_view const &v, size_t max_depth=20)
Parses JSON structure from input.
json & operator=(T n)
Sets type to number and assigns value.
Definition json.hpp:145
json & operator=(std::string_view const &v)
Sets type to string and assigns value.
std::string to_string(bool pretty=false, size_t depth=0) const
Serializes JSON structure.
json & operator[](size_t i)
Returns reference to the child value with the given index.
std::string string_value() const
Returns string, number and boolean values as string.
json const & operator[](std::string const &name) const
If object, get the value with the given name. Returns none if not object or name doesn't exist.
json & operator=(std::wstring_view const &v)
Sets type to string and assigns value.
Definition json.hpp:157
void erase(std::string const &name)
If object value, deletes child value with given name.
json & operator=(Bool b)
Sets type to boolean and assigns value.
Definition json.hpp:138
size_t children() const
For arrays and objects, returns the number of elements.
T number_value(T errorval={}) const
Returns number and string values as the passed integer type.
Definition json.hpp:63
std::optional< T > number_value_o() const
Returns values as passed integer type if it can be converted, nullopt otherwise.
Definition json.hpp:77
void to_string(std::string &ret, bool pretty=false, size_t depth=0) const
Serializes JSON structure.
json & operator[](std::string const &name)
Returns reference to the child value with the given name.
T number_value() const
Returns number and string values as the passed floating point type.
Definition json.hpp:101
std::wstring wstring_value() const
Returns string, number and boolean values as wstring.
Definition json.hpp:50
json(json_type t)
Explicitly creates a value of a specific type, mainly needed for null objects.
bool bool_value() const
Returns boolean and string values as bool.
json const & operator[](size_t i) const
If array, get the value with the given index. Returns none if not array or index doesn't exist.
type
Definition logger.hpp:16
The namespace used by libfilezilla.
Definition apply.hpp:17
std::wstring to_wstring_from_utf8(std::string_view const &in)
Converts from std::string in UTF-8 into std::wstring.
std::string to_utf8(std::string_view const &in)
Converts from std::string in native encoding into std::string in UTF-8.
std::string to_string(std::wstring_view const &in)
Converts from std::wstring into std::string in system encoding.
json_type
Types of JSON values.
Definition json.hpp:18
@ null
Not a JSON value.
Definition json.hpp:20
@ object
The explicit null value.
Definition json.hpp:21
String types and assorted functions.
Definition json.hpp:229
Definition json.hpp:226