OpenVPN 3 Core Library
Loading...
Searching...
No Matches
jsonhelper.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#pragma once
13
14#include <string>
15#include <cstring>
16#include <cstdint>
17#include <utility>
18
27
28#ifndef HAVE_JSON
29#error no JSON library available
30#endif
31
32namespace openvpn::json {
33
35
36/* Workaround warnings in gcc 13+, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109642
37 * Could use [[gnu::no_dangling]] in gcc 14+ but that would then cause warnings in older
38 * compilers...
39 */
40#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 13
41#define DISABLE_DANGLING_WARNINGS() \
42 _Pragma("GCC diagnostic push") \
43 _Pragma("GCC diagnostic ignored \"-Wdangling-reference\"")
44
45#define REENABLE_DANGLING_WARNINGS() \
46 _Pragma("GCC diagnostic pop")
47#else
48#define DISABLE_DANGLING_WARNINGS()
49#define REENABLE_DANGLING_WARNINGS()
50#endif
51
52
53template <typename TITLE>
54inline Json::Value parse(const std::string &str, const TITLE &title)
55{
56#ifdef OPENVPN_JSON
57 return Json::Value::parse(str, StringTempl::to_string(title));
58#else
59 Json::CharReaderBuilder builder;
60 builder["collectComments"] = false;
61 Json::Value root;
62 std::string errors;
63 std::istringstream instr(str);
64
65 if (!Json::parseFromStream(builder, instr, &root, &errors))
66 throw json_parse(StringTempl::to_string(title) + " : " + errors);
67 return root;
68#endif
69}
70
71inline Json::Value parse(const std::string &str)
72{
73 return parse(str, "json");
74}
75
76inline Json::Value parse_from_file(const std::string &fn)
77{
78 return parse(read_text_utf8(fn), fn);
79}
80
81template <typename BUFFER, typename TITLE>
82inline Json::Value parse_from_buffer(const BUFFER &buf, const TITLE &title)
83{
84#ifdef OPENVPN_JSON
85 return Json::Value::parse(buf, StringTempl::to_string(title));
86#else
87 Json::CharReaderBuilder builder;
88 builder["collectComments"] = false;
89 Json::Value root;
90 std::string errors;
91
92 std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
93 if (!reader->parse(reinterpret_cast<const char *>(buf.c_data()), reinterpret_cast<const char *>(buf.c_data()) + buf.size(), &root, &errors))
94 throw json_parse(StringTempl::to_string(title) + " : " + errors);
95 return root;
96#endif
97}
98
99#ifdef OPENVPN_JSON_INTERNAL
101template <typename NAME, typename TITLE>
102inline const Json::Value &cast(const Json::ValueType target_type,
103 const Json::Value &value,
104 const NAME &name,
105 const bool optional,
106 const TITLE &title)
107{
108 if (value.isNull())
109 {
110 if (optional)
111 return value;
112 throw json_parse(Json::Value::type_string(target_type) + " cast " + fmt_name(name, title) + " is null");
113 }
114 if (!value.isConvertibleTo(target_type))
115 throw json_parse(Json::Value::type_string(target_type) + " cast " + fmt_name(name, title) + " is of incorrect type (" + value.type_string() + ')');
116 return value;
117}
119
120template <typename NAME>
121inline const Json::Value &cast(const Json::ValueType target_type,
122 const Json::Value &value,
123 const NAME &name,
124 const bool optional)
125{
126 return cast(target_type, value, name, optional, nullptr);
127}
128
129template <typename NAME, typename TITLE>
130inline Json::Value cast(const Json::ValueType target_type,
131 Json::Value &&value,
132 const NAME &name,
133 const bool optional,
134 const TITLE &title)
135{
136 Json::Value ret = std::move(value);
137 cast(target_type, ret, name, optional, title);
138 return ret;
139}
140
141template <typename NAME>
142inline Json::Value cast(const Json::ValueType target_type,
143 Json::Value &&value,
144 const NAME &name,
145 const bool optional)
146{
147 return cast(target_type, std::move(value), name, optional, nullptr);
148}
149
150#endif
151
152template <typename T, typename NAME>
153inline void from_vector(Json::Value &root, const T &vec, const NAME &name)
154{
155 Json::Value array(Json::arrayValue);
156 for (auto &e : vec)
157 array.append(e.to_json());
158 if (array.size())
159 root[name] = std::move(array);
160}
161
162template <typename TITLE>
163inline void assert_dict(const Json::Value &obj, const TITLE &title)
164{
165 if (!obj.isObject())
166 throw json_parse(fmt_name_cast(title) + " is not a JSON dictionary");
167}
168
169template <typename TITLE>
170inline bool is_dict(const Json::Value &obj, const TITLE &title)
171{
172 if (obj.isNull())
173 return false;
174 assert_dict(obj, title);
175 return true;
176}
177
178template <typename NAME>
179inline bool exists(const Json::Value &root, const NAME &name)
180{
181 if (!root.isObject())
182 return false;
183 return !root[name].isNull();
184}
185
186template <typename NAME>
187inline bool string_exists(const Json::Value &root, const NAME &name)
188{
189 if (!root.isObject())
190 return false;
191 return root[name].isString();
192}
193
194template <typename T, typename NAME, typename TITLE>
195inline void to_vector(const Json::Value &root, T &vec, const NAME &name, const TITLE &title)
196{
197 const Json::Value &array = root[name];
198 if (array.isNull())
199 return;
200 if (!array.isArray())
201 throw json_parse("array " + fmt_name(name, title) + " is of incorrect type");
202 for (unsigned int i = 0; i < array.size(); ++i)
203 {
204 vec.emplace_back();
205 vec.back().from_json(array[i], fmt_name(name, title));
206 }
207}
208
209template <typename NAME, typename TITLE>
210inline std::string get_string(const Json::Value &root,
211 const NAME &name,
212 const TITLE &title)
213{
214 const Json::Value &value = root[name];
215 if (value.isNull())
216 throw json_parse("string " + fmt_name(name, title) + " is missing");
217 if (!value.isString())
218 throw json_parse("string " + fmt_name(name, title) + " is of incorrect type");
219 return value.asString();
220}
221
222template <typename NAME>
223inline std::string get_string(const Json::Value &root, const NAME &name)
224{
225 return get_string(root, name, nullptr);
226}
227
228#ifdef OPENVPN_JSON_INTERNAL
229template <typename NAME, typename TITLE>
230inline const std::string &get_string_ref(const Json::Value &root,
231 const NAME &name,
232 const TITLE &title)
233{
234 const Json::Value &value = root[name];
235 if (value.isNull())
236 throw json_parse("string " + fmt_name(name, title) + " is missing");
237 if (!value.isString())
238 throw json_parse("string " + fmt_name(name, title) + " is of incorrect type");
239 return value.asStringRef();
240}
241
242template <typename NAME>
243inline const std::string &get_string_ref(const Json::Value &root, const NAME &name)
244{
245 return get_string_ref(root, name, nullptr);
246}
247
248// for safety, define an rvalue ref overload that falls back to get_string()
249template <typename NAME, typename TITLE>
250inline std::string get_string_ref(Json::Value &&root,
251 const NAME &name,
252 const TITLE &title)
253{
254 return get_string(root, name, title);
255}
256
257template <typename NAME, typename TITLE>
258inline const std::string *get_string_ptr(const Json::Value &root,
259 const NAME &name,
260 const TITLE &title)
261{
262 const Json::Value &value = root[name];
263 if (value.isNull())
264 return nullptr;
265 if (!value.isString())
266 throw json_parse("string " + fmt_name(name, title) + " is of incorrect type");
267 return value.asStringPtr();
268}
269
270template <typename NAME>
271inline const std::string *get_string_ptr(const Json::Value &root, const NAME &name)
272{
273 return get_string_ptr(root, name, nullptr);
274}
275#endif
276
277template <typename NAME, typename TITLE>
278inline std::string get_string_optional(const Json::Value &root,
279 const NAME &name,
280 const std::string &default_value,
281 const TITLE &title)
282{
283 const Json::Value &value = root[name];
284 if (value.isNull())
285 return default_value;
286 if (!value.isString())
287 throw json_parse("string " + fmt_name(name, title) + " is of incorrect type");
288 return value.asString();
289}
290
291template <typename NAME>
292inline std::string get_string_optional(const Json::Value &root,
293 const NAME &name,
294 const std::string &default_value)
295{
296 return get_string_optional(root, name, default_value, nullptr);
297}
298
299template <typename TITLE>
300inline std::string get_string_from_array(const Json::Value &root,
301 const Json::ArrayIndex index,
302 const TITLE &title)
303{
304 const Json::Value &value = root[index];
305 if (value.isNull())
306 throw json_parse("string " + fmt_name(index, title) + " is missing");
307 if (!value.isString())
308 throw json_parse("string " + fmt_name(index, title) + " is of incorrect type");
309 return value.asString();
310}
311
312inline std::string get_string_from_array(const Json::Value &root,
313 const Json::ArrayIndex index)
314{
315 return get_string_from_array(root, index, nullptr);
316}
317
318template <typename NAME, typename TITLE>
319inline int get_int(const Json::Value &root,
320 const NAME &name,
321 const TITLE &title)
322{
323 const Json::Value &value = root[name];
324 if (value.isNull())
325 throw json_parse("int " + fmt_name(name, title) + " is missing");
326 if (!value.isInt())
327 throw json_parse("int " + fmt_name(name, title) + " is of incorrect type");
328 return value.asInt();
329}
330
331template <typename NAME>
332inline int get_int(const Json::Value &root, const NAME &name)
333{
334 return get_int(root, name, nullptr);
335}
336
337template <typename NAME, typename TITLE>
338inline int get_int_optional(const Json::Value &root,
339 const NAME &name,
340 const int default_value,
341 const TITLE &title)
342{
343 const Json::Value &value = root[name];
344 if (value.isNull())
345 return default_value;
346 if (!value.isInt())
347 throw json_parse("int " + fmt_name(name, title) + " is of incorrect type");
348 return value.asInt();
349}
350
351template <typename NAME>
352inline int get_int_optional(const Json::Value &root,
353 const NAME &name,
354 const int default_value)
355{
356 return get_int_optional(root, name, default_value, nullptr);
357}
358
359template <typename NAME, typename TITLE>
360inline unsigned int get_uint(const Json::Value &root,
361 const NAME &name,
362 const TITLE &title)
363{
364 const Json::Value &value = root[name];
365 if (value.isNull())
366 throw json_parse("uint " + fmt_name(name, title) + " is missing");
367 if (!value.isUInt())
368 throw json_parse("uint " + fmt_name(name, title) + " is of incorrect type");
369 return value.asUInt();
370}
371
372template <typename NAME>
373inline unsigned int get_uint(const Json::Value &root, const NAME &name)
374{
375 return get_uint(root, name, nullptr);
376}
377
378template <typename NAME, typename TITLE>
379inline unsigned int get_uint_optional(const Json::Value &root,
380 const NAME &name,
381 const unsigned int default_value,
382 const TITLE &title)
383{
384 const Json::Value &value = root[name];
385 if (value.isNull())
386 return default_value;
387 if (!value.isUInt())
388 throw json_parse("uint " + fmt_name(name, title) + " is of incorrect type");
389 return value.asUInt();
390}
391
392template <typename NAME>
393inline unsigned int get_uint_optional(const Json::Value &root,
394 const NAME &name,
395 const unsigned int default_value)
396{
397 return get_uint_optional(root, name, default_value, nullptr);
398}
399
400template <typename NAME, typename TITLE>
401inline unsigned int get_uint_via_string(const Json::Value &root,
402 const NAME &name,
403 const TITLE &title)
404{
405 const Json::Value &value = root[name];
406 if (value.isNull())
407 throw json_parse("uint-via-string " + fmt_name(name, title) + " is missing");
408 if (!value.isString())
409 throw json_parse("uint-via-string " + fmt_name(name, title) + " is of incorrect type");
410
411 unsigned int ret;
412 if (!parse_number(value.asString(), ret))
413 throw json_parse("uint-via-string " + fmt_name(name, title) + " failed to parse");
414 return ret;
415}
416
417template <typename NAME>
418inline unsigned int get_uint_via_string(const Json::Value &root,
419 const NAME &name)
420{
421 return get_uint_via_string(root, name, nullptr);
422}
423
424template <typename NAME, typename TITLE>
425inline unsigned int get_uint_optional_via_string(const Json::Value &root,
426 const NAME &name,
427 const unsigned int default_value,
428 const TITLE &title)
429{
430 const Json::Value &value = root[name];
431 if (value.isNull())
432 return default_value;
433 if (!value.isString())
434 throw json_parse("uint-via-string " + fmt_name(name, title) + " is of incorrect type");
435
436 unsigned int ret;
437 if (!parse_number(value.asString(), ret))
438 throw json_parse("uint-via-string " + fmt_name(name, title) + " failed to parse");
439 return ret;
440}
441
442template <typename NAME>
443inline unsigned int get_uint_optional_via_string(const Json::Value &root,
444 const NAME &name,
445 const unsigned int default_value)
446{
447 return get_uint_optional_via_string(root, name, default_value, nullptr);
448}
449
450template <typename NAME, typename TITLE>
451inline std::uint64_t get_uint64(const Json::Value &root,
452 const NAME &name,
453 const TITLE &title)
454{
455 const Json::Value &value = root[name];
456 if (value.isNull())
457 throw json_parse("uint64 " + fmt_name(name, title) + " is missing");
458 if (!value.isUInt64())
459 throw json_parse("uint64 " + fmt_name(name, title) + " is of incorrect type");
460 return value.asUInt64();
461}
462
463template <typename NAME>
464inline std::uint64_t get_uint64(const Json::Value &root, const NAME &name)
465{
466 return get_uint64(root, name, nullptr);
467}
468
469template <typename NAME, typename TITLE>
470inline std::uint64_t get_uint64_optional(const Json::Value &root,
471 const NAME &name,
472 const std::uint64_t default_value,
473 const TITLE &title)
474{
475 const Json::Value &value = root[name];
476 if (value.isNull())
477 return default_value;
478 if (!value.isUInt64())
479 throw json_parse("uint64 " + fmt_name(name, title) + " is of incorrect type");
480 return value.asUInt64();
481}
482
483template <typename NAME, typename TITLE>
484inline std::int64_t get_int64_optional(const Json::Value &root,
485 const NAME &name,
486 const std::uint64_t default_value,
487 const TITLE &title)
488{
489 const Json::Value &value = root[name];
490 if (value.isNull())
491 return default_value;
492 if (!value.isInt64())
493 throw json_parse("int64 " + fmt_name(name, title) + " is of incorrect type");
494 return value.asInt64();
495}
496
497template <typename NAME>
498inline std::uint64_t get_uint64_optional(const Json::Value &root,
499 const NAME &name,
500 const std::uint64_t default_value)
501{
502 return get_uint64_optional(root, name, default_value, nullptr);
503}
504
505/*
506 * The get_integer_optional function are used to select the right
507 * method based on the default_value parameter
508 */
509
510template <typename NAME, typename TITLE>
511std::uint64_t get_integer_optional(const Json::Value &root,
512 const NAME &name,
513 const std::uint64_t default_value,
514 const TITLE &title)
515{
516 return get_uint64_optional(root, name, default_value, title);
517}
518
519template <typename NAME, typename TITLE>
520std::int64_t get_integer_optional(const Json::Value &root,
521 const NAME &name,
522 const std::int64_t default_value,
523 const TITLE &title)
524{
525 return get_int64_optional(root, name, default_value, title);
526}
527
528template <typename NAME, typename TITLE>
529inline unsigned int get_integer_optional(const Json::Value &root,
530 const NAME &name,
531 const unsigned int default_value,
532 const TITLE &title)
533{
534 return get_uint_optional(root, name, default_value, title);
535}
536
537template <typename NAME, typename TITLE>
538inline int get_integer_optional(const Json::Value &root,
539 const NAME &name,
540 const int default_value,
541 const TITLE &title)
542{
543 return get_int_optional(root, name, default_value, title);
544}
545
546template <typename NAME, typename TITLE>
547inline std::uint64_t get_uint64_via_string(const Json::Value &root,
548 const NAME &name,
549 const TITLE &title)
550{
551 const Json::Value &value = root[name];
552 if (value.isNull())
553 throw json_parse("uint64-via-string " + fmt_name(name, title) + " is missing");
554 if (!value.isString())
555 throw json_parse("uint64-via-string " + fmt_name(name, title) + " is of incorrect type");
556
557 std::uint64_t ret;
558 if (!parse_number(value.asString(), ret))
559 throw json_parse("uint64-via-string " + fmt_name(name, title) + " failed to parse");
560 return ret;
561}
562
563template <typename NAME>
564inline std::uint64_t get_uint64_via_string(const Json::Value &root,
565 const NAME &name)
566{
567 return get_uint64_via_string(root, name, nullptr);
568}
569
570template <typename NAME, typename TITLE>
571inline std::uint64_t get_uint64_optional_via_string(const Json::Value &root,
572 const NAME &name,
573 const std::uint64_t default_value,
574 const TITLE &title)
575{
576 const Json::Value &value = root[name];
577 if (value.isNull())
578 return default_value;
579 if (!value.isString())
580 throw json_parse("uint64-via-string " + fmt_name(name, title) + " is of incorrect type");
581
582 std::uint64_t ret;
583 if (!parse_number(value.asString(), ret))
584 throw json_parse("uint64-via-string " + fmt_name(name, title) + " failed to parse");
585 return ret;
586}
587
588template <typename NAME>
589inline std::uint64_t get_uint64_optional_via_string(const Json::Value &root,
590 const NAME &name,
591 const std::uint64_t default_value)
592{
593 return get_uint64_optional_via_string(root, name, default_value, nullptr);
594}
595template <typename NAME, typename TITLE>
596inline bool get_bool(const Json::Value &root,
597 const NAME &name,
598 const TITLE &title)
599{
600 const Json::Value &value = root[name];
601 if (value.isNull())
602 throw json_parse("bool " + fmt_name(name, title) + " is missing");
603 if (!value.isBool())
604 throw json_parse("bool " + fmt_name(name, title) + " is of incorrect type");
605 return value.asBool();
606}
607
608template <typename NAME>
609inline bool get_bool(const Json::Value &root, const NAME &name)
610{
611 return get_bool(root, name, nullptr);
612}
613
614template <typename NAME>
615inline bool get_bool_optional(const Json::Value &root,
616 const NAME &name,
617 const bool default_value = false)
618{
619 const Json::Value &jv = root[name];
620 if (jv.isConvertibleTo(Json::booleanValue))
621 return jv.asBool();
622 else
623 return default_value;
624}
625
626template <typename NAME>
627inline int get_bool_tristate(const Json::Value &root,
628 const NAME &name)
629{
630 const Json::Value &jv = root[name];
631 if (jv.isConvertibleTo(Json::booleanValue))
632 return jv.asBool() ? 1 : 0;
633 else
634 return -1;
635}
636
638template <typename NAME, typename TITLE>
639inline const Json::Value &get_dict(const Json::Value &root,
640 const NAME &name,
641 const bool optional,
642 const TITLE &title)
643{
644 const Json::Value &value = root[name];
645 if (value.isNull())
646 {
647 if (optional)
648 return value;
649 throw json_parse("dictionary " + fmt_name(name, title) + " is missing");
650 }
651 if (!value.isObject())
652 throw json_parse("dictionary " + fmt_name(name, title) + " is of incorrect type");
653 return value;
654}
656
657template <typename NAME>
658inline const Json::Value &get_dict(const Json::Value &root,
659 const NAME &name,
660 const bool optional)
661{
662 return get_dict(root, name, optional, nullptr);
663}
664
665template <typename NAME, typename TITLE>
666inline Json::Value get_dict(Json::Value &&root,
667 const NAME &name,
668 const bool optional,
669 const TITLE &title)
670{
671 Json::Value r = std::move(root);
672 return get_dict(r, name, optional, title);
673}
674
675template <typename NAME>
676inline Json::Value get_dict(Json::Value &&root,
677 const NAME &name,
678 const bool optional)
679{
680 return get_dict(std::move(root), name, optional, nullptr);
681}
682
684template <typename TITLE>
685inline const Json::Value &cast_dict(const Json::Value &value,
686 const bool optional,
687 const TITLE &title)
688{
689 if (value.isNull())
690 {
691 if (optional)
692 return value;
693 throw json_parse("dictionary cast " + fmt_name_cast(title) + " is null");
694 }
695 if (!value.isObject())
696 throw json_parse("dictionary cast " + fmt_name_cast(title) + " is of incorrect type");
697 return value;
698}
700
701inline const Json::Value &cast_dict(const Json::Value &value,
702 const bool optional)
703{
704 return cast_dict(value, optional, nullptr);
705}
706
707template <typename TITLE>
708inline Json::Value cast_dict(Json::Value &&value,
709 const bool optional,
710 const TITLE &title)
711{
712 Json::Value ret = std::move(value);
713 cast_dict(ret, optional, title);
714 return ret;
715}
716
717inline Json::Value cast_dict(Json::Value &&value,
718 const bool optional)
719{
720 return cast_dict(std::move(value), optional, nullptr);
721}
722
724template <typename NAME, typename TITLE>
725inline const Json::Value &get_array(const Json::Value &root,
726 const NAME &name,
727 const bool optional,
728 const TITLE &title)
729{
730 const Json::Value &value = root[name];
731 if (value.isNull())
732 {
733 if (optional)
734 return value;
735 throw json_parse("array " + fmt_name(name, title) + " is missing");
736 }
737 if (!value.isArray())
738 throw json_parse("array " + fmt_name(name, title) + " is of incorrect type");
739 return value;
740}
742
743template <typename NAME>
744inline const Json::Value &get_array(const Json::Value &root,
745 const NAME &name,
746 const bool optional)
747{
748 return get_array(root, name, optional, nullptr);
749}
750
751template <typename NAME, typename TITLE>
752inline Json::Value get_array(Json::Value &&root,
753 const NAME &name,
754 const bool optional,
755 const TITLE &title)
756{
757 Json::Value r = std::move(root);
758 return get_array(r, name, optional, title);
759}
760
761template <typename NAME>
762inline Json::Value get_array(Json::Value &&root,
763 const NAME &name,
764 const bool optional)
765{
766 return get_array(std::move(root), name, optional, nullptr);
767}
768
770template <typename TITLE>
771inline const Json::Value &cast_array(const Json::Value &value,
772 const bool optional,
773 const TITLE &title)
774{
775 if (value.isNull())
776 {
777 if (optional)
778 return value;
779 throw json_parse("array cast " + fmt_name_cast(title) + " is null");
780 }
781 if (!value.isArray())
782 throw json_parse("array cast " + fmt_name_cast(title) + " is of incorrect type");
783 return value;
784}
786
787inline const Json::Value &cast_array(const Json::Value &value,
788 const bool optional)
789{
790 return cast_array(value, optional, nullptr);
791}
792
793template <typename TITLE>
794inline Json::Value cast_array(Json::Value &&value,
795 const bool optional,
796 const TITLE &title)
797{
798 Json::Value ret = std::move(value);
799 cast_array(ret, optional, title);
800 return ret;
801}
802
803inline Json::Value cast_array(Json::Value &&value,
804 const bool optional)
805{
806 return cast_array(std::move(value), optional, nullptr);
807}
808
809template <typename NAME, typename TITLE>
810inline void to_string(const Json::Value &root,
811 std::string &dest,
812 const NAME &name,
813 const TITLE &title)
814{
815 dest = get_string(root, name, title);
816}
817
818template <typename NAME, typename TITLE>
819inline void to_string_optional(const Json::Value &root,
820 std::string &dest,
821 const NAME &name,
822 const std::string &default_value,
823 const TITLE &title)
824{
825 dest = get_string_optional(root, name, default_value, title);
826}
827
828template <typename NAME, typename TITLE>
829inline void to_int(const Json::Value &root,
830 int &dest,
831 const NAME &name,
832 const TITLE &title)
833{
834 dest = get_int(root, name, title);
835}
836
837template <typename NAME, typename TITLE>
838inline void to_uchar(const Json::Value &root,
839 unsigned char &dest,
840 const NAME &name,
841 const TITLE &title)
842{
843 auto temp = get_int(root, name, title);
844 dest = clamp_notify<unsigned char>(temp,
845 [](decltype(temp) temp) -> unsigned char
846 {
847 auto why = std::string("Conversion error [" + std::to_string(temp) + "] to unsigned char");
848 throw json_parse(std::move(why)); });
849}
850
851template <typename NAME, typename TITLE>
852inline void to_uint(const Json::Value &root,
853 unsigned int &dest,
854 const NAME &name,
855 const TITLE &title)
856{
857 dest = get_uint(root, name, title);
858}
859
860template <typename NAME, typename TITLE>
861inline void to_uint_optional(const Json::Value &root,
862 unsigned int &dest,
863 const NAME &name,
864 const unsigned int default_value,
865 const TITLE &title)
866{
867 dest = get_uint_optional(root, name, default_value, title);
868}
869
870template <typename NAME, typename TITLE>
871inline void to_uint64(const Json::Value &root,
872 std::uint64_t &dest,
873 const NAME &name,
874 const TITLE &title)
875{
876 dest = get_uint64(root, name, title);
877}
878
879template <typename NAME, typename TITLE>
880inline void to_bool(const Json::Value &root,
881 bool &dest,
882 const NAME &name,
883 const TITLE &title)
884{
885 dest = get_bool(root, name, title);
886}
887
888inline void format_compact(const Json::Value &root, Buffer &buf)
889{
890#ifdef OPENVPN_JSON
891 root.toCompactString(buf);
892#else
893 Json::StreamWriterBuilder json_builder;
894 json_builder.settings_["indentation"] = "";
895 BufferStreamOut os(buf);
896 std::unique_ptr<Json::StreamWriter> sw(json_builder.newStreamWriter());
897 sw->write(root, &os);
898#endif
899}
900
901inline std::string format_compact(const Json::Value &root,
902 const size_t size_hint = 256)
903{
904 auto bp = BufferAllocated(size_hint, BufAllocFlags::GROW);
905 format_compact(root, bp);
906 return buf_to_string(bp);
907}
908
909inline void format(const Json::Value &root, Buffer &buf)
910{
911#ifdef OPENVPN_JSON
912 root.toStyledString(buf);
913#else
914 Json::StreamWriterBuilder json_builder;
915 json_builder.settings_["indentation"] = " ";
916 BufferStreamOut os(buf);
917 std::unique_ptr<Json::StreamWriter> sw(json_builder.newStreamWriter());
918 sw->write(root, &os);
919#endif
920}
921
922inline std::string format(const Json::Value &root)
923{
924 return root.toStyledString();
925}
926
927inline std::string error(const Json::Value &root)
928{
929 const Json::Value &je = root["error"];
930 if (je.isString())
931 return je.asString();
932 else
933 return std::string();
934}
935
936// Guarantee that json object jr is a dictionary.
937// Do this by encapsulating jr in a dictionary
938// { "result": jr } if it is not already one.
939inline Json::Value dict_result(Json::Value jr)
940{
941 if (jr.isObject())
942 return jr;
943 else
944 {
945 Json::Value jret(Json::objectValue);
946 jret["result"] = std::move(jr);
947 return jret;
948 }
949}
950} // namespace openvpn::json
#define OPENVPN_EXCEPTION(C)
#define REENABLE_DANGLING_WARNINGS()
#define DISABLE_DANGLING_WARNINGS()
constexpr BufferFlags GROW(1u<< 2)
if enabled, buffer will grow (otherwise buffer_full exception will be thrown)
const auto cast(const C &container)
Provide an instance of C2os::Container<C> from the underlying container.
const char * name(const KeyDerivation kd)
std::string to_string(std::nullptr_t)
void assert_dict(const Json::Value &obj, const TITLE &title)
int get_bool_tristate(const Json::Value &root, const NAME &name)
std::string fmt_name_cast(const TITLE &title)
void to_string_optional(const Json::Value &root, std::string &dest, const NAME &name, const std::string &default_value, const TITLE &title)
std::uint64_t get_integer_optional(const Json::Value &root, const NAME &name, const std::uint64_t default_value, const TITLE &title)
void format(const Json::Value &root, Buffer &buf)
std::string fmt_name(const NAME &name, const TITLE &title)
int get_int(const Json::Value &root, const NAME &name, const TITLE &title)
void to_uint64(const Json::Value &root, std::uint64_t &dest, const NAME &name, const TITLE &title)
std::uint64_t get_uint64(const Json::Value &root, const NAME &name, const TITLE &title)
void to_string(const Json::Value &root, std::string &dest, const NAME &name, const TITLE &title)
void to_uint(const Json::Value &root, unsigned int &dest, const NAME &name, const TITLE &title)
unsigned int get_uint_optional_via_string(const Json::Value &root, const NAME &name, const unsigned int default_value, const TITLE &title)
Json::Value parse_from_file(const std::string &fn)
const Json::Value & get_array(const Json::Value &root, const NAME &name, const bool optional, const TITLE &title)
bool string_exists(const Json::Value &root, const NAME &name)
std::int64_t get_int64_optional(const Json::Value &root, const NAME &name, const std::uint64_t default_value, const TITLE &title)
void to_int(const Json::Value &root, int &dest, const NAME &name, const TITLE &title)
bool get_bool_optional(const Json::Value &root, const NAME &name, const bool default_value=false)
bool get_bool(const Json::Value &root, const NAME &name, const TITLE &title)
unsigned int get_uint(const Json::Value &root, const NAME &name, const TITLE &title)
void to_uchar(const Json::Value &root, unsigned char &dest, const NAME &name, const TITLE &title)
std::uint64_t get_uint64_optional_via_string(const Json::Value &root, const NAME &name, const std::uint64_t default_value, const TITLE &title)
unsigned int get_uint_optional(const Json::Value &root, const NAME &name, const unsigned int default_value, const TITLE &title)
const Json::Value & get_dict(const Json::Value &root, const NAME &name, const bool optional, const TITLE &title)
const Json::Value & cast_array(const Json::Value &value, const bool optional, const TITLE &title)
bool is_dict(const Json::Value &obj, const TITLE &title)
void to_vector(const Json::Value &root, T &vec, const NAME &name, const TITLE &title)
bool exists(const Json::Value &root, const NAME &name)
int get_int_optional(const Json::Value &root, const NAME &name, const int default_value, const TITLE &title)
std::string error(const Json::Value &root)
std::string get_string_optional(const Json::Value &root, const NAME &name, const std::string &default_value, const TITLE &title)
std::uint64_t get_uint64_via_string(const Json::Value &root, const NAME &name, const TITLE &title)
void to_bool(const Json::Value &root, bool &dest, const NAME &name, const TITLE &title)
std::string get_string_from_array(const Json::Value &root, const Json::ArrayIndex index, const TITLE &title)
Json::Value parse(const std::string &str, const TITLE &title)
void from_vector(Json::Value &root, const T &vec, const NAME &name)
Json::Value dict_result(Json::Value jr)
const Json::Value & cast_dict(const Json::Value &value, const bool optional, const TITLE &title)
void format_compact(const Json::Value &root, Buffer &buf)
unsigned int get_uint_via_string(const Json::Value &root, const NAME &name, const TITLE &title)
std::uint64_t get_uint64_optional(const Json::Value &root, const NAME &name, const std::uint64_t default_value, const TITLE &title)
std::string get_string(const Json::Value &root, const NAME &name, const TITLE &title)
Json::Value parse_from_buffer(const BUFFER &buf, const TITLE &title)
void to_uint_optional(const Json::Value &root, unsigned int &dest, const NAME &name, const unsigned int default_value, const TITLE &title)
std::string root(const std::string &basename)
Definition path.hpp:171
std::string read_text_utf8(const std::string &filename, const std::uint64_t max_size=0)
Definition file.hpp:136
BufferAllocatedType< unsigned char > BufferAllocated
Definition buffer.hpp:1897
bool parse_number(const char *str, T &retval, const bool nondigit_term=false)
Definition number.hpp:34
std::string buf_to_string(const Buffer &buf)
Definition bufstr.hpp:22
os<< "Session Name: "<< tbc-> session_name<< '\n';os<< "Layer: "<< tbc-> layer str()<< '\n'
std::string ret
std::ostringstream os