mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-21 09:10:48 +00:00
Optimization by using implementation-specific JSONParser::sizeOfArray(), JSONParser::sizeOfObject().
This commit is contained in:
parent
823d862ceb
commit
095fc7b454
@ -17,18 +17,12 @@ struct DummyJSONParser
|
||||
{
|
||||
static constexpr bool need_preallocate = false;
|
||||
void preallocate(size_t) {}
|
||||
bool parse(const char *, size_t) { throw Exception{"Functions JSON* are not supported without AVX2", ErrorCodes::NOT_IMPLEMENTED}; }
|
||||
|
||||
bool parse(const StringRef &) { throw Exception{"Functions JSON* are not supported without AVX2", ErrorCodes::NOT_IMPLEMENTED}; }
|
||||
|
||||
using Iterator = std::nullptr_t;
|
||||
Iterator getRoot() const { return nullptr; }
|
||||
|
||||
static bool downToArray(Iterator &) { return false; }
|
||||
static bool downToObject(Iterator &) { return false; }
|
||||
static bool downToObject(Iterator &, StringRef &) { return false; }
|
||||
static bool parentScopeIsObject(const Iterator &) { return false; }
|
||||
static bool next(Iterator &) { return false; }
|
||||
static bool nextKeyValue(Iterator &) { return false; }
|
||||
static bool nextKeyValue(Iterator &, StringRef &) { return false; }
|
||||
static bool isInt64(const Iterator &) { return false; }
|
||||
static bool isUInt64(const Iterator &) { return false; }
|
||||
static bool isDouble(const Iterator &) { return false; }
|
||||
@ -36,13 +30,28 @@ struct DummyJSONParser
|
||||
static bool isArray(const Iterator &) { return false; }
|
||||
static bool isObject(const Iterator &) { return false; }
|
||||
static bool isBool(const Iterator &) { return false; }
|
||||
static bool isNull(const Iterator &) { return false; }
|
||||
static StringRef getKey(const Iterator &) { return {}; }
|
||||
static StringRef getString(const Iterator &) { return {}; }
|
||||
static bool isNull(const Iterator &) { return true; }
|
||||
|
||||
static Int64 getInt64(const Iterator &) { return 0; }
|
||||
static UInt64 getUInt64(const Iterator &) { return 0; }
|
||||
static double getDouble(const Iterator &) { return 0; }
|
||||
static bool getBool(const Iterator &) { return false; }
|
||||
static StringRef getString(const Iterator &) { return {}; }
|
||||
|
||||
static size_t sizeOfArray(const Iterator &) { return 0; }
|
||||
static bool firstArrayElement(Iterator &) { return false; }
|
||||
static bool arrayElementByIndex(Iterator &, size_t) { return false; }
|
||||
static bool nextArrayElement(Iterator &) { return false; }
|
||||
|
||||
static size_t sizeOfObject(const Iterator &) { return 0; }
|
||||
static bool firstObjectMember(Iterator &) { return false; }
|
||||
static bool firstObjectMember(Iterator &, StringRef &) { return false; }
|
||||
static bool objectMemberByIndex(Iterator &, size_t) { return false; }
|
||||
static bool objectMemberByName(Iterator &, const StringRef &) { return false; }
|
||||
static bool nextObjectMember(Iterator &) { return false; }
|
||||
static bool nextObjectMember(Iterator &, StringRef &) { return false; }
|
||||
static bool isObjectMember(const Iterator &) { return false; }
|
||||
static StringRef getKey(const Iterator &) { return {}; }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -108,50 +108,12 @@ private:
|
||||
const ColumnString::Chars & chars = col_json_string->getChars();
|
||||
const ColumnString::Offsets & offsets = col_json_string->getOffsets();
|
||||
|
||||
/// Prepare list of moves.
|
||||
std::vector<Move> moves;
|
||||
constexpr size_t num_extra_arguments = Impl<JSONParser>::num_extra_arguments;
|
||||
const size_t num_moves = arguments.size() - num_extra_arguments - 1;
|
||||
moves.reserve(num_moves);
|
||||
for (const auto i : ext::range(0, num_moves))
|
||||
{
|
||||
const auto & column = block.getByPosition(arguments[i + 1]);
|
||||
if (!isString(column.type) && !isInteger(column.type))
|
||||
throw Exception{"The argument " + std::to_string(i + 2) + " of function " + String(Name::name)
|
||||
+ " should be a string specifying key or an integer specifying index, illegal type: " + column.type->getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||
|
||||
if (column.column->isColumnConst())
|
||||
{
|
||||
const auto & column_const = static_cast<const ColumnConst &>(*column.column);
|
||||
if (isString(column.type))
|
||||
moves.emplace_back(MoveType::ConstKey, column_const.getField().get<String>());
|
||||
else
|
||||
moves.emplace_back(MoveType::ConstIndex, column_const.getField().get<Int64>());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isString(column.type))
|
||||
moves.emplace_back(MoveType::Key, "");
|
||||
else
|
||||
moves.emplace_back(MoveType::Index, 0);
|
||||
}
|
||||
}
|
||||
std::vector<Move> moves = prepareListOfMoves(block, arguments);
|
||||
|
||||
/// Preallocate memory in parser if necessary.
|
||||
JSONParser parser;
|
||||
if (parser.need_preallocate)
|
||||
{
|
||||
size_t max_size = 0;
|
||||
for (const auto i : ext::range(0, input_rows_count))
|
||||
if (max_size < offsets[i] - offsets[i - 1])
|
||||
max_size = offsets[i] - offsets[i - 1];
|
||||
|
||||
if (max_size < 1)
|
||||
max_size = 1;
|
||||
|
||||
parser.preallocate(max_size);
|
||||
}
|
||||
parser.preallocate(calculateMaxSize(offsets));
|
||||
|
||||
Impl<JSONParser> impl;
|
||||
|
||||
@ -160,7 +122,8 @@ private:
|
||||
|
||||
for (const auto i : ext::range(0, input_rows_count))
|
||||
{
|
||||
bool ok = parser.parse(reinterpret_cast<const char *>(&chars[offsets[i - 1]]), offsets[i] - offsets[i - 1] - 1);
|
||||
StringRef json{reinterpret_cast<const char *>(&chars[offsets[i - 1]]), offsets[i] - offsets[i - 1] - 1};
|
||||
bool ok = parser.parse(json);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
@ -215,6 +178,7 @@ private:
|
||||
ConstKey,
|
||||
ConstIndex,
|
||||
};
|
||||
|
||||
struct Move
|
||||
{
|
||||
Move(MoveType type_, size_t index_ = 0) : type(type_), index(index_) {}
|
||||
@ -224,6 +188,39 @@ private:
|
||||
String key;
|
||||
};
|
||||
|
||||
static std::vector<Move> prepareListOfMoves(Block & block, const ColumnNumbers & arguments)
|
||||
{
|
||||
constexpr size_t num_extra_arguments = Impl<JSONParser>::num_extra_arguments;
|
||||
const size_t num_moves = arguments.size() - num_extra_arguments - 1;
|
||||
std::vector<Move> moves;
|
||||
moves.reserve(num_moves);
|
||||
for (const auto i : ext::range(0, num_moves))
|
||||
{
|
||||
const auto & column = block.getByPosition(arguments[i + 1]);
|
||||
if (!isString(column.type) && !isInteger(column.type))
|
||||
throw Exception{"The argument " + std::to_string(i + 2) + " of function " + String(Name::name)
|
||||
+ " should be a string specifying key or an integer specifying index, illegal type: " + column.type->getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||
|
||||
if (column.column->isColumnConst())
|
||||
{
|
||||
const auto & column_const = static_cast<const ColumnConst &>(*column.column);
|
||||
if (isString(column.type))
|
||||
moves.emplace_back(MoveType::ConstKey, column_const.getField().get<String>());
|
||||
else
|
||||
moves.emplace_back(MoveType::ConstIndex, column_const.getField().get<Int64>());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isString(column.type))
|
||||
moves.emplace_back(MoveType::Key, "");
|
||||
else
|
||||
moves.emplace_back(MoveType::Index, 0);
|
||||
}
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
using Iterator = typename JSONParser::Iterator;
|
||||
|
||||
/// Performs moves of types MoveType::Index and MoveType::ConstIndex.
|
||||
@ -231,51 +228,17 @@ private:
|
||||
{
|
||||
if (JSONParser::isArray(it))
|
||||
{
|
||||
if (!JSONParser::downToArray(it))
|
||||
return false;
|
||||
size_t steps;
|
||||
if (index > 0)
|
||||
{
|
||||
steps = index - 1;
|
||||
}
|
||||
return JSONParser::arrayElementByIndex(it, index - 1);
|
||||
else
|
||||
{
|
||||
size_t length = 1;
|
||||
Iterator it2 = it;
|
||||
while (JSONParser::next(it2))
|
||||
++length;
|
||||
steps = index + length;
|
||||
}
|
||||
while (steps--)
|
||||
{
|
||||
if (!JSONParser::next(it))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return JSONParser::arrayElementByIndex(it, JSONParser::sizeOfArray(it) + index);
|
||||
}
|
||||
if (JSONParser::isObject(it))
|
||||
{
|
||||
if (!JSONParser::downToObject(it))
|
||||
return false;
|
||||
size_t steps;
|
||||
if (index > 0)
|
||||
{
|
||||
steps = index - 1;
|
||||
}
|
||||
return JSONParser::objectMemberByIndex(it, index - 1);
|
||||
else
|
||||
{
|
||||
size_t length = 1;
|
||||
Iterator it2 = it;
|
||||
while (JSONParser::nextKeyValue(it2))
|
||||
++length;
|
||||
steps = index + length;
|
||||
}
|
||||
while (steps--)
|
||||
{
|
||||
if (!JSONParser::nextKeyValue(it))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return JSONParser::objectMemberByIndex(it, JSONParser::sizeOfObject(it) + index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -284,18 +247,21 @@ private:
|
||||
static bool moveIteratorToElementByKey(Iterator & it, const String & key)
|
||||
{
|
||||
if (JSONParser::isObject(it))
|
||||
{
|
||||
StringRef current_key;
|
||||
if (!JSONParser::downToObject(it, current_key))
|
||||
return false;
|
||||
do
|
||||
{
|
||||
if (current_key == key)
|
||||
return true;
|
||||
} while (JSONParser::nextKeyValue(it, current_key));
|
||||
}
|
||||
return JSONParser::objectMemberByName(it, key);
|
||||
return false;
|
||||
}
|
||||
|
||||
static size_t calculateMaxSize(const ColumnString::Offsets & offsets)
|
||||
{
|
||||
size_t max_size = 0;
|
||||
for (const auto i : ext::range(0, offsets.size()))
|
||||
if (max_size < offsets[i] - offsets[i - 1])
|
||||
max_size = offsets[i] - offsets[i - 1];
|
||||
|
||||
if (max_size < 1)
|
||||
max_size = 1;
|
||||
return max_size;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -347,27 +313,9 @@ public:
|
||||
{
|
||||
size_t size;
|
||||
if (JSONParser::isArray(it))
|
||||
{
|
||||
size = 0;
|
||||
Iterator it2 = it;
|
||||
if (JSONParser::downToArray(it2))
|
||||
{
|
||||
do
|
||||
++size;
|
||||
while (JSONParser::next(it2));
|
||||
}
|
||||
}
|
||||
size = JSONParser::sizeOfArray(it);
|
||||
else if (JSONParser::isObject(it))
|
||||
{
|
||||
size = 0;
|
||||
Iterator it2 = it;
|
||||
if (JSONParser::downToObject(it2))
|
||||
{
|
||||
do
|
||||
++size;
|
||||
while (JSONParser::nextKeyValue(it2));
|
||||
}
|
||||
}
|
||||
size = JSONParser::sizeOfObject(it);
|
||||
else
|
||||
return false;
|
||||
|
||||
@ -393,7 +341,7 @@ public:
|
||||
using Iterator = typename JSONParser::Iterator;
|
||||
static bool addValueToColumn(IColumn & dest, const Iterator & it)
|
||||
{
|
||||
if (!JSONParser::parentScopeIsObject(it))
|
||||
if (!JSONParser::isObjectMember(it))
|
||||
return false;
|
||||
StringRef key = JSONParser::getKey(it);
|
||||
ColumnString & col_str = static_cast<ColumnString &>(dest);
|
||||
@ -705,7 +653,7 @@ struct JSONExtractTree
|
||||
return false;
|
||||
|
||||
Iterator it2 = it;
|
||||
if (!JSONParser::downToArray(it2))
|
||||
if (!JSONParser::firstArrayElement(it2))
|
||||
return false;
|
||||
|
||||
ColumnArray & col_arr = static_cast<ColumnArray &>(dest);
|
||||
@ -720,7 +668,7 @@ struct JSONExtractTree
|
||||
else
|
||||
data.insertDefault();
|
||||
}
|
||||
while (JSONParser::next(it2));
|
||||
while (JSONParser::nextArrayElement(it2));
|
||||
|
||||
if (!were_valid_elements)
|
||||
{
|
||||
@ -770,7 +718,7 @@ struct JSONExtractTree
|
||||
if (JSONParser::isArray(it))
|
||||
{
|
||||
Iterator it2 = it;
|
||||
if (!JSONParser::downToArray(it2))
|
||||
if (!JSONParser::firstArrayElement(it2))
|
||||
return false;
|
||||
|
||||
size_t index = 0;
|
||||
@ -782,7 +730,7 @@ struct JSONExtractTree
|
||||
tuple.getColumn(index).insertDefault();
|
||||
++index;
|
||||
}
|
||||
while (JSONParser::next(it2));
|
||||
while (JSONParser::nextArrayElement(it2));
|
||||
|
||||
set_size(old_size + static_cast<size_t>(were_valid_elements));
|
||||
return were_valid_elements;
|
||||
@ -793,7 +741,7 @@ struct JSONExtractTree
|
||||
if (name_to_index_map.empty())
|
||||
{
|
||||
Iterator it2 = it;
|
||||
if (!JSONParser::downToObject(it2))
|
||||
if (!JSONParser::firstObjectMember(it2))
|
||||
return false;
|
||||
|
||||
size_t index = 0;
|
||||
@ -805,13 +753,13 @@ struct JSONExtractTree
|
||||
tuple.getColumn(index).insertDefault();
|
||||
++index;
|
||||
}
|
||||
while (JSONParser::nextKeyValue(it2));
|
||||
while (JSONParser::nextObjectMember(it2));
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator it2 = it;
|
||||
StringRef key;
|
||||
if (!JSONParser::downToObject(it2, key))
|
||||
if (!JSONParser::firstObjectMember(it2, key))
|
||||
return false;
|
||||
|
||||
do
|
||||
@ -823,7 +771,7 @@ struct JSONExtractTree
|
||||
were_valid_elements = true;
|
||||
}
|
||||
}
|
||||
while (JSONParser::nextKeyValue(it2, key));
|
||||
while (JSONParser::nextObjectMember(it2, key));
|
||||
}
|
||||
|
||||
set_size(old_size + static_cast<size_t>(were_valid_elements));
|
||||
@ -965,7 +913,7 @@ public:
|
||||
|
||||
StringRef key;
|
||||
Iterator it2 = it;
|
||||
if (!JSONParser::downToObject(it2, key))
|
||||
if (!JSONParser::firstObjectMember(it2, key))
|
||||
return false;
|
||||
|
||||
do
|
||||
@ -973,7 +921,7 @@ public:
|
||||
if (extract_tree->addValueToColumn(col_value, it2))
|
||||
col_key.insertData(key.data, key.size);
|
||||
}
|
||||
while (JSONParser::nextKeyValue(it2, key));
|
||||
while (JSONParser::nextObjectMember(it2, key));
|
||||
|
||||
if (col_tuple.size() == old_size)
|
||||
return false;
|
||||
@ -1047,10 +995,10 @@ private:
|
||||
{
|
||||
writeChar('[', buf);
|
||||
Iterator it2 = it;
|
||||
if (JSONParser::downToArray(it2))
|
||||
if (JSONParser::firstArrayElement(it2))
|
||||
{
|
||||
traverse(it2, buf);
|
||||
while (JSONParser::next(it2))
|
||||
while (JSONParser::nextArrayElement(it2))
|
||||
{
|
||||
writeChar(',', buf);
|
||||
traverse(it2, buf);
|
||||
@ -1064,12 +1012,12 @@ private:
|
||||
writeChar('{', buf);
|
||||
Iterator it2 = it;
|
||||
StringRef key;
|
||||
if (JSONParser::downToObject(it2, key))
|
||||
if (JSONParser::firstObjectMember(it2, key))
|
||||
{
|
||||
writeJSONString(key, buf, format_settings());
|
||||
writeChar(':', buf);
|
||||
traverse(it2, buf);
|
||||
while (JSONParser::nextKeyValue(it2, key))
|
||||
while (JSONParser::nextObjectMember(it2, key))
|
||||
{
|
||||
writeChar(',', buf);
|
||||
writeJSONString(key, buf, format_settings());
|
||||
|
@ -20,10 +20,9 @@ struct RapidJSONParser
|
||||
static constexpr bool need_preallocate = false;
|
||||
void preallocate(size_t) {}
|
||||
|
||||
bool parse(const char * data, size_t size)
|
||||
bool parse(const StringRef & json)
|
||||
{
|
||||
InputStream in(data, size);
|
||||
document.ParseStream(in);
|
||||
document.Parse(json.data);
|
||||
return !document.HasParseError();
|
||||
}
|
||||
|
||||
@ -34,98 +33,19 @@ struct RapidJSONParser
|
||||
Iterator(const rapidjson::Document & document) : value(&document) {}
|
||||
Iterator(const Iterator & src)
|
||||
: value(src.value)
|
||||
, parent_scope_is_object(src.parent_scope_is_object)
|
||||
, is_object_member(src.is_object_member)
|
||||
, current_in_array(src.current_in_array)
|
||||
, end_of_array(src.end_of_array) {}
|
||||
|
||||
Iterator & operator =(const Iterator & src)
|
||||
{
|
||||
value = src.value;
|
||||
parent_scope_is_object = src.parent_scope_is_object;
|
||||
is_object_member = src.is_object_member;
|
||||
current_in_array = src.current_in_array;
|
||||
end_of_array = src.end_of_array;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const rapidjson::Value & getValue() const { return *value; }
|
||||
|
||||
bool downToArray()
|
||||
{
|
||||
if (value->Empty())
|
||||
return false;
|
||||
current_in_array = &*value->Begin();
|
||||
end_of_array = &*value->End();
|
||||
value = current_in_array;
|
||||
++current_in_array;
|
||||
parent_scope_is_object = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool next()
|
||||
{
|
||||
if (current_in_array == end_of_array)
|
||||
return false;
|
||||
value = current_in_array;
|
||||
++current_in_array;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool downToObject()
|
||||
{
|
||||
if (value->ObjectEmpty())
|
||||
return false;
|
||||
current_in_object = &*value->MemberBegin();
|
||||
end_of_object = &*value->MemberEnd();
|
||||
value = ¤t_in_object->value;
|
||||
++current_in_object;
|
||||
parent_scope_is_object = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool downToObject(StringRef & first_key)
|
||||
{
|
||||
if (value->ObjectEmpty())
|
||||
return false;
|
||||
current_in_object = &*value->MemberBegin();
|
||||
end_of_object = &*value->MemberEnd();
|
||||
const auto & name = current_in_object->name;
|
||||
first_key.data = name.GetString();
|
||||
first_key.size = name.GetStringLength();
|
||||
value = ¤t_in_object->value;
|
||||
++current_in_object;
|
||||
parent_scope_is_object = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nextKeyValue()
|
||||
{
|
||||
if (current_in_object == end_of_object)
|
||||
return false;
|
||||
value = ¤t_in_object->value;
|
||||
++current_in_object;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nextKeyValue(StringRef & key)
|
||||
{
|
||||
if (current_in_object == end_of_object)
|
||||
return false;
|
||||
const auto & name = current_in_object->name;
|
||||
key.data = name.GetString();
|
||||
key.size = name.GetStringLength();
|
||||
value = ¤t_in_object->value;
|
||||
++current_in_object;
|
||||
return true;
|
||||
}
|
||||
|
||||
StringRef getKey() const
|
||||
{
|
||||
const auto & name = (current_in_object - 1)->name;
|
||||
return {name.GetString(), name.GetStringLength()};
|
||||
}
|
||||
|
||||
bool parentScopeIsObject() const { return parent_scope_is_object; }
|
||||
|
||||
bool isInt64() const { return value->IsInt64(); }
|
||||
bool isUInt64() const { return value->IsUint64(); }
|
||||
bool isDouble() const { return value->IsDouble(); }
|
||||
@ -141,9 +61,103 @@ struct RapidJSONParser
|
||||
bool getBool() const { return value->GetBool(); }
|
||||
StringRef getString() const { return {value->GetString(), value->GetStringLength()}; }
|
||||
|
||||
size_t sizeOfArray() const { return value->Size(); }
|
||||
|
||||
bool arrayElementByIndex(size_t index)
|
||||
{
|
||||
if (index >= value->Size())
|
||||
return false;
|
||||
setRange(value->Begin() + index, value->End());
|
||||
value = current_in_array++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nextArrayElement()
|
||||
{
|
||||
if (current_in_array == end_of_array)
|
||||
return false;
|
||||
value = current_in_array++;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t sizeOfObject() const { return value->MemberCount(); }
|
||||
|
||||
bool objectMemberByIndex(size_t index)
|
||||
{
|
||||
if (index >= value->MemberCount())
|
||||
return false;
|
||||
setRange(value->MemberBegin() + index, value->MemberEnd());
|
||||
value = &(current_in_object++)->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool objectMemberByIndex(size_t index, StringRef & key)
|
||||
{
|
||||
if (index >= value->MemberCount())
|
||||
return false;
|
||||
setRange(value->MemberBegin() + index, value->MemberEnd());
|
||||
key = getKeyImpl(current_in_object);
|
||||
value = &(current_in_object++)->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool objectMemberByName(const StringRef & name)
|
||||
{
|
||||
auto it = value->FindMember(name.data);
|
||||
if (it == value->MemberEnd())
|
||||
return false;
|
||||
setRange(it, value->MemberEnd());
|
||||
value = &(current_in_object++)->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nextObjectMember()
|
||||
{
|
||||
if (current_in_object == end_of_object)
|
||||
return false;
|
||||
value = &(current_in_object++)->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nextObjectMember(StringRef & key)
|
||||
{
|
||||
if (current_in_object == end_of_object)
|
||||
return false;
|
||||
key = getKeyImpl(current_in_object);
|
||||
value = &(current_in_object++)->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isObjectMember() const { return is_object_member; }
|
||||
|
||||
StringRef getKey() const
|
||||
{
|
||||
return getKeyImpl(current_in_object - 1);
|
||||
}
|
||||
|
||||
private:
|
||||
void setRange(rapidjson::Value::ConstValueIterator current, rapidjson::Value::ConstValueIterator end)
|
||||
{
|
||||
current_in_array = &*current;
|
||||
end_of_array = &*end;
|
||||
is_object_member = false;
|
||||
}
|
||||
|
||||
void setRange(rapidjson::Value::ConstMemberIterator current, rapidjson::Value::ConstMemberIterator end)
|
||||
{
|
||||
current_in_object = &*current;
|
||||
end_of_object = &*end;
|
||||
is_object_member = true;
|
||||
}
|
||||
|
||||
static StringRef getKeyImpl(const rapidjson::GenericMember<rapidjson::UTF8<>, rapidjson::MemoryPoolAllocator<>> * member)
|
||||
{
|
||||
const auto & name = member->name;
|
||||
return {name.GetString(), name.GetStringLength()};
|
||||
}
|
||||
|
||||
const rapidjson::Value * value = nullptr;
|
||||
bool parent_scope_is_object = false;
|
||||
bool is_object_member = false;
|
||||
|
||||
union
|
||||
{
|
||||
@ -159,50 +173,37 @@ struct RapidJSONParser
|
||||
|
||||
Iterator getRoot() { return Iterator{document}; }
|
||||
|
||||
static bool downToArray(Iterator & it) { return it.downToArray(); }
|
||||
static bool downToObject(Iterator & it) { return it.downToObject(); }
|
||||
static bool downToObject(Iterator & it, StringRef & first_key) { return it.downToObject(first_key); }
|
||||
static bool parentScopeIsObject(const Iterator & it) { return it.parentScopeIsObject(); }
|
||||
static bool next(Iterator & it) { return it.next(); }
|
||||
static bool nextKeyValue(Iterator & it) { return it.nextKeyValue(); }
|
||||
static bool nextKeyValue(Iterator & it, StringRef & key) { return it.nextKeyValue(key); }
|
||||
static bool isInt64(const Iterator & it) { return it.isInt64(); }
|
||||
static bool isUInt64(const Iterator & it) { return it.isUInt64(); }
|
||||
static bool isDouble(const Iterator & it) { return it.isDouble(); }
|
||||
static bool isBool(const Iterator & it) { return it.isBool(); }
|
||||
static bool isString(const Iterator & it) { return it.isString(); }
|
||||
static bool isArray(const Iterator & it) { return it.isArray(); }
|
||||
static bool isObject(const Iterator & it) { return it.isObject(); }
|
||||
static bool isBool(const Iterator & it) { return it.isBool(); }
|
||||
static bool isNull(const Iterator & it) { return it.isNull(); }
|
||||
static StringRef getKey(const Iterator & it) { return it.getKey(); }
|
||||
static StringRef getString(const Iterator & it) { return it.getString(); }
|
||||
|
||||
static Int64 getInt64(const Iterator & it) { return it.getInt64(); }
|
||||
static UInt64 getUInt64(const Iterator & it) { return it.getUInt64(); }
|
||||
static double getDouble(const Iterator & it) { return it.getDouble(); }
|
||||
static bool getBool(const Iterator & it) { return it.getBool(); }
|
||||
static StringRef getString(const Iterator & it) { return it.getString(); }
|
||||
|
||||
static size_t sizeOfArray(const Iterator & it) { return it.sizeOfArray(); }
|
||||
static bool firstArrayElement(Iterator & it) { return it.arrayElementByIndex(0); }
|
||||
static bool arrayElementByIndex(Iterator & it, size_t index) { return it.arrayElementByIndex(index); }
|
||||
static bool nextArrayElement(Iterator & it) { return it.nextArrayElement(); }
|
||||
|
||||
static size_t sizeOfObject(const Iterator & it) { return it.sizeOfObject(); }
|
||||
static bool firstObjectMember(Iterator & it) { return it.objectMemberByIndex(0); }
|
||||
static bool firstObjectMember(Iterator & it, StringRef & first_key) { return it.objectMemberByIndex(0, first_key); }
|
||||
static bool objectMemberByIndex(Iterator & it, size_t index) { return it.objectMemberByIndex(index); }
|
||||
static bool objectMemberByName(Iterator & it, const StringRef & name) { return it.objectMemberByName(name); }
|
||||
static bool nextObjectMember(Iterator & it) { return it.nextObjectMember(); }
|
||||
static bool nextObjectMember(Iterator & it, StringRef & next_key) { return it.nextObjectMember(next_key); }
|
||||
static bool isObjectMember(const Iterator & it) { return it.isObjectMember(); }
|
||||
static StringRef getKey(const Iterator & it) { return it.getKey(); }
|
||||
|
||||
private:
|
||||
class InputStream
|
||||
{
|
||||
public:
|
||||
InputStream(const char * data, size_t size) : begin(data), end(data + size), current(data) {}
|
||||
|
||||
using Ch = char;
|
||||
Ch Peek() { if (current == end) return 0; return *current; }
|
||||
Ch Take() { if (current == end) return 0; return *current++; }
|
||||
size_t Tell() const { return current - begin; }
|
||||
|
||||
Ch* PutBegin() { return nullptr; }
|
||||
void Put(Ch) {}
|
||||
void Flush() {}
|
||||
size_t PutEnd(Ch*) { return 0; }
|
||||
|
||||
private:
|
||||
const char * begin;
|
||||
const char * end;
|
||||
const char * current;
|
||||
};
|
||||
|
||||
rapidjson::Document document;
|
||||
};
|
||||
|
||||
|
@ -40,46 +40,11 @@ struct SimdJSONParser
|
||||
ErrorCodes::CANNOT_ALLOCATE_MEMORY};
|
||||
}
|
||||
|
||||
bool parse(const char * data, size_t size) { return !json_parse(data, size, pj); }
|
||||
bool parse(const StringRef & json) { return !json_parse(json.data, json.size, pj); }
|
||||
|
||||
using Iterator = ParsedJson::iterator;
|
||||
Iterator getRoot() { return Iterator{pj}; }
|
||||
|
||||
static bool downToArray(Iterator & it) { return it.down(); }
|
||||
|
||||
static bool downToObject(Iterator & it) { return it.down() && it.next(); }
|
||||
|
||||
static bool downToObject(Iterator & it, StringRef & first_key)
|
||||
{
|
||||
if (!it.down())
|
||||
return false;
|
||||
first_key.data = it.get_string();
|
||||
first_key.size = it.get_string_length();
|
||||
return it.next();
|
||||
}
|
||||
|
||||
static bool parentScopeIsObject(const Iterator & it) { return it.get_scope_type() == '{'; }
|
||||
|
||||
static bool next(Iterator & it) { return it.next(); }
|
||||
|
||||
static bool nextKeyValue(Iterator & it) { return it.next() && it.next(); }
|
||||
|
||||
static bool nextKeyValue(Iterator & it, StringRef & key)
|
||||
{
|
||||
if (!it.next())
|
||||
return false;
|
||||
key.data = it.get_string();
|
||||
key.size = it.get_string_length();
|
||||
return it.next();
|
||||
}
|
||||
|
||||
static StringRef getKey(const Iterator & it)
|
||||
{
|
||||
Iterator it2 = it;
|
||||
it2.prev();
|
||||
return StringRef{it2.get_string(), it2.get_string_length()};
|
||||
}
|
||||
|
||||
static bool isInt64(const Iterator & it) { return it.is_integer(); }
|
||||
static bool isUInt64(const Iterator &) { return false; /* See https://github.com/lemire/simdjson/issues/68 */ }
|
||||
static bool isDouble(const Iterator & it) { return it.is_double(); }
|
||||
@ -87,13 +52,95 @@ struct SimdJSONParser
|
||||
static bool isArray(const Iterator & it) { return it.is_array(); }
|
||||
static bool isObject(const Iterator & it) { return it.is_object(); }
|
||||
static bool isBool(const Iterator & it) { return it.get_type() == 't' || it.get_type() == 'f'; }
|
||||
static bool isNull(const Iterator & it) { return it.get_type() == 'n'; }
|
||||
static bool isNull(const Iterator & it) { return it.is_null(); }
|
||||
|
||||
static StringRef getString(const Iterator & it) { return StringRef{it.get_string(), it.get_string_length()}; }
|
||||
static Int64 getInt64(const Iterator & it) { return it.get_integer(); }
|
||||
static UInt64 getUInt64(const Iterator &) { return 0; /* isUInt64() never returns true */ }
|
||||
static double getDouble(const Iterator & it) { return it.get_double(); }
|
||||
static bool getBool(const Iterator & it) { return it.get_type() == 't'; }
|
||||
static StringRef getString(const Iterator & it) { return StringRef{it.get_string(), it.get_string_length()}; }
|
||||
|
||||
static size_t sizeOfArray(const Iterator & it)
|
||||
{
|
||||
size_t size = 0;
|
||||
Iterator it2 = it;
|
||||
if (it2.down())
|
||||
{
|
||||
do
|
||||
++size;
|
||||
while (it2.next());
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static bool firstArrayElement(Iterator & it) { return it.down(); }
|
||||
|
||||
static bool arrayElementByIndex(Iterator & it, size_t index)
|
||||
{
|
||||
if (!it.down())
|
||||
return false;
|
||||
while (index--)
|
||||
if (!it.next())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool nextArrayElement(Iterator & it) { return it.next(); }
|
||||
|
||||
static size_t sizeOfObject(const Iterator & it)
|
||||
{
|
||||
size_t size = 0;
|
||||
Iterator it2 = it;
|
||||
if (it2.down())
|
||||
{
|
||||
do
|
||||
++size;
|
||||
while (it2.next() && it2.next());
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static bool firstObjectMember(Iterator & it) { return it.down() && it.next(); }
|
||||
|
||||
static bool firstObjectMember(Iterator & it, StringRef & first_key)
|
||||
{
|
||||
if (!it.down())
|
||||
return false;
|
||||
first_key.data = it.get_string();
|
||||
first_key.size = it.get_string_length();
|
||||
return it.next();
|
||||
}
|
||||
|
||||
static bool objectMemberByIndex(Iterator & it, size_t index)
|
||||
{
|
||||
if (!it.down())
|
||||
return false;
|
||||
while (index--)
|
||||
if (!it.next() || !it.next())
|
||||
return false;
|
||||
return it.next();
|
||||
}
|
||||
|
||||
static bool objectMemberByName(Iterator & it, const StringRef & name) { return it.move_to_key(name.data); }
|
||||
static bool nextObjectMember(Iterator & it) { return it.next() && it.next(); }
|
||||
|
||||
static bool nextObjectMember(Iterator & it, StringRef & next_key)
|
||||
{
|
||||
if (!it.next())
|
||||
return false;
|
||||
next_key.data = it.get_string();
|
||||
next_key.size = it.get_string_length();
|
||||
return it.next();
|
||||
}
|
||||
|
||||
static bool isObjectMember(const Iterator & it) { return it.get_scope_type() == '{'; }
|
||||
|
||||
static StringRef getKey(const Iterator & it)
|
||||
{
|
||||
Iterator it2 = it;
|
||||
it2.prev();
|
||||
return StringRef{it2.get_string(), it2.get_string_length()};
|
||||
}
|
||||
|
||||
private:
|
||||
ParsedJson pj;
|
||||
|
Loading…
Reference in New Issue
Block a user