HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NET_ConvertToType.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: NET_ConvertToType.h (LM Library, C++)
7  *
8  * COMMENTS: Convert a type to another type
9  */
10 
11 #ifndef __NET_ConvertToType_H__
12 #define __NET_ConvertToType_H__
13 
14 #include "NET_API.h"
15 
16 #include <UT/UT_IntArray.h>
17 #include <UT/UT_JSONValue.h>
18 #include <UT/UT_JSONValueArray.h>
19 #include <UT/UT_JSONValueMap.h>
20 #include <UT/UT_JSONWriter.h>
21 #include <UT/UT_String.h>
22 #include <UT/UT_StringArray.h>
23 #include <UT/UT_StringHolder.h>
24 #include <UT/UT_StringView.h>
25 #include <UT/UT_Variant.h>
26 #include <UT/UT_WorkBuffer.h>
27 
28 #include <type_traits>
29 
30 #define NET_REQUIRE(_cond_) std::enable_if_t<_cond_>
31 
32 // -----------------------------------------------------------------------------
33 // Serialize Object
34 // -----------------------------------------------------------------------------
35 
36 template <typename T>
37 bool NETserialize(UT_JSONWriter& writer, const T& obj)
38 {
39  return obj.serialize(writer);
40 }
41 
42 template <typename T>
44 {
45  return obj.serialize(data);
46 }
47 
48 // -----------------------------------------------------------------------------
49 // Serialize Integers
50 // -----------------------------------------------------------------------------
51 
52 #define NET_DEFINE_INT_SERIALIZER(_T_) \
53  template <> \
54  inline bool NETserialize<_T_>(UT_JSONWriter& writer, const _T_& obj) \
55 { \
56  writer.jsonValue(obj); \
57  return true; \
58 } \
59  template <> \
60  inline bool NETserialize<_T_>(const UT_JSONValue& data, _T_& item) \
61 { \
62  int64 v = 0; \
63  bool res = data.import(v); \
64  item = static_cast<_T_>(v); \
65  return res; \
66 }
70 #undef NET_DEFINE_INT_SERIALIZER
71 
72 template <>
73 inline bool NETserialize<int64>(UT_JSONWriter& writer, const int64& obj)
74 {
75  writer.jsonValue(obj);
76  return true;
77 }
78 
79 template <>
81 {
82  return data.import(obj);
83 }
84 
85 template <>
86 inline bool NETserialize<uint32>(UT_JSONWriter& writer, const uint32& obj)
87 {
88  writer.jsonValue(static_cast<int32>(obj));
89  return true;
90 }
91 
92 template <>
94 {
95  int64 tmp = 0;
96  bool res = data.import(tmp);
97  obj = static_cast<uint32>(tmp);
98  return res;
99 }
100 
101 // -----------------------------------------------------------------------------
102 // Serialize Bool
103 // -----------------------------------------------------------------------------
104 
105 template <>
106 inline bool NETserialize<bool>(UT_JSONWriter& writer, const bool& obj)
107 {
108  writer.jsonValue(obj);
109  return true;
110 }
111 
112 template <>
113 inline bool NETserialize<bool>(const UT_JSONValue& data, bool& item)
114 {
115  return data.import(item);
116 }
117 
118 // -----------------------------------------------------------------------------
119 // Serialize String Holder
120 // -----------------------------------------------------------------------------
121 
122 template <>
124 {
125  writer.jsonValue(obj);
126  return true;
127 }
128 
129 template <>
131 {
132  return data.import(obj);
133 }
134 
135 template <>
137 {
138  writer.jsonValue(obj);
139  return true;
140 }
141 template <>
143 {
144  if (data.getType() != UT_JSONValue::JSON_STRING)
145  return false;
146  obj = data.getS();
147  return true;
148 }
149 
150 template <>
152 {
153  writer.jsonValue(obj.asRef());
154  return true;
155 }
156 
157 template <>
158 inline bool NETserialize<UT_StringLit>(const UT_JSONValue& data, UT_StringLit&) = delete;
159 
160 // -----------------------------------------------------------------------------
161 // Serialize WorkBuffer
162 // -----------------------------------------------------------------------------
163 
164 template <>
166 {
167  writer.jsonValue(obj);
168  return true;
169 }
170 
171 template <>
173 {
174  return data.import(obj);
175 }
176 
177 // -----------------------------------------------------------------------------
178 // Serialize Arrays
179 // -----------------------------------------------------------------------------
180 
181 template <typename T, template <typename> class ARRAY>
182 inline bool NETserializeArray(UT_JSONWriter& writer, const ARRAY<T>& items)
183 {
184  writer.jsonBeginArray();
185  for (auto&& item : items)
186  NETserialize<T>(writer, item);
187  writer.jsonEndArray();
188  return true;
189 }
190 
191 template <typename T, template <typename> class ARRAY>
192 inline bool NETserializeArray(const UT_JSONValue& data, ARRAY<T>& items)
193 {
194  // To support some older clients that were sending empty strings in place
195  // of empty arrays.
196  if (data.getType() == UT_JSONValue::JSON_STRING)
197  {
198  const UT_StringHolder* str = data.getStringHolder();
199  if (str && str->isEmpty())
200  return true;
201  }
202  if (data.getType() != UT_JSONValue::JSON_ARRAY)
203  return false;
205  if (values == nullptr)
206  return false;
207  exint size = values->entries();
208  items.setSize(size);
209  for (exint i = 0; i < size; ++i)
210  {
211  UT_JSONValue* value = values->get(i);
212  if (value == nullptr)
213  continue;
214  NETserialize<T>(*value, items[i]);
215  }
216  return true;
217 }
218 
219 #define NET_DEFINE_ARRAY_SERIALIZER(_ARRAY_) \
220 template <typename T> \
221 inline bool NETserialize(UT_JSONWriter& writer, const _ARRAY_<typename T::value_type>& items) \
222 { \
223  return NETserializeArray<typename T::value_type, _ARRAY_>(writer, items); \
224 } \
225 template <typename T> \
226 inline bool NETserialize(const UT_JSONValue& data, _ARRAY_<typename T::value_type>& items) \
227 { \
228  return NETserializeArray<typename T::value_type, _ARRAY_>(data, items); \
229 }
232 #undef NET_DEFINE_ARRAY_SERIALIZER
233 
234 template <>
236 {
237  return writer.jsonStringArray(items);
238 }
239 
240 template <>
242 {
243  // To support some older clients that were sending empty strings in place
244  // of empty arrays.
245  if (data.getType() == UT_JSONValue::JSON_STRING)
246  {
247  const UT_StringHolder* str = data.getStringHolder();
248  if (str && str->isEmpty())
249  return true;
250  }
251  return data.import(items);
252 }
253 
254 // -----------------------------------------------------------------------------
255 // Serialize JSONValue
256 // -----------------------------------------------------------------------------
257 
258 template <>
260 {
261  writer.jsonValue(value);
262  return false;
263 }
264 
265 template <>
267 {
268  item = data;
269  return true;
270 }
271 
272 // -----------------------------------------------------------------------------
273 // Serialize UT_Variant
274 // -----------------------------------------------------------------------------
275 
276 // Forward declare so UT_VariantArray and UT_Variant can use each others serialize
277 // functions
278 template <>
280 template <>
282 template <>
284 template <>
286 
287 template <>
289 {
290  if (v.type() == UT_Variant::Type::Int)
291  writer.jsonValue(v.get<int64>());
292  else if (v.type() == UT_Variant::Type::Float)
293  writer.jsonValue(v.get<float>());
294  else if (v.type() == UT_Variant::Type::String)
295  writer.jsonValue(v.get<UT_StringHolder>());
296  else if (v.type() == UT_Variant::Type::Bool)
297  writer.jsonValue(v.get<bool>());
298  else if (v.type() == UT_Variant::Type::Array)
299  {
301  return NETserialize(writer, values);
302  }
303  else if (v.type() == UT_Variant::Type::Map)
304  {
306  return NETserialize(writer, values);
307  }
308  else
309  {
310  return false;
311  }
312 
313  return true;
314 }
315 
316 template <>
318 {
319  if (data.getType() == UT_JSONValue::JSON_INT)
320  v = data.getI();
321  else if (data.getType() == UT_JSONValue::JSON_REAL)
322  v = data.getF();
323  else if (data.getType() == UT_JSONValue::JSON_BOOL)
324  v = data.getB();
325  else if (data.getType() == UT_JSONValue::JSON_STRING)
326  v = data.getStringHolder();
327  else if (data.getType() == UT_JSONValue::JSON_ARRAY)
328  {
329  UT_VariantArray variants;
330  if (!NETserialize(data, variants))
331  return false;
332 
333  v = variants;
334  }
335  else if (data.getType() == UT_JSONValue::JSON_MAP)
336  {
337  UT_VariantMap variants;
338  if (!NETserialize(data, variants))
339  return false;
340 
341  v = variants;
342  }
343  else
344  {
345  return false;
346  }
347 
348  return true;
349 }
350 
351 // -----------------------------------------------------------------------------
352 // Serialize UT_VariantArray
353 // -----------------------------------------------------------------------------
354 
355 template <>
356 inline bool NETserialize<UT_VariantArray>(UT_JSONWriter& writer, const UT_VariantArray& variants)
357 {
358  writer.jsonBeginArray();
359 
360  for (auto&& k : variants)
361  {
362  if (!NETserialize(writer, k))
363  return false;
364  }
365 
366  writer.jsonEndArray();
367 
368  return true;
369 }
370 
371 template <>
373 {
374  UT_JSONValueArray* arr = data.getArray();
375  if (arr == nullptr)
376  return false;
377 
378  for (int i = 0; i < arr->entries(); i++)
379  {
380  UT_JSONValue* json = arr->get(i);
381  if (json == nullptr)
382  return false;
383 
385  if (!NETserialize(*json, value))
386  return false;
387 
388  variants.append(value);
389  }
390 
391  return true;
392 }
393 
394 // -----------------------------------------------------------------------------
395 // Serialize a UT_VariantMap
396 // -----------------------------------------------------------------------------
397 
398 template <>
399 inline bool NETserialize<UT_VariantMap>(UT_JSONWriter& writer, const UT_VariantMap& variants)
400 {
401  writer.jsonBeginMap();
402 
403  for (auto&& v : variants)
404  {
405  if (v.second.type() == UT_Variant::Type::Null)
406  continue;
407 
408  writer.jsonKeyToken(v.first);
409  if (!NETserialize(writer, v.second))
410  return false;
411  }
412 
413  writer.jsonEndMap();
414  return true;
415 }
416 
417 template <>
419 {
420  UT_JSONValueMap* json = data.getMap();
421  if (json == nullptr)
422  return false;
423 
424  for (auto&& v : *json)
425  {
426  if (v.second == nullptr)
427  return false;
428 
430  if (!NETserialize(*v.second, value))
431  return false;
432 
433  variants[v.first] = value;
434  }
435 
436  return false;
437 }
438 
439 // -----------------------------------------------------------------------------
440 // Helper for cases where you dont need to serialize something for whatever
441 // reason. Typically this would only ever be used when doing templated calls
442 // where theres little control over how to serialize something.
443 // For example, in some cases the parameter on an api function no longer means
444 // anything then it might make sense to just ignore it.
445 // -----------------------------------------------------------------------------
447 {
448 public:
449 };
450 
452 
453 template <>
454 inline bool
456  UT_JSONWriter& writer,
457  const NET_EmptySerializer&)
458 {
459  return true;
460 }
461 
462 template <>
463 inline bool
465  const UT_JSONValue& data,
467 {
468  return true;
469 }
470 
471 // =============================================================================
472 // Deprecated conversion type.
473 // =============================================================================
474 
475 namespace NET_ConvertToType
476 {
477 // Remove const reference from type
478 template <class T>
480 {
481  typedef std::remove_const_t<std::remove_reference_t<T>> type;
482 };
483 
484 template <class T>
486 
487 // C++ 17 will allow us to support more then just UT_StringHolder and combine
488 // some of this code as well.
489 template <typename Tto, typename Enable = void>
491 {
492 public:
493  static Tto cast(const UT_StringHolder& source)
494  {
495  UT_ASSERT(!"This code should never be entered. You have not setup a proper cast for this type.");
496  return Tto{};
497  }
498 };
499 
500 template <typename Tto>
501 class convertImpl<Tto,
502  std::enable_if_t<std::is_same<UT_StringHolder,
503  NET_remove_cref_t<Tto>>::value>>
504 {
505 public:
506  static Tto cast(const UT_StringHolder &source) { return source; }
507 };
508 
509 template <typename Tto>
510 class convertImpl<Tto,
511  std::enable_if_t<std::is_same<UT_StringArray,
512  NET_remove_cref_t<Tto>>::value>>
513 {
514 public:
515  static Tto cast(const UT_StringHolder &source)
516  {
517  // Try parsing it as a json string array first. If that fails then
518  // try parsing it as a custom array string.
520  if (value.parseValue(source))
521  {
523  if (NETserialize(value, values))
524  return values;
525  }
526 
527  UT_StringView view_source(source.buffer());
528  UT_StringViewArray values = view_source.split(",");
530  result.setCapacity(values.entries());
531  for (auto &&value : values)
532  {
533  result.emplace_back(value);
534  }
535 
536  return result;
537  }
538 };
539 
540 template <typename Tto>
542  Tto,
543  std::enable_if_t<std::is_same<UT_IntArray, NET_remove_cref_t<Tto>>::value>>
544 {
545 public:
546  static Tto cast(const UT_StringHolder &source)
547  {
548  UT_StringView view_source(source.buffer());
549  UT_StringViewArray values = view_source.split(",");
551  result.setCapacity(values.entries());
552  for (auto &&value : values)
553  {
554  UT_String str(value);
555  result.emplace_back(str.toInt());
556  }
557 
558  return result;
559  }
560 };
561 
562 template <typename Tto>
563 class convertImpl<Tto,
564  std::enable_if_t<std::is_integral<Tto>::value &&
565  !std::is_same<Tto, bool>::value>>
566 {
567 public:
568  // Return integer
569  static Tto cast(const UT_StringHolder &source)
570  {
571  UT_ASSERT(source.isInteger());
572  return source.toInt();
573  }
574 };
575 
576 template <typename Tto>
577 class convertImpl<Tto, std::enable_if_t<std::is_floating_point<Tto>::value>>
578 {
579 public:
580  // Return float
581  static Tto cast(const UT_StringHolder &source)
582  {
583  UT_ASSERT(source.isFloat());
584  return source.toFloat();
585  }
586 };
587 
588 template <typename Tto>
589 class convertImpl<Tto, std::enable_if_t<std::is_same<bool, Tto>::value>>
590 {
591 public:
592  // Return bool
593  static Tto cast(const UT_StringHolder &source)
594  {
595  if (source.isInteger())
596  return source.toInt();
597 
598  UT_StringRef low_source = source.toLower();
599  return low_source == "true";
600  }
601 };
602 
603 } // namespace NET_ConvertToType
604 
605 template <typename Tto, typename Tfrom>
606 Tto
607 convert(const Tfrom &source)
608 {
610 }
611 
612 #endif // __NET_ConvertToType_H__
static Tto cast(const UT_StringHolder &source)
typename std::enable_if< B, T >::type enable_if_t
Define Imath::enable_if_t to be std for C++14, equivalent for C++11.
bool NETserialize< UT_String >(UT_JSONWriter &writer, const UT_String &obj)
bool NETserialize< UT_WorkBuffer >(UT_JSONWriter &writer, const UT_WorkBuffer &obj)
UT_JSONValueMap stores a map/dictionary of UT_JSONValue objects.
int int32
Definition: SYS_Types.h:39
SYS_NO_DISCARD_RESULT UT_JSONValueArray * getArray() const
Get the array value (may return a NULL pointer)
bool parseValue(UT_JSONParser &parser, UT_IStream *is=0, bool record_source_offsets=false)
int toInt() const
UT_JSONValueArray stores a list of UT_JSONValue objects.
bool isEmpty() const
Same as !isstring()
typename NET_remove_cref< T >::type NET_remove_cref_t
int64 exint
Definition: SYS_Types.h:125
bool NETserialize< NET_EmptySerializer >(UT_JSONWriter &writer, const NET_EmptySerializer &)
bool NETserialize< UT_VariantMap >(UT_JSONWriter &writer, const UT_VariantMap &value)
bool NETserialize< bool >(UT_JSONWriter &writer, const bool &obj)
Tto convert(const Tfrom &source)
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:35
bool NETserialize< UT_StringArray >(UT_JSONWriter &writer, const UT_StringArray &items)
bool NETserialize< UT_StringLit >(UT_JSONWriter &writer, const UT_StringLit &obj)
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
fpreal toFloat() const
A 64-bit float value.
GLsizeiptr size
Definition: glcorearb.h:664
#define NET_API
Definition: NET_API.h:9
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:40
A 64-bit signed integer.
void setCapacity(exint newcapacity)
Definition: UT_ArrayImpl.h:756
bool NETserialize< UT_Variant >(UT_JSONWriter &writer, const UT_Variant &v)
exint emplace_back(S &&...s)
Definition: UT_ArrayImpl.h:177
SYS_FORCE_INLINE const char * buffer() const
A shared string.
const GLdouble * v
Definition: glcorearb.h:837
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
bool NETserialize< int64 >(UT_JSONWriter &writer, const int64 &obj)
bool NETserialize(UT_JSONWriter &writer, const T &obj)
GLhandleARB obj
Definition: glew.h:6266
long long int64
Definition: SYS_Types.h:116
signed char int8
Definition: SYS_Types.h:35
GLuint res
Definition: glew.h:11549
#define NET_DEFINE_INT_SERIALIZER(_T_)
A null variant. A null variant holds no value.
SYS_NO_DISCARD_RESULT const UT_StringHolder * getStringHolder() const
Return the string value.
SYS_FORCE_INLINE int64 entries() const
Return the number of entries in the array.
GLboolean * data
Definition: glcorearb.h:131
bool NETserialize< UT_JSONValue >(UT_JSONWriter &writer, const UT_JSONValue &value)
short int16
Definition: SYS_Types.h:37
SYS_NO_DISCARD_RESULT UT_StringRef toLower() const
#define NET_DEFINE_ARRAY_SERIALIZER(_ARRAY_)
bool jsonBeginArray()
Begin a generic array object.
GLsizei const GLfloat * value
Definition: glcorearb.h:824
SYS_NO_DISCARD_RESULT Type getType() const
Get the type of data stored in the object.
Definition: UT_JSONValue.h:134
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:77
unsigned int uint32
Definition: SYS_Types.h:40
unsigned isInteger(int skip_spaces=0) const
Determine if string can be seen as a single integer number.
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:153
Definition: core.h:1131
int toInt() const
SYS_NO_DISCARD_RESULT const UT_JSONValueArray * getArray(int64 i) const
Access a const array by index.
A UT_VariantMap value.
unsigned isFloat(int skip_spaces=0, int loose=0) const
Determine if string can be seen as a single floating point number.
std::remove_const_t< std::remove_reference_t< T > > type
Definition: format.h:895
SYS_FORCE_INLINE const UT_JSONValue * get(int64 i) const
Access a const entry by index.
A UT_VariantArray value.
bool NETserialize< UT_StringHolder >(UT_JSONWriter &writer, const UT_StringHolder &obj)
bool NETserialize< UT_VariantArray >(UT_JSONWriter &writer, const UT_VariantArray &value)
bool NETserialize< uint32 >(UT_JSONWriter &writer, const uint32 &obj)
bool NETserializeArray(UT_JSONWriter &writer, const ARRAY< T > &items)