Skip to content

Commit 37cd183

Browse files
committed
COMP: Update jsonxx to latest TransitApp/jsonxx (eede690)
Update vendored jsonxx to TransitApp/jsonxx master (eede690, 2025-11-24) which includes an includes cleanup removing cassert from the header. The original hjiang/jsonxx repo (v1.0.1) has not been updated since 2021; TransitApp fork is the actively maintained continuation. Replace GCC case range extension with individual case labels for MSVC. Applied clang-format 19.1.7 to match project style.
1 parent 6eddcef commit 37cd183

2 files changed

Lines changed: 323 additions & 218 deletions

File tree

include/jsonxx.h

Lines changed: 135 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
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 }
@@ -33,28 +34,32 @@
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

5454
namespace jsonxx
5555
{
5656

57-
// FIXME(hjiang): Those should really be dynamic.
57+
enum PrintMode
58+
{
59+
Pretty,
60+
Compact,
61+
};
62+
5863
// Settings
5964
enum 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
9682
enum 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;
11298
class Object;
11399
class 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
116117
template <typename T>
117118
struct 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+
215224
class Array
216225
{
217226
public:
@@ -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
295305
class 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+
467520
template <typename T>
468521
bool
469522
Array::has(unsigned int i) const
@@ -501,15 +554,15 @@ template <typename T>
501554
const T &
502555
Array::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

515568
template <typename T>
@@ -540,9 +593,10 @@ template <typename T>
540593
const T &
541594
Object::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

706759
std::ostream &
@@ -709,3 +762,5 @@ std::ostream &
709762
operator<<(std::ostream & stream, const jsonxx::Object & v);
710763
std::ostream &
711764
operator<<(std::ostream & stream, const jsonxx::Array & v);
765+
766+
#endif

0 commit comments

Comments
 (0)