• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef API_UTIL_JSONUTIL_H
17 #define API_UTIL_JSONUTIL_H
18 
19 #include <cstdlib>
20 #include <type_traits>
21 
22 #include <base/containers/string.h>
23 #include <base/containers/string_view.h>
24 #include <base/math/vector.h>
25 #include <base/math/quaternion.h>
26 #include <base/util/uid_util.h>
27 
28 #include <core/json/json.h>
29 
30 #include <util/namespace.h>
31 
UTIL_BEGIN_NAMESPACE()32 UTIL_BEGIN_NAMESPACE()
33 
34 inline BASE_NS::string JsonUnescape(BASE_NS::string_view str)
35 {
36     return CORE_NS::json::unescape(str);
37 }
38 
39 template<class T, std::enable_if_t<std::is_arithmetic_v<T>, bool> = true>
SafeGetJsonValue(const CORE_NS::json::value & jsonData,const BASE_NS::string_view element,BASE_NS::string & error,T & output)40 inline bool SafeGetJsonValue(
41     const CORE_NS::json::value& jsonData, const BASE_NS::string_view element, BASE_NS::string& error, T& output)
42 {
43     if (auto const pos = jsonData.find(element); pos) {
44         if (pos->is_number()) {
45             output = pos->as_number<T>();
46             return true;
47         } else if (pos->is_boolean()) {
48             output = pos->boolean_;
49             return true;
50         } else {
51             error += element + ": expected number.\n";
52         }
53     }
54     return false;
55 }
56 
57 template<class T, std::enable_if_t<std::is_convertible_v<T, BASE_NS::string_view>, bool> = true>
SafeGetJsonValue(const CORE_NS::json::value & jsonData,const BASE_NS::string_view element,BASE_NS::string & error,T & output)58 inline bool SafeGetJsonValue(
59     const CORE_NS::json::value& jsonData, const BASE_NS::string_view element, BASE_NS::string& error, T& output)
60 {
61     if (auto const pos = jsonData.find(element); pos) {
62         if (pos->is_string()) {
63             output = JsonUnescape(T(pos->string_.data(), pos->string_.size()));
64             return true;
65         } else {
66             error += element + ": expected string.\n";
67         }
68     }
69     return false;
70 }
71 
72 template<class T, std::enable_if_t<std::is_arithmetic_v<T>, bool> = true>
FromJson(const CORE_NS::json::value & jsonIn,T & output)73 inline bool FromJson(const CORE_NS::json::value& jsonIn, T& output)
74 {
75     if (jsonIn.is_number()) {
76         output = jsonIn.as_number<T>();
77         return true;
78     }
79     return false;
80 }
81 
82 template<class T, std::enable_if_t<std::is_convertible_v<T, BASE_NS::string_view>, bool> = true>
FromJson(const CORE_NS::json::value & jsonIn,T & output)83 inline bool FromJson(const CORE_NS::json::value& jsonIn, T& output)
84 {
85     if (jsonIn.is_string()) {
86         output = JsonUnescape(static_cast<T>(jsonIn.string_));
87         return true;
88     }
89     return false;
90 }
91 
FromJson(const CORE_NS::json::value & jsonIn,bool & output)92 inline bool FromJson(const CORE_NS::json::value& jsonIn, bool& output)
93 {
94     if (jsonIn.is_boolean()) {
95         output = jsonIn.boolean_;
96         return true;
97     }
98     return false;
99 }
100 
FromJson(const CORE_NS::json::value & jsonIn,BASE_NS::Uid & output)101 inline bool FromJson(const CORE_NS::json::value& jsonIn, BASE_NS::Uid& output)
102 {
103     constexpr size_t UID_LENGTH = 36; // 36:uid length
104     if (jsonIn.is_string() && jsonIn.string_.size() == UID_LENGTH) {
105         output = StringToUid(JsonUnescape(jsonIn.string_));
106         return true;
107     }
108     return false;
109 }
110 
111 template<class T>
FromJsonArray(const CORE_NS::json::value & jsonIn,T * output,size_t size)112 inline bool FromJsonArray(const CORE_NS::json::value& jsonIn, T* output, size_t size)
113 {
114     if (jsonIn.is_array() && jsonIn.array_.size() == size) {
115         for (const auto& element : jsonIn.array_) {
116             if (!FromJson(element, *output)) {
117                 return false;
118             }
119             output++;
120         }
121         return true;
122     }
123     return false;
124 }
125 
FromJson(const CORE_NS::json::value & jsonIn,BASE_NS::Math::Vec2 & output)126 inline bool FromJson(const CORE_NS::json::value& jsonIn, BASE_NS::Math::Vec2& output)
127 {
128     return FromJsonArray(jsonIn, output.data, 2); // 2 : param
129 }
130 
FromJson(const CORE_NS::json::value & jsonIn,BASE_NS::Math::Vec3 & output)131 inline bool FromJson(const CORE_NS::json::value& jsonIn, BASE_NS::Math::Vec3& output)
132 {
133     return FromJsonArray(jsonIn, output.data, 3); // 3 : param
134 }
135 
FromJson(const CORE_NS::json::value & jsonIn,BASE_NS::Math::Vec4 & output)136 inline bool FromJson(const CORE_NS::json::value& jsonIn, BASE_NS::Math::Vec4& output)
137 {
138     return FromJsonArray(jsonIn, output.data, 4); // 4 : size
139 }
140 
FromJson(const CORE_NS::json::value & jsonIn,BASE_NS::Math::UVec2 & output)141 inline bool FromJson(const CORE_NS::json::value& jsonIn, BASE_NS::Math::UVec2& output)
142 {
143     return FromJsonArray(jsonIn, output.data, 2); // 2 : size
144 }
145 
FromJson(const CORE_NS::json::value & jsonIn,BASE_NS::Math::UVec3 & output)146 inline bool FromJson(const CORE_NS::json::value& jsonIn, BASE_NS::Math::UVec3& output)
147 {
148     return FromJsonArray(jsonIn, output.data, 3); // 3 :size
149 }
150 
FromJson(const CORE_NS::json::value & jsonIn,BASE_NS::Math::UVec4 & output)151 inline bool FromJson(const CORE_NS::json::value& jsonIn, BASE_NS::Math::UVec4& output)
152 {
153     return FromJsonArray(jsonIn, output.data, 4); // 4 : size
154 }
155 
FromJson(const CORE_NS::json::value & jsonIn,BASE_NS::Math::Quat & output)156 inline bool FromJson(const CORE_NS::json::value& jsonIn, BASE_NS::Math::Quat& output)
157 {
158     return FromJsonArray(jsonIn, output.data, 4); // 4 : size
159 }
160 
161 template<class T>
ToJson(T value)162 inline CORE_NS::json::standalone_value ToJson(T value)
163 {
164     return CORE_NS::json::standalone_value(value);
165 }
166 
167 // how to make more generic?, Does not understand fixed_string
168 template<>
ToJson(BASE_NS::string_view value)169 inline CORE_NS::json::standalone_value ToJson(BASE_NS::string_view value)
170 {
171     return CORE_NS::json::standalone_value(BASE_NS::string{ value });
172 }
173 
174 template<>
ToJson(BASE_NS::string value)175 inline CORE_NS::json::standalone_value ToJson(BASE_NS::string value)
176 {
177     return CORE_NS::json::standalone_value(value);
178 }
179 
180 template<>
181 inline CORE_NS::json::standalone_value ToJson<BASE_NS::Math::Vec2>(BASE_NS::Math::Vec2 value)
182 {
183     CORE_NS::json::standalone_value json = CORE_NS::json::standalone_value::array();
184     json.array_.reserve(2); // 2 : param
185     json.array_.emplace_back(CORE_NS::json::standalone_value(value.x));
186     json.array_.emplace_back(CORE_NS::json::standalone_value(value.y));
187     return json;
188 }
189 template<>
190 inline CORE_NS::json::standalone_value ToJson<BASE_NS::Math::UVec2>(BASE_NS::Math::UVec2 value)
191 {
192     CORE_NS::json::standalone_value json = CORE_NS::json::standalone_value::array();
193     json.array_.reserve(2); // 2 : param
194     json.array_.emplace_back(CORE_NS::json::standalone_value(value.x));
195     json.array_.emplace_back(CORE_NS::json::standalone_value(value.y));
196     return json;
197 }
198 
199 template<>
200 inline CORE_NS::json::standalone_value ToJson<BASE_NS::Math::Vec3>(BASE_NS::Math::Vec3 value)
201 {
202     CORE_NS::json::standalone_value json = CORE_NS::json::standalone_value::array();
203     json.array_.reserve(3); // 3 : size
204     json.array_.emplace_back(CORE_NS::json::standalone_value(value.x));
205     json.array_.emplace_back(CORE_NS::json::standalone_value(value.y));
206     json.array_.emplace_back(CORE_NS::json::standalone_value(value.z));
207     return json;
208 }
209 template<>
210 inline CORE_NS::json::standalone_value ToJson<BASE_NS::Math::UVec3>(BASE_NS::Math::UVec3 value)
211 {
212     CORE_NS::json::standalone_value json = CORE_NS::json::standalone_value::array();
213     json.array_.reserve(3); // 3 : size
214     json.array_.emplace_back(CORE_NS::json::standalone_value(value.x));
215     json.array_.emplace_back(CORE_NS::json::standalone_value(value.y));
216     json.array_.emplace_back(CORE_NS::json::standalone_value(value.z));
217     return json;
218 }
219 
220 template<>
221 inline CORE_NS::json::standalone_value ToJson<BASE_NS::Math::Vec4>(BASE_NS::Math::Vec4 value)
222 {
223     CORE_NS::json::standalone_value json = CORE_NS::json::standalone_value::array();
224     json.array_.reserve(4); // 4 :size
225     json.array_.emplace_back(CORE_NS::json::standalone_value(value.x));
226     json.array_.emplace_back(CORE_NS::json::standalone_value(value.y));
227     json.array_.emplace_back(CORE_NS::json::standalone_value(value.z));
228     json.array_.emplace_back(CORE_NS::json::standalone_value(value.w));
229     return json;
230 }
231 template<>
232 inline CORE_NS::json::standalone_value ToJson<BASE_NS::Math::UVec4>(BASE_NS::Math::UVec4 value)
233 {
234     CORE_NS::json::standalone_value json = CORE_NS::json::standalone_value::array();
235     json.array_.reserve(4); // 4 : size
236     json.array_.emplace_back(CORE_NS::json::standalone_value(value.x));
237     json.array_.emplace_back(CORE_NS::json::standalone_value(value.y));
238     json.array_.emplace_back(CORE_NS::json::standalone_value(value.z));
239     json.array_.emplace_back(CORE_NS::json::standalone_value(value.w));
240     return json;
241 }
242 
243 template<>
244 inline CORE_NS::json::standalone_value ToJson<BASE_NS::Math::Quat>(BASE_NS::Math::Quat value)
245 {
246     CORE_NS::json::standalone_value json = CORE_NS::json::standalone_value::array();
247     json.array_.reserve(4); // 4 : size
248     json.array_.emplace_back(CORE_NS::json::standalone_value(value.x));
249     json.array_.emplace_back(CORE_NS::json::standalone_value(value.y));
250     json.array_.emplace_back(CORE_NS::json::standalone_value(value.z));
251     json.array_.emplace_back(CORE_NS::json::standalone_value(value.w));
252     return json;
253 }
254 
255 template<>
256 inline CORE_NS::json::standalone_value ToJson<BASE_NS::Uid>(BASE_NS::Uid value)
257 {
258     return ToJson(BASE_NS::string_view{ to_string(value) });
259 }
260 
261 UTIL_END_NAMESPACE()
262 #endif // API_UTIL_JSONUTIL_H
263