JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
jsoncxx.h
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2// Project : VST SDK
3// Flags : clang-format SMTGSequencer
4//
5// Category :
6// Filename : public.sdk/source/vst/moduleinfo/jsoncxx.h
7// Created by : Steinberg, 12/2021
8// Description :
9//
10//-----------------------------------------------------------------------------
11// LICENSE
12// (c) 2023, Steinberg Media Technologies GmbH, All Rights Reserved
13//-----------------------------------------------------------------------------
14// Redistribution and use in source and binary forms, with or without modification,
15// are permitted provided that the following conditions are met:
16//
17// * Redistributions of source code must retain the above copyright notice,
18// this list of conditions and the following disclaimer.
19// * Redistributions in binary form must reproduce the above copyright notice,
20// this list of conditions and the following disclaimer in the documentation
21// and/or other materials provided with the distribution.
22// * Neither the name of the Steinberg Media Technologies nor the names of its
23// contributors may be used to endorse or promote products derived from this
24// software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
34// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35// OF THE POSSIBILITY OF SUCH DAMAGE.
36//-----------------------------------------------------------------------------
37
38#pragma once
39
40#include "json.h"
41#include <cassert>
42#include <cstdlib>
43#include <optional>
44#include <string>
45#include <string_view>
46#include <variant>
47
48#if defined(_MSC_VER) || __has_include(<charconv>)
49#include <charconv>
50#define SMTG_HAS_CHARCONV
51#endif
52
53//------------------------------------------------------------------------
54namespace JSON {
55namespace Detail {
56
57//------------------------------------------------------------------------
58template <typename JsonT>
59struct Base
60{
61 explicit Base (JsonT* o) : object_ (o) {}
62 explicit Base (const Base& o) : object_ (o.object_) {}
63
64 Base& operator= (const Base& o) = default;
65
66 operator JsonT* () const { return object_; }
67 JsonT* jsonValue () const { return object_; }
68
69protected:
70 Base () : object_ (nullptr) {}
71
72 JsonT* object_;
73};
74
75//------------------------------------------------------------------------
76template <typename JsonElement>
78{
79 explicit Iterator (JsonElement el) : el (el) {}
80
81 bool operator== (const Iterator& other) const { return other.el == el; }
82 bool operator!= (const Iterator& other) const { return other.el != el; }
83
84 const JsonElement& operator* () const { return el; }
85 const JsonElement& operator-> () const { return el; }
86
87 Iterator& operator++ ()
88 {
89 if (el)
90 el = el.next ();
91 return *this;
92 }
93
94 Iterator operator++ (int)
95 {
96 auto it = Iterator (el);
97 operator++ ();
98 return it;
99 }
100
101private:
102 JsonElement el;
103};
104
105//------------------------------------------------------------------------
106} // Detail
107
108struct Object;
109struct Array;
110struct String;
111struct Number;
112struct Boolean;
113
114//------------------------------------------------------------------------
115enum class Type
116{
117 Object,
118 Array,
119 String,
120 Number,
121 True,
122 False,
123 Null,
124};
125
126//------------------------------------------------------------------------
128{
129 size_t offset;
130 size_t line;
131 size_t row;
132};
133
134//------------------------------------------------------------------------
135struct Value : Detail::Base<json_value_s>
136{
137 using Detail::Base<json_value_s>::Base;
139
140 std::optional<Object> asObject () const;
141 std::optional<Array> asArray () const;
142 std::optional<String> asString () const;
143 std::optional<Number> asNumber () const;
144 std::optional<Boolean> asBoolean () const;
145 std::optional<std::nullptr_t> asNull () const;
146
147 VariantT asVariant () const;
148 Type type () const;
149
150 SourceLocation getSourceLocation () const;
151};
152
153//------------------------------------------------------------------------
155{
156 Boolean (size_t type) : value (type == json_type_true) {}
157
158 operator bool () const { return value; }
159
160private:
161 bool value;
162};
163
164//------------------------------------------------------------------------
165struct String : Detail::Base<json_string_s>
166{
167 using Detail::Base<json_string_s>::Base;
168
169 std::string_view text () const { return {jsonValue ()->string, jsonValue ()->string_size}; }
170
171 SourceLocation getSourceLocation () const;
172};
173
174//------------------------------------------------------------------------
175struct Number : Detail::Base<json_number_s>
176{
177 using Detail::Base<json_number_s>::Base;
178
179 std::string_view text () const { return {jsonValue ()->number, jsonValue ()->number_size}; }
180
181 std::optional<int64_t> getInteger () const;
182 std::optional<double> getDouble () const;
183};
184
185//------------------------------------------------------------------------
186struct ObjectElement : Detail::Base<json_object_element_s>
187{
189
190 String name () const { return String (jsonValue ()->name); }
191 Value value () const { return Value (jsonValue ()->value); }
192
193 ObjectElement next () const { return ObjectElement (jsonValue ()->next); }
194};
195
196//------------------------------------------------------------------------
197struct Object : Detail::Base<json_object_s>
198{
199 using Detail::Base<json_object_s>::Base;
201
202 size_t size () const { return jsonValue ()->length; }
203
204 Iterator begin () const { return Iterator (ObjectElement (jsonValue ()->start)); }
205 Iterator end () const { return Iterator (ObjectElement (nullptr)); }
206};
207
208//------------------------------------------------------------------------
209struct ArrayElement : Detail::Base<json_array_element_s>
210{
212
213 Value value () const { return Value (jsonValue ()->value); }
214
215 ArrayElement next () const { return ArrayElement (jsonValue ()->next); }
216};
217
218//------------------------------------------------------------------------
219struct Array : Detail::Base<json_array_s>
220{
221 using Detail::Base<json_array_s>::Base;
223
224 size_t size () const { return jsonValue ()->length; }
225
226 Iterator begin () const { return Iterator (ArrayElement (jsonValue ()->start)); }
227 Iterator end () const { return Iterator (ArrayElement (nullptr)); }
228};
229
230//------------------------------------------------------------------------
232{
234 {
235 auto allocate = [] (void*, size_t allocSize) { return std::malloc (allocSize); };
236 json_parse_result_s parse_result {};
237 auto value = json_parse_ex (data.data (), data.size (),
238 json_parse_flags_allow_json5 |
239 json_parse_flags_allow_location_information,
240 allocate, nullptr, &parse_result);
241 if (value)
242 return Document (value);
243 return parse_result;
244 }
245 ~Document () noexcept
246 {
247 if (object_)
248 std::free (object_);
249 }
250
251 Document (Document&& doc) noexcept { *this = std::move (doc); }
252 Document& operator= (Document&& doc) noexcept
253 {
254 std::swap (object_, doc.object_);
255 return *this;
256 }
257
258private:
259 using Value::Value;
260};
261
262//------------------------------------------------------------------------
263inline std::optional<Object> Value::asObject () const
264{
265 if (type () != Type::Object)
266 return {};
267 return Object (json_value_as_object (jsonValue ()));
268}
269
270//------------------------------------------------------------------------
271inline std::optional<Array> Value::asArray () const
272{
273 if (type () != Type::Array)
274 return {};
275 return Array (json_value_as_array (jsonValue ()));
276}
277
278//------------------------------------------------------------------------
279inline std::optional<String> Value::asString () const
280{
281 if (type () != Type::String)
282 return {};
283 return String (json_value_as_string (jsonValue ()));
284}
285
286//------------------------------------------------------------------------
287inline std::optional<Number> Value::asNumber () const
288{
289 if (type () != Type::Number)
290 return {};
291 return Number (json_value_as_number (jsonValue ()));
292}
293
294//------------------------------------------------------------------------
295inline std::optional<Boolean> Value::asBoolean () const
296{
297 if (type () == Type::True || type () == Type::False)
298 return Boolean (jsonValue ()->type);
299 return {};
300}
301
302//------------------------------------------------------------------------
303inline std::optional<std::nullptr_t> Value::asNull () const
304{
305 if (type () != Type::Null)
306 return {};
307 return nullptr;
308}
309
310//------------------------------------------------------------------------
311inline Type Value::type () const
312{
313 switch (jsonValue ()->type)
314 {
315 case json_type_string: return Type::String;
316 case json_type_number: return Type::Number;
317 case json_type_object: return Type::Object;
318 case json_type_array: return Type::Array;
319 case json_type_true: return Type::True;
320 case json_type_false: return Type::False;
321 case json_type_null: return Type::Null;
322 }
323 assert (false);
324 return Type::Null;
325}
326
327//------------------------------------------------------------------------
328inline Value::VariantT Value::asVariant () const
329{
330 switch (type ())
331 {
332 case Type::String: return *asString ();
333 case Type::Number: return *asNumber ();
334 case Type::Object: return *asObject ();
335 case Type::Array: return *asArray ();
336 case Type::True: return *asBoolean ();
337 case Type::False: return *asBoolean ();
338 case Type::Null: return *asNull ();
339 }
340 assert (false);
341 return nullptr;
342}
343
344//------------------------------------------------------------------------
345inline SourceLocation Value::getSourceLocation () const
346{
347 auto exValue = reinterpret_cast<json_value_ex_s*> (jsonValue ());
348 return {exValue->offset, exValue->line_no, exValue->row_no};
349}
350
351//------------------------------------------------------------------------
352inline SourceLocation String::getSourceLocation () const
353{
354 auto exValue = reinterpret_cast<json_string_ex_s*> (jsonValue ());
355 return {exValue->offset, exValue->line_no, exValue->row_no};
356}
357
358//------------------------------------------------------------------------
359inline std::optional<int64_t> Number::getInteger () const
360{
361#if defined(SMTG_HAS_CHARCONV)
362 int64_t result {0};
363 auto res = std::from_chars (jsonValue ()->number,
364 jsonValue ()->number + jsonValue ()->number_size, result);
365 if (res.ec == std::errc ())
366 return result;
367 return {};
368#else
369 int64_t result {0};
370 std::string str (jsonValue ()->number, jsonValue ()->number + jsonValue ()->number_size);
371 if (std::sscanf (str.data (), "%lld", &result) != 1)
372 return {};
373 return result;
374#endif
375}
376
377//------------------------------------------------------------------------
378inline std::optional<double> Number::getDouble () const
379{
380#if 1 // clang still has no floting point from_chars version
381 size_t ctrl {0};
382 auto result = std::stod (std::string (jsonValue ()->number, jsonValue ()->number_size), &ctrl);
383 if (ctrl > 0)
384 return result;
385#else
386 double result {0.};
387 auto res = std::from_chars (jsonValue ()->number,
388 jsonValue ()->number + jsonValue ()->number_size, result);
389 if (res.ec == std::errc ())
390 return result;
391#endif
392 return {};
393}
394
395//------------------------------------------------------------------------
396inline std::string_view errorToString (json_parse_error_e error)
397{
398 switch (error)
399 {
400 case json_parse_error_e::json_parse_error_none: return {};
401 case json_parse_error_e::json_parse_error_expected_comma_or_closing_bracket:
402 return "json_parse_error_expected_comma_or_closing_bracket";
403 case json_parse_error_e::json_parse_error_expected_colon:
404 return "json_parse_error_expected_colon";
405 case json_parse_error_e::json_parse_error_expected_opening_quote:
406 return "json_parse_error_expected_opening_quote";
407 case json_parse_error_e::json_parse_error_invalid_string_escape_sequence:
408 return "json_parse_error_invalid_string_escape_sequence";
409 case json_parse_error_e::json_parse_error_invalid_number_format:
410 return "json_parse_error_invalid_number_format";
411 case json_parse_error_e::json_parse_error_invalid_value:
412 return "json_parse_error_invalid_value";
413 case json_parse_error_e::json_parse_error_premature_end_of_buffer:
414 return "json_parse_error_premature_end_of_buffer";
415 case json_parse_error_e::json_parse_error_invalid_string:
416 return "json_parse_error_invalid_string";
417 case json_parse_error_e::json_parse_error_allocator_failed:
418 return "json_parse_error_allocator_failed";
419 case json_parse_error_e::json_parse_error_unexpected_trailing_characters:
420 return "json_parse_error_unexpected_trailing_characters";
421 case json_parse_error_e::json_parse_error_unknown: return "json_parse_error_unknown";
422 }
423 return {};
424}
425
426//------------------------------------------------------------------------
427} // JSON
assert
T free(T... args)
T from_chars(T... args)
T sscanf(T... args)
T malloc(T... args)
typedef int64_t
T stod(T... args)
T swap(T... args)