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 return default_value;
623}
624
625template <typename NAME>
626inline int get_bool_tristate(const Json::Value &root,
627 const NAME &name)
628{
629 const Json::Value &jv = root[name];
630 if (jv.isConvertibleTo(Json::booleanValue))
631 return jv.asBool() ? 1 : 0;
632 return -1;
633}
634
636template <typename NAME, typename TITLE>
637inline const Json::Value &get_dict(const Json::Value &root,
638 const NAME &name,
639 const bool optional,
640 const TITLE &title)
641{
642 const Json::Value &value = root[name];
643 if (value.isNull())
644 {
645 if (optional)
646 return value;
647 throw json_parse("dictionary " + fmt_name(name, title) + " is missing");
648 }
649 if (!value.isObject())
650 throw json_parse("dictionary " + fmt_name(name, title) + " is of incorrect type");
651 return value;
652}
654
655template <typename NAME>
656inline const Json::Value &get_dict(const Json::Value &root,
657 const NAME &name,
658 const bool optional)
659{
660 return get_dict(root, name, optional, nullptr);
661}
662
663template <typename NAME, typename TITLE>
664inline Json::Value get_dict(Json::Value &&root,
665 const NAME &name,
666 const bool optional,
667 const TITLE &title)
668{
669 Json::Value r = std::move(root);
670 return get_dict(r, name, optional, title);
671}
672
673template <typename NAME>
674inline Json::Value get_dict(Json::Value &&root,
675 const NAME &name,
676 const bool optional)
677{
678 return get_dict(std::move(root), name, optional, nullptr);
679}
680
682template <typename TITLE>
683inline const Json::Value &cast_dict(const Json::Value &value,
684 const bool optional,
685 const TITLE &title)
686{
687 if (value.isNull())
688 {
689 if (optional)
690 return value;
691 throw json_parse("dictionary cast " + fmt_name_cast(title) + " is null");
692 }
693 if (!value.isObject())
694 throw json_parse("dictionary cast " + fmt_name_cast(title) + " is of incorrect type");
695 return value;
696}
698
699inline const Json::Value &cast_dict(const Json::Value &value,
700 const bool optional)
701{
702 return cast_dict(value, optional, nullptr);
703}
704
705template <typename TITLE>
706inline Json::Value cast_dict(Json::Value &&value,
707 const bool optional,
708 const TITLE &title)
709{
710 Json::Value ret = std::move(value);
711 cast_dict(ret, optional, title);
712 return ret;
713}
714
715inline Json::Value cast_dict(Json::Value &&value,
716 const bool optional)
717{
718 return cast_dict(std::move(value), optional, nullptr);
719}
720
722template <typename NAME, typename TITLE>
723inline const Json::Value &get_array(const Json::Value &root,
724 const NAME &name,
725 const bool optional,
726 const TITLE &title)
727{
728 const Json::Value &value = root[name];
729 if (value.isNull())
730 {
731 if (optional)
732 return value;
733 throw json_parse("array " + fmt_name(name, title) + " is missing");
734 }
735 if (!value.isArray())
736 throw json_parse("array " + fmt_name(name, title) + " is of incorrect type");
737 return value;
738}
740
741template <typename NAME>
742inline const Json::Value &get_array(const Json::Value &root,
743 const NAME &name,
744 const bool optional)
745{
746 return get_array(root, name, optional, nullptr);
747}
748
749template <typename NAME, typename TITLE>
750inline Json::Value get_array(Json::Value &&root,
751 const NAME &name,
752 const bool optional,
753 const TITLE &title)
754{
755 Json::Value r = std::move(root);
756 return get_array(r, name, optional, title);
757}
758
759template <typename NAME>
760inline Json::Value get_array(Json::Value &&root,
761 const NAME &name,
762 const bool optional)
763{
764 return get_array(std::move(root), name, optional, nullptr);
765}
766
768template <typename TITLE>
769inline const Json::Value &cast_array(const Json::Value &value,
770 const bool optional,
771 const TITLE &title)
772{
773 if (value.isNull())
774 {
775 if (optional)
776 return value;
777 throw json_parse("array cast " + fmt_name_cast(title) + " is null");
778 }
779 if (!value.isArray())
780 throw json_parse("array cast " + fmt_name_cast(title) + " is of incorrect type");
781 return value;
782}
784
785inline const Json::Value &cast_array(const Json::Value &value,
786 const bool optional)
787{
788 return cast_array(value, optional, nullptr);
789}
790
791template <typename TITLE>
792inline Json::Value cast_array(Json::Value &&value,
793 const bool optional,
794 const TITLE &title)
795{
796 Json::Value ret = std::move(value);
797 cast_array(ret, optional, title);
798 return ret;
799}
800
801inline Json::Value cast_array(Json::Value &&value,
802 const bool optional)
803{
804 return cast_array(std::move(value), optional, nullptr);
805}
806
807template <typename NAME, typename TITLE>
808inline void to_string(const Json::Value &root,
809 std::string &dest,
810 const NAME &name,
811 const TITLE &title)
812{
813 dest = get_string(root, name, title);
814}
815
816template <typename NAME, typename TITLE>
817inline void to_string_optional(const Json::Value &root,
818 std::string &dest,
819 const NAME &name,
820 const std::string &default_value,
821 const TITLE &title)
822{
823 dest = get_string_optional(root, name, default_value, title);
824}
825
826template <typename NAME, typename TITLE>
827inline void to_int(const Json::Value &root,
828 int &dest,
829 const NAME &name,
830 const TITLE &title)
831{
832 dest = get_int(root, name, title);
833}
834
835template <typename NAME, typename TITLE>
836inline void to_uchar(const Json::Value &root,
837 unsigned char &dest,
838 const NAME &name,
839 const TITLE &title)
840{
841 auto temp = get_int(root, name, title);
842 dest = clamp_notify<unsigned char>(temp,
843 [](decltype(temp) temp) -> unsigned char
844 {
845 auto why = std::string("Conversion error [" + std::to_string(temp) + "] to unsigned char");
846 throw json_parse(std::move(why)); });
847}
848
849template <typename NAME, typename TITLE>
850inline void to_uint(const Json::Value &root,
851 unsigned int &dest,
852 const NAME &name,
853 const TITLE &title)
854{
855 dest = get_uint(root, name, title);
856}
857
858template <typename NAME, typename TITLE>
859inline void to_uint_optional(const Json::Value &root,
860 unsigned int &dest,
861 const NAME &name,
862 const unsigned int default_value,
863 const TITLE &title)
864{
865 dest = get_uint_optional(root, name, default_value, title);
866}
867
868template <typename NAME, typename TITLE>
869inline void to_uint64(const Json::Value &root,
870 std::uint64_t &dest,
871 const NAME &name,
872 const TITLE &title)
873{
874 dest = get_uint64(root, name, title);
875}
876
877template <typename NAME, typename TITLE>
878inline void to_bool(const Json::Value &root,
879 bool &dest,
880 const NAME &name,
881 const TITLE &title)
882{
883 dest = get_bool(root, name, title);
884}
885
886inline void format_compact(const Json::Value &root, Buffer &buf)
887{
888#ifdef OPENVPN_JSON
889 root.toCompactString(buf);
890#else
891 Json::StreamWriterBuilder json_builder;
892 json_builder.settings_["indentation"] = "";
893 BufferStreamOut os(buf);
894 std::unique_ptr<Json::StreamWriter> sw(json_builder.newStreamWriter());
895 sw->write(root, &os);
896#endif
897}
898
899inline std::string format_compact(const Json::Value &root,
900 const size_t size_hint = 256)
901{
902 auto bp = BufferAllocated(size_hint, BufAllocFlags::GROW);
903 format_compact(root, bp);
904 return buf_to_string(bp);
905}
906
907inline void format(const Json::Value &root, Buffer &buf)
908{
909#ifdef OPENVPN_JSON
910 root.toStyledString(buf);
911#else
912 Json::StreamWriterBuilder json_builder;
913 json_builder.settings_["indentation"] = " ";
914 BufferStreamOut os(buf);
915 std::unique_ptr<Json::StreamWriter> sw(json_builder.newStreamWriter());
916 sw->write(root, &os);
917#endif
918}
919
920inline std::string format(const Json::Value &root)
921{
922 return root.toStyledString();
923}
924
925inline std::string error(const Json::Value &root)
926{
927 const Json::Value &je = root["error"];
928 if (je.isString())
929 return je.asString();
930 return std::string();
931}
932
933// Guarantee that json object jr is a dictionary.
934// Do this by encapsulating jr in a dictionary
935// { "result": jr } if it is not already one.
936inline Json::Value dict_result(Json::Value jr)
937{
938 if (jr.isObject())
939 return jr;
940
941 Json::Value jret(Json::objectValue);
942 jret["result"] = std::move(jr);
943 return jret;
944}
945} // namespace openvpn::json
designed to represent an optional reference to an object of type T
#define OPENVPN_EXCEPTION(C)
Definition exception.hpp:99
#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:165
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:1894
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