some parsing performance improvements
This commit is contained in:
parent
abb8653115
commit
5ed80d308d
3 changed files with 167 additions and 151 deletions
158
src/json.hpp
158
src/json.hpp
|
@ -147,6 +147,23 @@ class basic_json
|
||||||
using list_init_t = std::initializer_list<basic_json>;
|
using list_init_t = std::initializer_list<basic_json>;
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
// JSON value type enumeration //
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
/// JSON value type enumeration
|
||||||
|
enum class value_t : uint8_t
|
||||||
|
{
|
||||||
|
null, ///< null value
|
||||||
|
object, ///< object (unordered set of name/value pairs)
|
||||||
|
array, ///< array (ordered collection of values)
|
||||||
|
string, ///< string value
|
||||||
|
boolean, ///< boolean value
|
||||||
|
number_integer, ///< number value (integer)
|
||||||
|
number_float, ///< number value (floating-point)
|
||||||
|
discarded ///< (internal) indicates the parser callback chose not to keep the value
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// JSON value storage //
|
// JSON value storage //
|
||||||
////////////////////////
|
////////////////////////
|
||||||
|
@ -175,24 +192,60 @@ class basic_json
|
||||||
json_value(number_integer_t v) : number_integer(v) {}
|
json_value(number_integer_t v) : number_integer(v) {}
|
||||||
/// constructor for numbers (floating-point)
|
/// constructor for numbers (floating-point)
|
||||||
json_value(number_float_t v) : number_float(v) {}
|
json_value(number_float_t v) : number_float(v) {}
|
||||||
};
|
/// constructor for empty values of a given type
|
||||||
|
json_value(value_t t)
|
||||||
|
{
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case (value_t::null):
|
||||||
|
case (value_t::discarded):
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case (value_t::object):
|
||||||
|
{
|
||||||
|
AllocatorType<object_t> alloc;
|
||||||
|
object = alloc.allocate(1);
|
||||||
|
alloc.construct(object);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////
|
case (value_t::array):
|
||||||
// JSON value type enumeration //
|
{
|
||||||
/////////////////////////////////
|
AllocatorType<array_t> alloc;
|
||||||
|
array = alloc.allocate(1);
|
||||||
|
alloc.construct(array);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/// JSON value type enumeration
|
case (value_t::string):
|
||||||
enum class value_t : uint8_t
|
{
|
||||||
{
|
AllocatorType<string_t> alloc;
|
||||||
null, ///< null value
|
string = alloc.allocate(1);
|
||||||
object, ///< object (unordered set of name/value pairs)
|
alloc.construct(string, "");
|
||||||
array, ///< array (ordered collection of values)
|
break;
|
||||||
string, ///< string value
|
}
|
||||||
boolean, ///< boolean value
|
|
||||||
number_integer, ///< number value (integer)
|
case (value_t::boolean):
|
||||||
number_float, ///< number value (floating-point)
|
{
|
||||||
discarded ///< (internal) indicates the parser callback chose not to keep the value
|
boolean = boolean_t(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case (value_t::number_integer):
|
||||||
|
{
|
||||||
|
number_integer = number_integer_t(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case (value_t::number_float):
|
||||||
|
{
|
||||||
|
number_float = number_float_t(0.0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
@ -261,59 +314,8 @@ class basic_json
|
||||||
@exception std::bad_alloc if allocation for object, array, or string fails.
|
@exception std::bad_alloc if allocation for object, array, or string fails.
|
||||||
*/
|
*/
|
||||||
inline basic_json(const value_t value)
|
inline basic_json(const value_t value)
|
||||||
: m_type(value)
|
: m_type(value), m_value(value)
|
||||||
{
|
{}
|
||||||
switch (m_type)
|
|
||||||
{
|
|
||||||
case (value_t::null):
|
|
||||||
case (value_t::discarded):
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::object):
|
|
||||||
{
|
|
||||||
AllocatorType<object_t> alloc;
|
|
||||||
m_value.object = alloc.allocate(1);
|
|
||||||
alloc.construct(m_value.object);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::array):
|
|
||||||
{
|
|
||||||
AllocatorType<array_t> alloc;
|
|
||||||
m_value.array = alloc.allocate(1);
|
|
||||||
alloc.construct(m_value.array);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::string):
|
|
||||||
{
|
|
||||||
AllocatorType<string_t> alloc;
|
|
||||||
m_value.string = alloc.allocate(1);
|
|
||||||
alloc.construct(m_value.string, "");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::boolean):
|
|
||||||
{
|
|
||||||
m_value.boolean = boolean_t(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::number_integer):
|
|
||||||
{
|
|
||||||
m_value.number_integer = number_integer_t(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::number_float):
|
|
||||||
{
|
|
||||||
m_value.number_float = number_float_t(0.0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief create a null object (implicitly)
|
@brief create a null object (implicitly)
|
||||||
|
@ -4629,7 +4631,8 @@ basic_json_parser_59:
|
||||||
if (keep and (keep = callback(depth++, parse_event_t::object_start, result)))
|
if (keep and (keep = callback(depth++, parse_event_t::object_start, result)))
|
||||||
{
|
{
|
||||||
// explicitly set result to object to cope with {}
|
// explicitly set result to object to cope with {}
|
||||||
result = basic_json(value_t::object);
|
result.m_type = value_t::object;
|
||||||
|
result.m_value = json_value(value_t::object);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read next token
|
// read next token
|
||||||
|
@ -4698,7 +4701,8 @@ basic_json_parser_59:
|
||||||
if (keep and (keep = callback(depth++, parse_event_t::array_start, result)))
|
if (keep and (keep = callback(depth++, parse_event_t::array_start, result)))
|
||||||
{
|
{
|
||||||
// explicitly set result to object to cope with []
|
// explicitly set result to object to cope with []
|
||||||
result = basic_json(value_t::array);
|
result.m_type = value_t::array;
|
||||||
|
result.m_value = json_value(value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read next token
|
// read next token
|
||||||
|
@ -4750,7 +4754,7 @@ basic_json_parser_59:
|
||||||
case (lexer::token_type::literal_null):
|
case (lexer::token_type::literal_null):
|
||||||
{
|
{
|
||||||
get_token();
|
get_token();
|
||||||
result = basic_json(nullptr);
|
result.m_type = value_t::null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4765,14 +4769,16 @@ basic_json_parser_59:
|
||||||
case (lexer::token_type::literal_true):
|
case (lexer::token_type::literal_true):
|
||||||
{
|
{
|
||||||
get_token();
|
get_token();
|
||||||
result = basic_json(true);
|
result.m_type = value_t::boolean;
|
||||||
|
result.m_value = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case (lexer::token_type::literal_false):
|
case (lexer::token_type::literal_false):
|
||||||
{
|
{
|
||||||
get_token();
|
get_token();
|
||||||
result = basic_json(false);
|
result.m_type = value_t::boolean;
|
||||||
|
result.m_value = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4795,12 +4801,14 @@ basic_json_parser_59:
|
||||||
if (approx(float_val, static_cast<number_float_t>(int_val)))
|
if (approx(float_val, static_cast<number_float_t>(int_val)))
|
||||||
{
|
{
|
||||||
// we basic_json not lose precision -> return int
|
// we basic_json not lose precision -> return int
|
||||||
result = basic_json(int_val);
|
result.m_type = value_t::number_integer;
|
||||||
|
result.m_value = int_val;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we would lose precision -> returnfloat
|
// we would lose precision -> returnfloat
|
||||||
result = basic_json(float_val);
|
result.m_type = value_t::number_float;
|
||||||
|
result.m_value = float_val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,23 @@ class basic_json
|
||||||
using list_init_t = std::initializer_list<basic_json>;
|
using list_init_t = std::initializer_list<basic_json>;
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
// JSON value type enumeration //
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
/// JSON value type enumeration
|
||||||
|
enum class value_t : uint8_t
|
||||||
|
{
|
||||||
|
null, ///< null value
|
||||||
|
object, ///< object (unordered set of name/value pairs)
|
||||||
|
array, ///< array (ordered collection of values)
|
||||||
|
string, ///< string value
|
||||||
|
boolean, ///< boolean value
|
||||||
|
number_integer, ///< number value (integer)
|
||||||
|
number_float, ///< number value (floating-point)
|
||||||
|
discarded ///< (internal) indicates the parser callback chose not to keep the value
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// JSON value storage //
|
// JSON value storage //
|
||||||
////////////////////////
|
////////////////////////
|
||||||
|
@ -175,24 +192,60 @@ class basic_json
|
||||||
json_value(number_integer_t v) : number_integer(v) {}
|
json_value(number_integer_t v) : number_integer(v) {}
|
||||||
/// constructor for numbers (floating-point)
|
/// constructor for numbers (floating-point)
|
||||||
json_value(number_float_t v) : number_float(v) {}
|
json_value(number_float_t v) : number_float(v) {}
|
||||||
};
|
/// constructor for empty values of a given type
|
||||||
|
json_value(value_t t)
|
||||||
|
{
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case (value_t::null):
|
||||||
|
case (value_t::discarded):
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case (value_t::object):
|
||||||
|
{
|
||||||
|
AllocatorType<object_t> alloc;
|
||||||
|
object = alloc.allocate(1);
|
||||||
|
alloc.construct(object);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////
|
case (value_t::array):
|
||||||
// JSON value type enumeration //
|
{
|
||||||
/////////////////////////////////
|
AllocatorType<array_t> alloc;
|
||||||
|
array = alloc.allocate(1);
|
||||||
|
alloc.construct(array);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/// JSON value type enumeration
|
case (value_t::string):
|
||||||
enum class value_t : uint8_t
|
{
|
||||||
{
|
AllocatorType<string_t> alloc;
|
||||||
null, ///< null value
|
string = alloc.allocate(1);
|
||||||
object, ///< object (unordered set of name/value pairs)
|
alloc.construct(string, "");
|
||||||
array, ///< array (ordered collection of values)
|
break;
|
||||||
string, ///< string value
|
}
|
||||||
boolean, ///< boolean value
|
|
||||||
number_integer, ///< number value (integer)
|
case (value_t::boolean):
|
||||||
number_float, ///< number value (floating-point)
|
{
|
||||||
discarded ///< (internal) indicates the parser callback chose not to keep the value
|
boolean = boolean_t(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case (value_t::number_integer):
|
||||||
|
{
|
||||||
|
number_integer = number_integer_t(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case (value_t::number_float):
|
||||||
|
{
|
||||||
|
number_float = number_float_t(0.0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
@ -261,59 +314,8 @@ class basic_json
|
||||||
@exception std::bad_alloc if allocation for object, array, or string fails.
|
@exception std::bad_alloc if allocation for object, array, or string fails.
|
||||||
*/
|
*/
|
||||||
inline basic_json(const value_t value)
|
inline basic_json(const value_t value)
|
||||||
: m_type(value)
|
: m_type(value), m_value(value)
|
||||||
{
|
{}
|
||||||
switch (m_type)
|
|
||||||
{
|
|
||||||
case (value_t::null):
|
|
||||||
case (value_t::discarded):
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::object):
|
|
||||||
{
|
|
||||||
AllocatorType<object_t> alloc;
|
|
||||||
m_value.object = alloc.allocate(1);
|
|
||||||
alloc.construct(m_value.object);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::array):
|
|
||||||
{
|
|
||||||
AllocatorType<array_t> alloc;
|
|
||||||
m_value.array = alloc.allocate(1);
|
|
||||||
alloc.construct(m_value.array);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::string):
|
|
||||||
{
|
|
||||||
AllocatorType<string_t> alloc;
|
|
||||||
m_value.string = alloc.allocate(1);
|
|
||||||
alloc.construct(m_value.string, "");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::boolean):
|
|
||||||
{
|
|
||||||
m_value.boolean = boolean_t(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::number_integer):
|
|
||||||
{
|
|
||||||
m_value.number_integer = number_integer_t(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case (value_t::number_float):
|
|
||||||
{
|
|
||||||
m_value.number_float = number_float_t(0.0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief create a null object (implicitly)
|
@brief create a null object (implicitly)
|
||||||
|
@ -3935,7 +3937,8 @@ class basic_json
|
||||||
if (keep and (keep = callback(depth++, parse_event_t::object_start, result)))
|
if (keep and (keep = callback(depth++, parse_event_t::object_start, result)))
|
||||||
{
|
{
|
||||||
// explicitly set result to object to cope with {}
|
// explicitly set result to object to cope with {}
|
||||||
result = basic_json(value_t::object);
|
result.m_type = value_t::object;
|
||||||
|
result.m_value = json_value(value_t::object);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read next token
|
// read next token
|
||||||
|
@ -4004,7 +4007,8 @@ class basic_json
|
||||||
if (keep and (keep = callback(depth++, parse_event_t::array_start, result)))
|
if (keep and (keep = callback(depth++, parse_event_t::array_start, result)))
|
||||||
{
|
{
|
||||||
// explicitly set result to object to cope with []
|
// explicitly set result to object to cope with []
|
||||||
result = basic_json(value_t::array);
|
result.m_type = value_t::array;
|
||||||
|
result.m_value = json_value(value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read next token
|
// read next token
|
||||||
|
@ -4056,7 +4060,7 @@ class basic_json
|
||||||
case (lexer::token_type::literal_null):
|
case (lexer::token_type::literal_null):
|
||||||
{
|
{
|
||||||
get_token();
|
get_token();
|
||||||
result = basic_json(nullptr);
|
result.m_type = value_t::null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4071,14 +4075,16 @@ class basic_json
|
||||||
case (lexer::token_type::literal_true):
|
case (lexer::token_type::literal_true):
|
||||||
{
|
{
|
||||||
get_token();
|
get_token();
|
||||||
result = basic_json(true);
|
result.m_type = value_t::boolean;
|
||||||
|
result.m_value = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case (lexer::token_type::literal_false):
|
case (lexer::token_type::literal_false):
|
||||||
{
|
{
|
||||||
get_token();
|
get_token();
|
||||||
result = basic_json(false);
|
result.m_type = value_t::boolean;
|
||||||
|
result.m_value = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4101,12 +4107,14 @@ class basic_json
|
||||||
if (approx(float_val, static_cast<number_float_t>(int_val)))
|
if (approx(float_val, static_cast<number_float_t>(int_val)))
|
||||||
{
|
{
|
||||||
// we basic_json not lose precision -> return int
|
// we basic_json not lose precision -> return int
|
||||||
result = basic_json(int_val);
|
result.m_type = value_t::number_integer;
|
||||||
|
result.m_value = int_val;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we would lose precision -> returnfloat
|
// we would lose precision -> returnfloat
|
||||||
result = basic_json(float_val);
|
result.m_type = value_t::number_float;
|
||||||
|
result.m_value = float_val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue