[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / loader / json-reader.h
1 #ifndef DALI_SCENE3D_LOADER_JSON_READER_H_
2 #define DALI_SCENE3D_LOADER_JSON_READER_H_
3 /*
4  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 // EXTERNAL INCLUDES
21 #include <dali/public-api/common/vector-wrapper.h>
22 #include <algorithm>
23 #include <cstring>
24 #include <map>
25 #include <memory>
26 #include <sstream>
27 #include <string_view>
28
29 // INTERNAL INCLUDES
30 #include <dali-scene3d/third-party/json.h> // TODO : Since license issue, We shoud replace this thing as <dali-toolkit/devel-api/builder/json-parser.h>
31
32 namespace json
33 {
34 /**
35  * @brief Helper for freeing the memory allocated by json_parse()
36  */
37 struct json_value_deleter
38 {
39   void operator()(json_value_s* p) const
40   {
41     free(p);
42   }
43 };
44 typedef std::unique_ptr<json_value_s, json_value_deleter> unique_ptr;
45
46 /**
47  * @brief Case sensitive comparison of json_string_s and c-string.
48  * @return difference in first different character, or 0 if the strings are identical.
49  */
50 int StrCmp(const json_string_s& js, const char* s);
51
52 /**
53  * @brief Case sensitive comparison of json_string_s and std::string.
54  * @return difference in first different character, or 0 if the strings are identical.
55  */
56 int StrCmp(const json_string_s& js, const std::string& s);
57
58 /**
59  * @brief Convenience function to compare json_string_s and other supported string type,
60  *  in swapped order.
61  */
62 template<typename String>
63 inline int StrCmp(String& s, const json_string_s& js)
64 {
65   return -StrCmp(js, s);
66 }
67
68 /**
69  * @brief Checks @a jv to be the given @a type, otherwise a std::runtime_error is thrown.
70  */
71 void Validate(const json_value_s& jv, json_type_e type);
72
73 namespace detail
74 {
75 /**
76  * @brief Compile-time type-enum mapping.
77  */
78 template<typename T>
79 struct Type2Enum
80 {
81 };
82
83 #define TYPE2ENUM(x)             \
84   template<>                     \
85   struct Type2Enum<json_##x##_s> \
86   {                              \
87     enum                         \
88     {                            \
89       VALUE = json_type_##x      \
90     };                           \
91   };
92
93 TYPE2ENUM(object)
94 TYPE2ENUM(array)
95 TYPE2ENUM(string)
96 TYPE2ENUM(number)
97 #undef TYPE2ENUM
98 } // namespace detail
99
100 /**
101  * @brief Casts the payload of a json_value_s to the given type.
102  */
103 template<typename Out>
104 inline const Out& Cast(const json_value_s& j)
105 {
106   Validate(j, static_cast<json_type_e>(detail::Type2Enum<typename std::decay<Out>::type>::VALUE));
107   return *static_cast<const Out*>(j.payload);
108 }
109
110 /**
111  * @brief Casts the payload of a json_value_s to the given type.
112  * @note std::runtime_error is thrown if the value is not the given type.
113  */
114 template<typename Out>
115 inline Out& Cast(json_value_s& j)
116 {
117   Validate(j, static_cast<json_type_e>(detail::Type2Enum<typename std::decay<Out>::type>::VALUE));
118   return *static_cast<Out*>(j.payload);
119 }
120
121 /**
122  * @brief Helper function to find a child element of @a obj mapped to @a key.
123  * @return Pointer to the element, or nullptr if it could not be found.
124  */
125 json_value_s* FindObjectChild(const std::string& key, json_object_s& obj);
126
127 /**
128  * @brief Helper functions for reading various value types.
129  */
130 struct Read
131 {
132   static bool Boolean(const json_value_s& j)
133   {
134     if(j.type == json_type_true)
135     {
136       return true;
137     }
138     else if(j.type == json_type_false)
139     {
140       return false;
141     }
142     else // try to interpret a numeric value.
143     {
144       return Number<int>(j) != 0;
145     }
146   }
147
148   template<typename T>
149   static T Number(const json_value_s& j)
150   {
151     auto&             jn = Cast<const json_number_s>(j);
152     std::stringstream ss;
153     for(auto i0 = jn.number, i1 = i0 + jn.number_size; i0 != i1; ++i0)
154     {
155       ss.put(*i0);
156     }
157
158     T result;
159     if(ss >> result)
160     {
161       return result;
162     }
163     throw std::runtime_error("Failed to convert value to number");
164   }
165
166   template<typename E>
167   static E Enum(const json_value_s& j)
168   {
169     size_t number = Number<size_t>(j);
170     return static_cast<E>(number);
171   }
172
173   static std::string_view StringView(const json_string_s& js)
174   {
175     return std::string_view(js.string, js.string_size);
176   }
177
178   static std::string_view StringView(const json_value_s& j)
179   {
180     auto& js = Cast<json_string_s>(j);
181     return StringView(js);
182   }
183
184   static std::string String(const json_value_s& j)
185   {
186     auto& js = Cast<const json_string_s>(j);
187     return std::string(js.string, js.string_size);
188   }
189
190   template<typename T, T (*readElement)(const json_value_s&)>
191   static std::vector<T> Array(const json_value_s& j)
192   {
193     auto&          ja = Cast<const json_array_s>(j);
194     std::vector<T> result;
195     result.reserve(ja.length);
196     auto i = ja.start;
197     while(i)
198     {
199       result.push_back(std::move(readElement(*i->value)));
200       i = i->next;
201     }
202     return result;
203   }
204 };
205
206 /**
207  * @brief Core class for object properties.
208  */
209 struct PropertyCore
210 {
211 protected:
212   explicit PropertyCore(const std::string& key)
213   : mKey(key)
214   {
215   }
216
217   const std::string& GetKey() const
218   {
219     return mKey;
220   }
221
222 private:
223   std::string mKey;
224 };
225
226 /**
227  * @brief Base class for the properties of a type T.
228  */
229 template<typename T>
230 struct PropertyBase : PropertyCore
231 {
232   using PropertyCore::GetKey;
233
234   explicit PropertyBase(const std::string& key)
235   : PropertyCore(key)
236   {
237   }
238
239   virtual ~PropertyBase()
240   {
241   }
242
243   virtual void Read(const json_value_s& j, T& obj) = 0;
244 };
245
246 /**
247  * @brief Concrete property of an object to read into from JSON with a given function.
248  */
249 template<class T, typename U>
250 struct Property : PropertyBase<T>
251 {
252   using ReadFn        = U (*)(const json_value_s&);
253   using MemberPtr     = U T::*;
254   using SetterArgType = typename std::conditional<sizeof(U) <= sizeof(uintptr_t), U, const U&>::type;
255   using Setter        = void (T::*)(SetterArgType);
256
257   Property(const std::string& key, ReadFn read, MemberPtr ptr)
258   : PropertyBase<T>(key),
259     mRead(read),
260     mAccessor(new DirectAccessor(ptr))
261   {
262   }
263
264   Property(const std::string& key, ReadFn read, Setter setter)
265   : PropertyBase<T>(key),
266     mRead(read),
267     mAccessor(new SetterAccessor(setter))
268   {
269   }
270
271   ~Property()
272   {
273   }
274
275   void Read(const json_value_s& j, T& obj) override
276   {
277     mAccessor->Set(mRead(j), obj);
278   }
279
280 private:
281   struct AccessorBase
282   {
283     virtual ~AccessorBase()
284     {
285     }
286
287     virtual void Set(U value, T& obj) const = 0;
288   };
289
290   struct DirectAccessor : AccessorBase
291   {
292     DirectAccessor(MemberPtr ptr)
293     : mPointer(ptr)
294     {
295     }
296
297     void Set(U value, T& obj) const override
298     {
299       obj.*mPointer = std::move(value);
300     }
301
302     MemberPtr mPointer;
303   };
304
305   struct SetterAccessor : AccessorBase
306   {
307     SetterAccessor(Setter setter)
308     : mSetter(setter)
309     {
310     }
311
312     void Set(U value, T& obj) const override
313     {
314       (obj.*mSetter)(value);
315     }
316
317     Setter mSetter;
318   };
319
320   ReadFn                        mRead;
321   std::unique_ptr<AccessorBase> mAccessor;
322 };
323
324 /**
325  * @brief Helper function to make a Property for a member of type U, of object of type T.
326  */
327 template<class T, typename U>
328 Property<T, U>* MakeProperty(const std::string& key, typename Property<T, U>::ReadFn readFn, U T::*ptr)
329 {
330   return new Property<T, U>(key, readFn, ptr);
331 }
332
333 /**
334  * @brief Core class for an object Reader.
335  */
336 struct ReaderCore
337 {
338 protected:
339   std::vector<void*> mProperties;
340
341   ReaderCore() = default;
342
343   ReaderCore(const ReaderCore& other) = delete;
344   ReaderCore& operator=(const ReaderCore& other) = delete;
345
346   ReaderCore(ReaderCore&& other) = default;
347   ReaderCore& operator=(ReaderCore&& other) = default;
348 };
349
350 /**
351  * @brief Object Reader template for reading into an object of a given type,
352  *  with properties registered for the various members.
353  */
354 template<typename T>
355 class Reader : protected ReaderCore
356 {
357 public:
358   Reader() = default;
359
360   Reader(const Reader<T>& other) = delete;
361   Reader<T>& operator=(const Reader<T>& other) = delete;
362
363   Reader(Reader<T>&& other) = default;
364   Reader<T>& operator=(Reader&& other) = default;
365
366   ~Reader()
367   {
368     for(auto& p : mProperties)
369     {
370       delete Cast(p);
371     }
372   }
373
374   Reader<T>& Register(PropertyBase<T>& prop)
375   {
376     auto iInsert = std::lower_bound(mProperties.begin(), mProperties.end(), &prop, SortPredicate);
377     if(iInsert == mProperties.end() || Cast(*iInsert)->GetKey() != prop.GetKey())
378     {
379       mProperties.insert(iInsert, &prop);
380     }
381     else
382     {
383       delete Cast(*iInsert);
384       *iInsert = &prop;
385     }
386     return *this;
387   }
388
389   void Read(const json_object_s& jo, T& obj) const
390   {
391     auto i = jo.start;
392     while(i)
393     {
394       auto iFind = std::lower_bound(mProperties.begin(), mProperties.end(), *i->name, FindPredicate);
395       if(iFind != mProperties.end())
396       {
397         auto prop = Cast(*iFind);
398         if(0 == StrCmp(*i->name, prop->GetKey()))
399         {
400           prop->Read(*i->value, obj);
401         }
402       }
403       i = i->next;
404     }
405   }
406
407 private:
408   static inline PropertyBase<T>* Cast(void* p)
409   {
410     return static_cast<PropertyBase<T>*>(p);
411   }
412
413   static bool SortPredicate(void* p, PropertyBase<T>* prop)
414   {
415     const auto prop0 = Cast(p);
416     return prop0->GetKey().compare(prop->GetKey()) < 0;
417   }
418
419   static bool FindPredicate(void* p, const json_string_s& key)
420   {
421     const auto prop = Cast(p);
422     return StrCmp(prop->GetKey(), key) < 0;
423   }
424 };
425
426 /**
427  * @brief Wraps a Reader<T> in a function usable as a Property<T>::ReadFn, i.e. to facilitate
428  *  deserializing structures of nested objects.
429  */
430 template<typename T>
431 struct ObjectReader
432 {
433   static const Reader<T>* sReader;
434
435   static T Read(const json_value_s& j)
436   {
437     T     result;
438     auto& jo = Cast<json_object_s>(j);
439     sReader->Read(jo, result);
440     return result;
441   }
442 };
443
444 template<typename T>
445 const Reader<T>* ObjectReader<T>::sReader = nullptr;
446
447 template<typename T>
448 void SetObjectReader(const Reader<T>& r)
449 {
450   ObjectReader<T>::sReader = &r;
451 }
452
453 } // namespace json
454
455 #endif //DALI_SCENE3D_LOADER_JSON_READER_H_