55// Sean Middleditch <sean@middleditch.us>
66// rlyeh <https://github.com/r-lyeh>
77
8- #pragma once
8+ #ifndef JSONXX_DEFINE_H
9+ #define JSONXX_DEFINE_H
910
1011#include < cstddef>
11- #include < cassert>
1212#include < iostream>
13+ #include < limits>
1314#include < map>
1415#include < vector>
1516#include < string>
16- #include < sstream >
17+ #include < string_view >
1718
1819// jsonxx versioning: major.minor-extra where
1920// major = { number }
3334# define JSONXX_COMPILER_HAS_CXX11 0
3435#endif
3536
36- #ifdef _MSC_VER
37- // disable the C4127 warning if using VC, see https://stackoverflow.com/a/12042515
38- # define JSONXX_ASSERT (...) \
39- do \
40- { \
41- __pragma (warning (push)) __pragma (warning (disable : 4127 )) if (jsonxx::Assertions) __pragma (warning (pop)) \
42- jsonxx::assertion (__FILE__, __LINE__, #__VA_ARGS__, bool (__VA_ARGS__)); \
43- __pragma (warning (push)) __pragma (warning (disable : 4127 )) \
44- } while (0 ) __pragma(warning(pop))
37+ #define JSONXX_ASSERT (...) \
38+ do \
39+ { \
40+ if (jsonxx::Assertions) \
41+ jsonxx::assertion (__FILE__, __LINE__, #__VA_ARGS__, bool (__VA_ARGS__)); \
42+ } while (0 )
43+
44+ #ifndef JSONXX_HANDLE_INFINITY
45+ # define JSONXX_HANDLE_INFINITY 1
46+ #endif
47+
48+ #ifdef DEBUG
49+ # define JSONXX_WARN (...) std::cerr << " [WARN] " << __VA_ARGS__ << std::endl;
4550#else
46- # define JSONXX_ASSERT (...) \
47- do \
48- { \
49- if (jsonxx::Assertions) \
50- jsonxx::assertion (__FILE__, __LINE__, #__VA_ARGS__, bool (__VA_ARGS__)); \
51- } while (0 )
51+ # define JSONXX_WARN (...) ;
5252#endif
5353
5454namespace jsonxx
5555{
5656
57- // FIXME(hjiang): Those should really be dynamic.
57+ enum PrintMode
58+ {
59+ Pretty,
60+ Compact,
61+ };
62+
5863// Settings
5964enum Settings
6065{
@@ -66,37 +71,18 @@ enum Settings
6671 // values
6772 Parser = Permissive, // permissive or strict parsing
6873 UnquotedKeys = Disabled, // support of unquoted keys
69- Assertions = Enabled // enabled or disabled assertions (these asserts work both in DEBUG and RELEASE builds)
70- };
71-
72- #ifdef _MSC_VER
73- # pragma warning(push)
74- # pragma warning(disable : 4127)
75- #endif
76- inline bool
77- parser_is_strict ()
78- {
79- return Parser == Strict;
80- }
81- inline bool
82- parser_is_permissive ()
83- {
84- return Parser == Permissive;
85- }
86- inline bool
87- unquoted_keys_are_enabled ()
88- {
89- return UnquotedKeys == Enabled;
90- }
91- #ifdef _MSC_VER
92- # pragma warning(pop)
74+ #if DEBUG
75+ Assertions = Enabled // enabled or disabled assertions (these asserts work both in DEBUG and RELEASE builds)
76+ #else
77+ Assertions = Disabled // enabled or disabled assertions (these asserts work both in DEBUG and RELEASE builds)
9378#endif
79+ };
9480
9581// Constants for .write() and .xml() methods
9682enum Format
9783{
9884 JSON = 0 , // JSON output
99- JSONx = 1 , // XML output, JSONx format. see https ://goo.gl/I3cxs
85+ JSONx = 1 , // XML output, JSONx format. see http ://goo.gl/I3cxs
10086 JXML = 2 , // XML output, JXML format. see https://github.com/r-lyeh/JXML
10187 JXMLex = 3 , // XML output, JXMLex format. see https://github.com/r-lyeh/JXMLex
10288 TaggedXML = 4 // XML output, tagged XML format. see https://github.com/hjiang/jsonxx/issues/12
@@ -112,6 +98,21 @@ class Value;
11298class Object ;
11399class Array ;
114100
101+ // Range of Number. Valid numbers outside the range as considered infinite
102+ constexpr Number MaxNumberRange = std::numeric_limits<double >::max();
103+ constexpr Number MinNumberRange = -std::numeric_limits<double >::max();
104+
105+ // JSON representation of infinite numbers
106+ constexpr const char * InfinityRepresentation = " 1e500" ;
107+
108+ // Default value
109+ static const String EmptyString = " " ;
110+ static const Number Zero = 0 ;
111+ static const Number MinusOne = -1 ;
112+ static const Number One = 1 ;
113+ static const Boolean True = true ;
114+ static const Boolean False = false ;
115+
115116// Identity meta-function
116117template <typename T>
117118struct identity
@@ -161,6 +162,11 @@ class Object
161162 const T &
162163 get (const std::string & key, const typename identity<T>::type & default_value) const ;
163164
165+ // Delete unsafe operation
166+ template <typename T>
167+ const T &
168+ get (const std::string & key, typename identity<T>::type && default_value) const = delete ;
169+
164170 size_t
165171 size () const ;
166172 bool
@@ -169,11 +175,12 @@ class Object
169175 const std::map<std::string, Value *> &
170176 kv_map () const ;
171177 std::string
172- json () const ;
178+ json (PrintMode printMode = PrintMode::Compact, int floatPrecision = std::numeric_limits< double >::digits10 + 1 ) const ;
173179 std::string
174180 xml (unsigned format = JSONx,
175181 const std::string & header = std::string(),
176- const std::string & attrib = std::string()) const ;
182+ const std::string & attrib = std::string(),
183+ int floatPrecision = std::numeric_limits<double >::digits10 + 1 ) const ;
177184 std::string
178185 write (unsigned format) const ;
179186
@@ -212,6 +219,8 @@ class Object
212219 std::string odd;
213220};
214221
222+ static const Object EmptyObject = {};
223+
215224class Array
216225{
217226public:
@@ -238,17 +247,23 @@ class Array
238247 const T &
239248 get (unsigned int i, const typename identity<T>::type & default_value) const ;
240249
250+ // Delete unsafe operation
251+ template <typename T>
252+ const T &
253+ get (unsigned int i, typename identity<T>::type && default_value) const = delete ;
254+
241255 const std::vector<Value *> &
242256 values () const
243257 {
244258 return values_;
245259 }
246260 std::string
247- json () const ;
261+ json (PrintMode printMode = PrintMode::Compact, int floatPrecision = std::numeric_limits< double >::digits10 + 1 ) const ;
248262 std::string
249263 xml (unsigned format = JSONx,
250264 const std::string & header = std::string(),
251- const std::string & attrib = std::string()) const ;
265+ const std::string & attrib = std::string(),
266+ int floatPrecision = std::numeric_limits<double >::digits10 + 1 ) const ;
252267
253268 std::string
254269 write (unsigned format) const
@@ -263,13 +278,6 @@ class Array
263278 parse (const std::string & input);
264279 typedef std::vector<Value *> container;
265280 void
266- append (const Array & other);
267- void
268- append (const Value & value)
269- {
270- import (value);
271- }
272- void
273281 import (const Array & other);
274282 void
275283 import (const Value & value);
@@ -290,6 +298,8 @@ class Array
290298 container values_;
291299};
292300
301+ static const Array EmptyArray = {};
302+
293303// A value could be a number, an array, a string, an object, a
294304// boolean, or null
295305class Value
@@ -300,35 +310,41 @@ class Value
300310 void
301311 reset ();
302312
313+ #ifdef JSONXX_ALLOW_INVALID_TYPES
303314 template <typename T>
315+ [[deprecated(" this type is not natively supported by jsonxx, therefore its value will be converted to 'null'" )]]
304316 void
305- import (const T &)
317+ import (const T & t )
306318 {
307319 reset ();
308320 type_ = INVALID_;
309- // debug
310- // std::cout << "[WARN] No support for " << typeid(t).name() << std::endl;
321+ JSONXX_WARN (" No JSONXX support for " << typeid (t).name ());
311322 }
323+ #else
324+ template <typename T>
325+ void
326+ import (const T & t) = delete;
327+ #endif
328+
312329 void
313330 import (const bool & b)
314331 {
315332 reset ();
316333 type_ = BOOL_;
317334 bool_value_ = b;
318335 }
319- #define local_number (TYPE ) \
336+ #define $number (TYPE) \
320337 void import (const TYPE & n) \
321338 { \
322339 reset (); \
323340 type_ = NUMBER_; \
324341 number_value_ = static_cast <long double >(n); \
325342 }
326- local_number (char ) local_number(int ) local_number(long ) local_number(long long ) local_number(unsigned char )
327- local_number (unsigned int ) local_number(unsigned long ) local_number(unsigned long long ) local_number(float )
328- local_number (double ) local_number(long double )
329- #undef local_number
343+ $number(char ) $number(int ) $number(long ) $number(long long ) $number(unsigned char ) $number(unsigned int )
344+ $number(unsigned long ) $number(unsigned long long ) $number(float ) $number(double ) $number(long double )
345+ #undef $number
330346#if JSONXX_COMPILER_HAS_CXX11 > 0
331- void import (const std::nullptr_t &)
347+ void import (const std::nullptr_t &)
332348 {
333349 reset ();
334350 type_ = NULL_;
@@ -348,6 +364,24 @@ class Value
348364 *(string_value_ = new String ()) = s;
349365 }
350366 void
367+ import (const std::string_view & sv)
368+ {
369+ reset ();
370+ type_ = STRING_;
371+ *(string_value_ = new String ()) = sv;
372+ }
373+ template <typename T>
374+ void
375+ import (const std::vector<T> & array)
376+ {
377+ Array a;
378+ for (const auto & elmt : array)
379+ {
380+ a << elmt;
381+ }
382+ import (a);
383+ }
384+ void
351385 import (const Array & a)
352386 {
353387 reset ();
@@ -408,14 +442,31 @@ class Value
408442 return *this ;
409443 }
410444 Value (const Value & other);
411- template <typename T>
412- Value (const T & t)
413- : type_(INVALID_)
414- {
415- import (t);
445+
446+ #define $Value(TYPE) \
447+ Value (const TYPE & t) \
448+ : type_(INVALID_) \
449+ { \
450+ import (t); \
416451 }
417- template <size_t N>
418- Value (const char (&t)[N])
452+
453+ #ifdef JSONXX_ALLOW_INVALID_TYPES
454+ template <typename T>
455+ $Value(T)
456+ #else
457+ $Value(bool ) $Value(char ) $Value(int ) $Value(long ) $Value(long long ) $Value(unsigned char ) $Value(unsigned int )
458+ $Value(unsigned long ) $Value(unsigned long long ) $Value(float ) $Value(double ) $Value(long double )
459+ # if JSONXX_COMPILER_HAS_CXX11 > 0
460+ $Value(std::nullptr_t )
461+ # endif
462+ $Value(Null) $Value(String) $Value(std::string_view) template <typename T>
463+ $Value(std::vector<T>) $Value(Array) $Value(Object)
464+ #endif
465+
466+ #undef $Value
467+
468+ template <size_t N>
469+ Value (const char (&t)[N])
419470 : type_(INVALID_)
420471 {
421472 import (std::string (t));
@@ -464,6 +515,8 @@ class Value
464515 parse (std::istream & input, Value & value);
465516};
466517
518+ static const Value EmptyValue = {};
519+
467520template <typename T>
468521bool
469522Array::has (unsigned int i) const
@@ -501,15 +554,15 @@ template <typename T>
501554const T &
502555Array::get (unsigned int i, const typename identity<T>::type & default_value) const
503556{
504- if (has<T>(i ))
557+ if (i < size ( ))
505558 {
506559 const Value * v = values_.at (i);
507- return v->get <T>();
508- }
509- else
510- {
511- return default_value;
560+ if (v->is <T>())
561+ {
562+ return v->get <T>();
563+ }
512564 }
565+ return default_value;
513566}
514567
515568template <typename T>
@@ -540,9 +593,10 @@ template <typename T>
540593const T &
541594Object::get (const std::string & key, const typename identity<T>::type & default_value) const
542595{
543- if (has<T>(key))
596+ auto iterator = value_map_.find (key);
597+ if (iterator != value_map_.end () && iterator->second ->is <T>())
544598 {
545- return value_map_. find (key) ->second ->get <T>();
599+ return iterator ->second ->get <T>();
546600 }
547601 else
548602 {
@@ -700,7 +754,6 @@ Object::operator<<(const T & value)
700754 *this << Value (value);
701755 return *this ;
702756}
703-
704757} // namespace jsonxx
705758
706759std::ostream &
@@ -709,3 +762,5 @@ std::ostream &
709762operator <<(std::ostream & stream, const jsonxx::Object & v);
710763std::ostream &
711764operator <<(std::ostream & stream, const jsonxx::Array & v);
765+
766+ #endif
0 commit comments