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_JSONWriter.h>
19 #include <UT/UT_SGuid.h>
20 #include <UT/UT_String.h>
21 #include <UT/UT_StringArray.h>
22 #include <UT/UT_StringHolder.h>
23 #include <UT/UT_StringSet.h>
24 #include <UT/UT_StringView.h>
25 #include <UT/UT_WorkBuffer.h>
26 
27 #include <type_traits>
28 
29 #define NET_REQUIRE(_cond_) std::enable_if_t<_cond_>
30 
31 // -----------------------------------------------------------------------------
32 // Serialize Object
33 // -----------------------------------------------------------------------------
34 
35 template <typename T>
36 bool NETserialize(UT_JSONWriter& writer, const T& obj)
37 {
38  return obj.serialize(writer);
39 }
40 
41 template <typename T>
42 bool NETserialize(const UT_JSONValue& data, T& obj)
43 {
44  return obj.serialize(data);
45 }
46 
47 // -----------------------------------------------------------------------------
48 // Serialize Integers
49 // -----------------------------------------------------------------------------
50 
51 #define NET_DEFINE_INT_SERIALIZER(_T_) \
52  template <> \
53  inline bool NETserialize<_T_>(UT_JSONWriter& writer, const _T_& obj) \
54 { \
55  writer.jsonValue(obj); \
56  return true; \
57 } \
58  template <> \
59  inline bool NETserialize<_T_>(const UT_JSONValue& data, _T_& item) \
60 { \
61  int64 v = 0; \
62  bool res = data.import(v); \
63  item = static_cast<_T_>(v); \
64  return res; \
65 }
69 #undef NET_DEFINE_INT_SERIALIZER
70 
71 template <>
72 inline bool NETserialize<int64>(UT_JSONWriter& writer, const int64& obj)
73 {
74  writer.jsonValue(obj);
75  return true;
76 }
77 
78 template <>
79 inline bool NETserialize<int64>(const UT_JSONValue& data, int64& obj)
80 {
81  return data.import(obj);
82 }
83 
84 template <>
85 inline bool NETserialize<uint32>(UT_JSONWriter& writer, const uint32& obj)
86 {
87  writer.jsonValue(static_cast<int32>(obj));
88  return true;
89 }
90 
91 template <>
92 inline bool NETserialize<uint32>(const UT_JSONValue& data, uint32& obj)
93 {
94  int64 tmp = 0;
95  bool res = data.import(tmp);
96  obj = static_cast<uint32>(tmp);
97  return res;
98 }
99 
100 // -----------------------------------------------------------------------------
101 // Serialize Bool
102 // -----------------------------------------------------------------------------
103 
104 template <>
105 inline bool NETserialize<bool>(UT_JSONWriter& writer, const bool& obj)
106 {
107  writer.jsonValue(obj);
108  return true;
109 }
110 
111 template <>
112 inline bool NETserialize<bool>(const UT_JSONValue& data, bool& item)
113 {
114  return data.import(item);
115 }
116 
117 // -----------------------------------------------------------------------------
118 // Serialize String Holder
119 // -----------------------------------------------------------------------------
120 
121 template <>
123 {
124  writer.jsonValue(obj);
125  return true;
126 }
127 
128 template <>
130 {
131  return data.import(obj);
132 }
133 
134 template <>
135 inline bool NETserialize<UT_StringRef>(UT_JSONWriter& writer, const UT_StringRef& obj)
136 {
137  writer.jsonValue(obj);
138  return true;
139 }
140 
141 template <>
143 {
144  return false;
145 }
146 
147 template <>
148 inline bool NETserialize<UT_String>(UT_JSONWriter& writer, const UT_String& obj)
149 {
150  writer.jsonValue(obj);
151  return true;
152 }
153 template <>
155 {
156  if (data.getType() != UT_JSONValue::JSON_STRING)
157  return false;
158  obj = data.getS();
159  return true;
160 }
161 
162 template <>
163 inline bool NETserialize<UT_StringLit>(UT_JSONWriter& writer, const UT_StringLit& obj)
164 {
165  writer.jsonValue(obj.asRef());
166  return true;
167 }
168 
169 template <>
170 inline bool NETserialize<UT_StringLit>(const UT_JSONValue& data, UT_StringLit&) = delete;
171 
172 // -----------------------------------------------------------------------------
173 // Serialize WorkBuffer
174 // -----------------------------------------------------------------------------
175 
176 template <>
178 {
179  writer.jsonValue(obj);
180  return true;
181 }
182 
183 template <>
185 {
186  return data.import(obj);
187 }
188 
189 // -----------------------------------------------------------------------------
190 // Serialize UT_SGuid
191 // -----------------------------------------------------------------------------
192 
193 template <>
194 inline bool NETserialize<UT_SGuid>(UT_JSONWriter& writer, const UT_SGuid& id)
195 {
196  writer.jsonValue(id.toString());
197  return true;
198 }
199 
200 template <>
202 {
203  UT_StringHolder str;
204  if (!data.import(str))
205  return false;
206 
207  return id.setString(str);
208 }
209 
210 // -----------------------------------------------------------------------------
211 // Serialize Arrays
212 // -----------------------------------------------------------------------------
213 
214 template <typename T, template <typename> class ARRAY>
215 inline bool NETserializeArray(UT_JSONWriter& writer, const ARRAY<T>& items)
216 {
217  writer.jsonBeginArray();
218  for (auto&& item : items)
219  NETserialize<T>(writer, item);
220  writer.jsonEndArray();
221  return true;
222 }
223 
224 template <typename T, template <typename> class ARRAY>
225 inline bool NETserializeArray(const UT_JSONValue& data, ARRAY<T>& items)
226 {
227  // To support some older clients that were sending empty strings in place
228  // of empty arrays.
229  if (data.getType() == UT_JSONValue::JSON_STRING)
230  {
231  const UT_StringHolder* str = data.getStringHolder();
232  if (str && str->isEmpty())
233  return true;
234  }
235  if (!data.isArray())
236  return false;
237  exint size = data.count();
238  items.setSize(size);
239  for (auto&& [index, value] : data.enumerate())
240  {
241  NETserialize<T>(value, items[index]);
242  }
243  return true;
244 }
245 
246 #define NET_DEFINE_ARRAY_SERIALIZER(_ARRAY_) \
247 template <typename T> \
248 inline bool NETserialize(UT_JSONWriter& writer, const _ARRAY_<typename T::value_type>& items) \
249 { \
250  return NETserializeArray<typename T::value_type, _ARRAY_>(writer, items); \
251 } \
252 template <typename T> \
253 inline bool NETserialize(const UT_JSONValue& data, _ARRAY_<typename T::value_type>& items) \
254 { \
255  return NETserializeArray<typename T::value_type, _ARRAY_>(data, items); \
256 }
259 #undef NET_DEFINE_ARRAY_SERIALIZER
260 
261 template <>
263 {
264  return writer.jsonStringArray(items);
265 }
266 
267 template <>
269 {
270  // To support some older clients that were sending empty strings in place
271  // of empty arrays.
272  if (data.getType() == UT_JSONValue::JSON_STRING)
273  {
274  const UT_StringHolder* str = data.getStringHolder();
275  if (str && str->isEmpty())
276  return true;
277  }
278  return data.import(items);
279 }
280 
281 // -----------------------------------------------------------------------------
282 // Serialize Sets
283 // -----------------------------------------------------------------------------
284 
285 template <typename SetT>
286 inline bool NETserializeSet(UT_JSONWriter& writer, const SetT& items)
287 {
288  using T = typename SetT::value_type;
289  writer.jsonBeginArray();
290  for (auto&& item : items)
291  NETserialize<T>(writer, item);
292  writer.jsonEndArray();
293  return true;
294 }
295 
296 template <typename SetT>
297 inline bool NETserializeSet(const UT_JSONValue& data, SetT& items)
298 {
299  using T = typename SetT::value_type;
300  static_assert(
301  std::is_default_constructible_v<T>,
302  "Serialize of a set requires the type to be default constructibe");
303  // To support some older clients that were sending empty strings in place
304  // of empty arrays.
305  if (data.getType() == UT_JSONValue::JSON_STRING)
306  {
307  UT_StringHolder str = data.getString();
308  if (str.isEmpty())
309  return true;
310  }
311  if (!data.isArray())
312  return false;
313  for (auto&& value : data)
314  {
315  T items_value;
316  NETserialize<T>(value, items_value);
317  items.emplace(items_value);
318  }
319  return true;
320 }
321 
322 #define NET_DEFINE_SET_SERIALIZER(_SET_) \
323 template <typename T> \
324 inline bool NETserialize(UT_JSONWriter& writer, const _SET_<typename T::value_type>& items) \
325 { \
326  return NETserializeSet<T>(writer, items); \
327 } \
328 template <typename T> \
329 inline bool NETserialize(const UT_JSONValue& data, _SET_<typename T::value_type>& items) \
330 { \
331  return NETserializeSet<T>(data, items); \
332 }
334 #undef NET_DEFINE_SET_SERIALIZER
335 
336 template <>
337 inline bool
339 {
340  return writer.jsonSetAsArray(items);
341 }
342 
343 template <>
344 inline bool
346 {
347  // To support some older clients that were sending empty strings in place
348  // of empty arrays.
349  if (data.getType() == UT_JSONValue::JSON_STRING)
350  {
351  const UT_StringHolder* str = data.getStringHolder();
352  if (str && str->isEmpty())
353  return true;
354  }
355 
356  return NETserializeSet<UT_StringSet>(data, items);
357 }
358 
359 // -----------------------------------------------------------------------------
360 // Serialize JSONValue
361 // -----------------------------------------------------------------------------
362 
363 template <>
365 {
366  writer.jsonValue(value);
367  return false;
368 }
369 
370 template <>
372 {
373  item = data;
374  return true;
375 }
376 
377 // -----------------------------------------------------------------------------
378 // Serialize std::pair<>
379 // -----------------------------------------------------------------------------
380 template <typename T1, typename T2>
381 inline bool
383  UT_JSONWriter &writer,
384  const std::pair<T1, T2> &obj)
385 {
386  writer.jsonBeginArray();
387  NETserialize<T1>(writer, obj.first);
388  NETserialize<T2>(writer, obj.second);
389  writer.jsonEndArray();
390  return true;
391 }
392 
393 template <typename T1, typename T2>
394 inline bool
396  const UT_JSONValue &data,
397  std::pair<T1, T2> &obj)
398 {
399  if (data.isArray() && data.count() == 2)
400  {
401  return NETserialize<T1>(data[0], obj.first)
402  && NETserialize<T2>(data[1], obj.second);
403  }
404  return false;
405 }
406 
407 template <typename T>
408 inline bool
410  UT_JSONWriter& writer,
411  const std::pair<typename T::first_type, typename T::second_type>& p)
412 {
413  return NETserializePair(writer, p);
414 }
415 template <typename T>
416 inline bool
418  const UT_JSONValue& data,
419  std::pair<typename T::first_type, typename T::second_type>& p)
420 {
421  return NETserializePair(data, p);
422 }
423 
424 // -----------------------------------------------------------------------------
425 // Helper for cases where you dont need to serialize something for whatever
426 // reason. Typically this would only ever be used when doing templated calls
427 // where theres little control over how to serialize something.
428 // For example, in some cases the parameter on an api function no longer means
429 // anything then it might make sense to just ignore it.
430 // -----------------------------------------------------------------------------
432 {
433 public:
434 };
435 
437 
438 template <>
439 inline bool
441  UT_JSONWriter& writer,
442  const NET_EmptySerializer&)
443 {
444  return true;
445 }
446 
447 template <>
448 inline bool
450  const UT_JSONValue& data,
452 {
453  return true;
454 }
455 
456 // =============================================================================
457 // Deprecated conversion type.
458 // =============================================================================
459 
460 namespace NET_ConvertToType
461 {
462 // Remove const reference from type
463 template <class T>
465 {
466  typedef std::remove_const_t<std::remove_reference_t<T>> type;
467 };
468 
469 template <class T>
471 
472 // C++ 17 will allow us to support more then just UT_StringHolder and combine
473 // some of this code as well.
474 template <typename Tto, typename Enable = void>
476 {
477 public:
478  static Tto cast(const UT_StringHolder& source)
479  {
480  UT_ASSERT(!"This code should never be entered. You have not setup a proper cast for this type.");
481  return Tto{};
482  }
483 };
484 
485 template <typename Tto>
486 class convertImpl<Tto,
487  std::enable_if_t<std::is_same<UT_StringHolder,
488  NET_remove_cref_t<Tto>>::value>>
489 {
490 public:
491  static Tto cast(const UT_StringHolder &source) { return source; }
492 };
493 
494 template <typename Tto>
495 class convertImpl<Tto,
496  std::enable_if_t<std::is_same<UT_StringArray,
497  NET_remove_cref_t<Tto>>::value>>
498 {
499 public:
500  static Tto cast(const UT_StringHolder &source)
501  {
502  // Try parsing it as a json string array first. If that fails then
503  // try parsing it as a custom array string.
505  if (value.parseValue(source))
506  {
508  if (NETserialize(value, values))
509  return values;
510  }
511 
512  UT_StringView view_source(source.buffer());
513  UT_StringViewArray values = view_source.split(",");
515  result.setCapacity(values.entries());
516  for (auto &&value : values)
517  {
518  result.emplace_back(value);
519  }
520 
521  return result;
522  }
523 };
524 
525 template <typename Tto>
527  Tto,
528  std::enable_if_t<std::is_same<UT_IntArray, NET_remove_cref_t<Tto>>::value>>
529 {
530 public:
531  static Tto cast(const UT_StringHolder &source)
532  {
533  UT_StringView view_source(source.buffer());
534  UT_StringViewArray values = view_source.split(",");
536  result.setCapacity(values.entries());
537  for (auto &&value : values)
538  {
539  UT_String str(value);
540  result.emplace_back(str.toInt());
541  }
542 
543  return result;
544  }
545 };
546 
547 template <typename Tto>
548 class convertImpl<Tto,
549  std::enable_if_t<std::is_integral<Tto>::value &&
550  !std::is_same<Tto, bool>::value>>
551 {
552 public:
553  // Return integer
554  static Tto cast(const UT_StringHolder &source)
555  {
556  UT_ASSERT(source.isInteger());
557  return source.toInt();
558  }
559 };
560 
561 template <typename Tto>
562 class convertImpl<Tto, std::enable_if_t<std::is_floating_point<Tto>::value>>
563 {
564 public:
565  // Return float
566  static Tto cast(const UT_StringHolder &source)
567  {
568  UT_ASSERT(source.isFloat());
569  return source.toFloat();
570  }
571 };
572 
573 template <typename Tto>
574 class convertImpl<Tto, std::enable_if_t<std::is_same<bool, Tto>::value>>
575 {
576 public:
577  // Return bool
578  static Tto cast(const UT_StringHolder &source)
579  {
580  if (source.isInteger())
581  return source.toInt();
582 
583  UT_StringRef low_source = source.toLower();
584  return low_source == "true";
585  }
586 };
587 
588 } // namespace NET_ConvertToType
589 
590 template <typename Tto, typename Tfrom>
591 Tto
592 convert(const Tfrom &source)
593 {
595 }
596 
597 #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)
Definition: UT_Set.h:58
int int32
Definition: SYS_Types.h:39
bool parseValue(UT_JSONParser &parser, UT_IStream *is=0, bool record_source_offsets=false)
bool NETserializeSet(UT_JSONWriter &writer, const SetT &items)
GLboolean * data
Definition: glcorearb.h:131
GLsizei const GLfloat * value
Definition: glcorearb.h:824
int toInt() const
bool isEmpty() const
Same as !isstring()
bool isFloat(bool skip_spaces=false, bool loose=false) const
Determine if string can be seen as a single floating point number.
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 &)
void setCapacity(exint new_capacity)
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:37
bool NETserialize< UT_SGuid >(UT_JSONWriter &writer, const UT_SGuid &id)
**But if you need a result
Definition: thread.h:613
uint64 value_type
Definition: GA_PrimCompat.h:29
bool NETserialize< UT_StringArray >(UT_JSONWriter &writer, const UT_StringArray &items)
bool NETserialize< UT_StringLit >(UT_JSONWriter &writer, const UT_StringLit &obj)
fpreal toFloat() const
#define NET_API
Definition: NET_API.h:9
bool isInteger(bool skip_spaces=false) const
Determine if string can be seen as a single integer number.
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:39
bool NETserializePair(UT_JSONWriter &writer, const std::pair< T1, T2 > &obj)
exint emplace_back(S &&...s)
Definition: UT_ArrayImpl.h:769
SYS_FORCE_INLINE const char * buffer() const
bool NETserialize< int64 >(UT_JSONWriter &writer, const int64 &obj)
bool NETserialize(UT_JSONWriter &writer, const T &obj)
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
SYS_NO_DISCARD_RESULT indexed_proxy enumerate()
Definition: UT_JSONValue.h:858
long long int64
Definition: SYS_Types.h:116
GLuint id
Definition: glcorearb.h:655
SYS_NO_DISCARD_RESULT bool isArray() const
Definition: UT_JSONValue.h:188
signed char int8
Definition: SYS_Types.h:35
#define NET_DEFINE_SET_SERIALIZER(_SET_)
#define NET_DEFINE_INT_SERIALIZER(_T_)
SYS_NO_DISCARD_RESULT const UT_StringHolder * getStringHolder() const
Return the string value.
GLsizeiptr size
Definition: glcorearb.h:664
bool NETserialize< UT_JSONValue >(UT_JSONWriter &writer, const UT_JSONValue &value)
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
short int16
Definition: SYS_Types.h:37
GLuint index
Definition: glcorearb.h:786
SYS_NO_DISCARD_RESULT exint count() const
Number of elements contained inside the json value.
SYS_NO_DISCARD_RESULT UT_StringRef toLower() const
#define NET_DEFINE_ARRAY_SERIALIZER(_ARRAY_)
bool jsonBeginArray()
Begin a generic array object.
SYS_NO_DISCARD_RESULT Type getType() const
Get the type of data stored in the object.
Definition: UT_JSONValue.h:186
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:99
unsigned int uint32
Definition: SYS_Types.h:40
bool NETserialize< UT_StringRef >(UT_JSONWriter &writer, const UT_StringRef &obj)
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
Definition: core.h:1131
int toInt() const
SYS_NO_DISCARD_RESULT const UT_StringHolder & getString() const
Definition: UT_JSONValue.h:205
std::remove_const_t< std::remove_reference_t< T > > type
Definition: format.h:895
bool NETserialize< UT_StringHolder >(UT_JSONWriter &writer, const UT_StringHolder &obj)
bool NETserialize< UT_StringSet >(UT_JSONWriter &writer, const UT_StringSet &items)
bool NETserialize< uint32 >(UT_JSONWriter &writer, const uint32 &obj)
bool NETserializeArray(UT_JSONWriter &writer, const ARRAY< T > &items)