aboutsummaryrefslogtreecommitdiff
path: root/source/Common/RapidJsonHelper.hpp
blob: 75cd93ad8535daf579a9b015a39ac1d31c4af12e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#pragma once

#include <rapidjson/document.h>
#include <cstring>
#include <string>
#include <string_view>

#define BRUSSEL_JSON_GET(object, name, type, out, failAction) \
	{                                                         \
		auto it = (object).FindMember(name);                  \
		if (it == (object).MemberEnd()) failAction;           \
		auto& value = it->value;                              \
		if (!value.Is<type>()) failAction;                    \
		(out) = value.Get<type>();                            \
	}

#define BRUSSEL_JSON_GET_DEFAULT(object, name, type, out, theDefault) \
	do {                                                              \
		auto it = (object).FindMember(name);                          \
		if (it == (object).MemberEnd()) {                             \
			(out) = theDefault;                                       \
			break;                                                    \
		}                                                             \
		auto& value = it->value;                                      \
		if (!value.Is<type>()) {                                      \
			(out) = theDefault;                                       \
			break;                                                    \
		}                                                             \
		(out) = value.Get<type>();                                    \
	} while (0);

namespace rapidjson {

inline const Value* GetProperty(const Value& value, std::string_view name) {
	for (auto it = value.MemberBegin(); it != value.MemberEnd(); ++it) {
		if (it->name.GetStringLength() != name.size()) continue;
		if (std::memcmp(it->name.GetString(), name.data(), name.size())) continue;

		return &it->value;
	}
	return nullptr;
}

inline const Value* GetProperty(const Value& value, Type type, std::string_view name) {
	for (auto it = value.MemberBegin(); it != value.MemberEnd(); ++it) {
		if (it->name.GetStringLength() != name.size()) continue;
		if (it->value.GetType() != type) continue;
		if (std::memcmp(it->name.GetString(), name.data(), name.size())) continue;

		return &it->value;
	}
	return nullptr;
}

inline std::string_view AsStringView(const Value& value) {
	return std::string_view(value.GetString(), value.GetStringLength());
}

inline std::string_view AsStringView(const GenericStringRef<char>& strRef) {
	return std::string_view(strRef.s, strRef.length);
}

inline std::string AsString(const Value& value) {
	return std::string(value.GetString(), value.GetStringLength());
}

inline std::string AsString(const GenericStringRef<char>& strRef) {
	return std::string(strRef.s, strRef.length);
}

// RapidJson itself already provides std::string and const char* overloads
inline GenericStringRef<char> StringRef(std::string_view str) {
	return GenericStringRef<char>(
		str.data() ? str.data() : "",
		str.size());
}

template <class TIter, class TSentienl>
rapidjson::Value WriteVectorPrimitives(rapidjson::Document& root, TIter begin, TSentienl end) {
	using TElement = typename TIter::value_type;

	rapidjson::Value list;
	while (begin != end) {
		if constexpr (std::is_same_v<TElement, std::string>) {
			auto& elm = *begin;
			list.PushBack(rapidjson::Value(elm.c_str(), elm.size()), root.GetAllocator());
		} else {
			list.PushBack(*begin, root.GetAllocator());
		}
		++begin;
	}
	return list;
}

template <class TContainer>
bool ReadVectorPrimitives(const rapidjson::Value& value, TContainer& list) {
	using TElement = typename TContainer::value_type;

	if (!value.IsArray()) return false;

	list.reserve(value.Size());
	for (auto& elm : value.GetArray()) {
		if (!elm.Is<TElement>()) return {};
		list.push_back(elm.Get<TElement>());
	}

	return true;
}

} // namespace rapidjson