ClickHouse/src/Functions/RapidJSONParser.h
Konstantin Rudenskii 8199b45e95 Fix style
Fifth try v2.0

Fifth try v2.1

Fifth try v2.2

Fifth try v2.3

Fifth try v2.4

Fifth try v2.5

Fifth try v2.6

Fifth try v2.7

Fifth try v2.8

Fifth try v2.9

Fifth try v2.10

Fifth try v2.11

Fifth try v2.12

Fifth try v2.13

Fifth try v2.14

Fifth try v2.15

Fifth try v2.16

Fifth try v2.17

Fifth try v2.18

Fifth try v2.19

Fifth try v2.20

Fifth try v2.21

Fifth try v2.22

Fifth try v2.23

Fifth try v2.24

Fifth try v2.25

Fifth try v2.26

Fifth try v2.27

Fifth try v2.28

Add ranges

Add ranges try v1.1

Add ranges try v1.2

Add ranges try v1.3

Add ranges try v1.4

Add ranges try v1.5

Add ranges try v1.6

Add ranges try v1.7

Add ranges try v1.8

Add ranges try v1.9

Add ranges try v1.10

Add ranges try v1.11

Add ranges try v1.12

Add ranges try v1.13

Add ranges try v1.14

Add ranges try v1.15

Add ranges try v1.16

Add ranges try v1.17

Add ranges try v1.18

Add ranges try v1.19

Add ranges try v1.20

Add ranges try v1.21

Add ranges try v1.22

Add ranges try v1.23

Add ranges try v1.24

Add ranges try v1.25

Add ranges try v1.26

Add ranges try v1.27

Add ranges try v1.28

Add ranges try v1.29

Add ranges try v1.30

Add ranges try v1.31

Add ranges try v1.32

Add ranges try v1.33

Add ranges try v1.34

Add ranges try v1.35

Add ranges try v1.36

Add ranges try v1.37

Add ranges try v1.38

Add ranges try v1.39

Add ranges try v1.40

Add ranges try v1.41

Add ranges try v1.42

Add ranges try v1.43

Add ranges try v1.44

Add ranges try v1.45

Add ranges try v1.46

Add ranges try v1.47

Leftover comment

Try wildcard

Try wildcard v1.1

Try wildcard v1.2

Try wildcard v1.3

New functions

New functions 1.1

New functions 1.2

New functions 1.3

New functions 1.4

New functions 1.5

New functions 1.6

New functions 1.7

New functions 1.8

New functions 1.9

New functions 1.10

New functions 1.11

New functions 1.12

New functions 1.13

New functions 1.14

New functions 1.15

New functions 1.16

Final steps

Final steps v1.1

Final steps v1.2
2021-05-29 15:30:53 +03:00

159 lines
5.8 KiB
C++

#pragma once
#if !defined(ARCADIA_BUILD)
# include "config_functions.h"
#endif
#if USE_RAPIDJSON
# include <common/types.h>
# include <common/defines.h>
# include <rapidjson/document.h>
namespace DB
{
/// This class can be used as an argument for the template class FunctionJSON.
/// It provides ability to parse JSONs using rapidjson library.
struct RapidJSONParser
{
class Array;
class Object;
/// References an element in a JSON document, representing a JSON null, boolean, string, number,
/// array or object.
class Element
{
public:
ALWAYS_INLINE Element() {}
ALWAYS_INLINE Element(const rapidjson::Value & value_) : ptr(&value_) {}
ALWAYS_INLINE bool isInt64() const { return ptr->IsInt64(); }
ALWAYS_INLINE bool isUInt64() const { return ptr->IsUint64(); }
ALWAYS_INLINE bool isDouble() const { return ptr->IsDouble(); }
ALWAYS_INLINE bool isString() const { return ptr->IsString(); }
ALWAYS_INLINE bool isArray() const { return ptr->IsArray(); }
ALWAYS_INLINE bool isObject() const { return ptr->IsObject(); }
ALWAYS_INLINE bool isBool() const { return ptr->IsBool(); }
ALWAYS_INLINE bool isNull() const { return ptr->IsNull(); }
ALWAYS_INLINE Int64 getInt64() const { return ptr->GetInt64(); }
ALWAYS_INLINE UInt64 getUInt64() const { return ptr->GetUint64(); }
ALWAYS_INLINE double getDouble() const { return ptr->GetDouble(); }
ALWAYS_INLINE bool getBool() const { return ptr->GetBool(); }
ALWAYS_INLINE std::string_view getString() const { return {ptr->GetString(), ptr->GetStringLength()}; }
Array getArray() const;
Object getObject() const;
private:
const rapidjson::Value * ptr = nullptr;
};
/// References an array in a JSON document.
class Array
{
public:
class Iterator
{
public:
ALWAYS_INLINE Iterator(const rapidjson::Value::ConstValueIterator & it_) : it(it_) {}
ALWAYS_INLINE Element operator*() const { return *it; }
ALWAYS_INLINE Iterator & operator ++() { ++it; return *this; }
ALWAYS_INLINE Iterator operator ++(int) { auto res = *this; ++it; return res; }
ALWAYS_INLINE friend bool operator ==(const Iterator & left, const Iterator & right) { return left.it == right.it; }
ALWAYS_INLINE friend bool operator !=(const Iterator & left, const Iterator & right) { return !(left == right); }
private:
rapidjson::Value::ConstValueIterator it;
};
ALWAYS_INLINE Array(const rapidjson::Value & value_) : ptr(&value_) {}
ALWAYS_INLINE Iterator begin() const { return ptr->Begin(); }
ALWAYS_INLINE Iterator end() const { return ptr->End(); }
ALWAYS_INLINE size_t size() const { return ptr->Size(); }
ALWAYS_INLINE Element operator[](size_t index) const { assert(index < size()); return *(ptr->Begin() + index); }
private:
const rapidjson::Value * ptr = nullptr;
};
using KeyValuePair = std::pair<std::string_view, Element>;
/// References an object in a JSON document.
class Object
{
public:
class Iterator
{
public:
ALWAYS_INLINE Iterator(const rapidjson::Value::ConstMemberIterator & it_) : it(it_) {}
ALWAYS_INLINE KeyValuePair operator *() const { std::string_view key{it->name.GetString(), it->name.GetStringLength()}; return {key, it->value}; }
ALWAYS_INLINE Iterator & operator ++() { ++it; return *this; }
ALWAYS_INLINE Iterator operator ++(int) { auto res = *this; ++it; return res; }
ALWAYS_INLINE friend bool operator ==(const Iterator & left, const Iterator & right) { return left.it == right.it; }
ALWAYS_INLINE friend bool operator !=(const Iterator & left, const Iterator & right) { return !(left == right); }
private:
rapidjson::Value::ConstMemberIterator it;
};
ALWAYS_INLINE Object(const rapidjson::Value & value_) : ptr(&value_) {}
ALWAYS_INLINE Iterator begin() const { return ptr->MemberBegin(); }
ALWAYS_INLINE Iterator end() const { return ptr->MemberEnd(); }
ALWAYS_INLINE size_t size() const { return ptr->MemberCount(); }
bool find(const std::string_view & key, Element & result) const
{
auto it = ptr->FindMember(rapidjson::StringRef(key.data(), key.length()));
if (it == ptr->MemberEnd())
return false;
result = it->value;
return true;
}
/// Optional: Provides access to an object's element by index.
ALWAYS_INLINE KeyValuePair operator[](size_t index) const
{
assert (index < size());
auto it = ptr->MemberBegin() + index;
std::string_view key{it->name.GetString(), it->name.GetStringLength()};
return {key, it->value};
}
private:
const rapidjson::Value * ptr = nullptr;
};
/// Parses a JSON document, returns the reference to its root element if succeeded.
bool parse(const std::string_view & json, Element & result)
{
rapidjson::MemoryStream ms(json.data(), json.size());
rapidjson::EncodedInputStream<rapidjson::UTF8<>, rapidjson::MemoryStream> is(ms);
document.ParseStream(is);
if (document.HasParseError() || (ms.Tell() != json.size()))
return false;
result = document;
return true;
}
#if 0
/// Optional: Allocates memory to parse JSON documents faster.
void reserve(size_t max_size);
#endif
private:
rapidjson::Document document;
};
inline ALWAYS_INLINE RapidJSONParser::Array RapidJSONParser::Element::getArray() const
{
return *ptr;
}
inline ALWAYS_INLINE RapidJSONParser::Object RapidJSONParser::Element::getObject() const
{
return *ptr;
}
}
#endif