All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
crateValueInliners.h
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef USD_CRATE_VALUE_INLINERS_H
25 #define USD_CRATE_VALUE_INLINERS_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/base/gf/traits.h"
29 
30 #include <type_traits>
31 #include <limits>
32 #include <cstdint>
33 #include <cstring>
34 
35 PXR_NAMESPACE_OPEN_SCOPE
36 
37 
38 namespace Usd_CrateValueInliners
39 {
40 
41 // Return true and set \p *dst if \p src can be exactly represented as a Dst
42 // instance. This only works for numeric types, and it checks range before
43 // doing the conversion.
44 template <class Src, class Dst>
45 inline bool _IsExactlyRepresented(Src const &src, Dst *dst) {
46  Src min = static_cast<Src>(std::numeric_limits<Dst>::lowest());
47  Src max = static_cast<Src>(std::numeric_limits<Dst>::max());
48  if (min <= src && src <= max &&
49  static_cast<Src>(static_cast<Dst>(src)) == src) {
50  *dst = static_cast<Dst>(src);
51  return true;
52  }
53  return false;
54 }
55 
56 // Base case templates.
57 template <class T> bool _EncodeInline(T, ...) { return false; }
58 template <class T> void _DecodeInline(T *, ...) { }
59 
61 // Inline double as float if possible.
62 template <class FP>
63 typename std::enable_if<std::is_floating_point<FP>::value, bool>::type
64 _EncodeInline(FP fp, uint32_t *ival) {
65  // If fp is representable exactly as float, encode as inline float.
66  float f;
67  if (_IsExactlyRepresented(fp, &f)) {
68  memcpy(ival, &f, sizeof(f));
69  return true;
70  }
71  return false;
72 }
73 template <class FP>
74 typename std::enable_if<std::is_floating_point<FP>::value>::type
75 _DecodeInline(FP *fp, uint32_t ival) {
76  float f;
77  memcpy(&f, &ival, sizeof(f));
78  *fp = static_cast<FP>(f);
79 }
80 
82 // Inline integral as int if possible.
83 template <class INT>
84 typename std::enable_if<std::is_integral<INT>::value, bool>::type
85 _EncodeInline(INT i, uint32_t *ival) {
86  // If i is in-range for (u)int32_t, encode as such.
87  using int_t = typename std::conditional<
88  std::is_signed<INT>::value, int32_t, uint32_t>::type;
89  int_t rep;
90  if (_IsExactlyRepresented(i, &rep)) {
91  memcpy(ival, &rep, sizeof(rep));
92  return true;
93  }
94  return false;
95 }
96 template <class INT>
97 typename std::enable_if<std::is_integral<INT>::value>::type
98 _DecodeInline(INT *i, uint32_t ival) {
99  using int_t = typename std::conditional<
100  std::is_signed<INT>::value, int32_t, uint32_t>::type;
101  int_t tmp;
102  memcpy(&tmp, &ival, sizeof(tmp));
103  *i = static_cast<INT>(tmp);
104 }
105 
107 // Inline GfVecs when their components are exactly represented by int8_t.
108 template <class T>
109 typename std::enable_if<GfIsGfVec<T>::value, bool>::type
110 _EncodeInline(T vec, uint32_t *out) {
111  // If each component of the vector can be represented by an int8_t, we can
112  // inline it.
113  static_assert(T::dimension <= 4, "Vec dimension cannot exceed 4.");
114  int8_t ivec[T::dimension];
115  for (int i = 0; i != T::dimension; ++i) {
116  if (!_IsExactlyRepresented(vec[i], &ivec[i]))
117  return false;
118  }
119  // All components exactly represented as int8_t, can inline.
120  memcpy(out, ivec, sizeof(ivec));
121  return true;
122 }
123 template <class T>
124 typename std::enable_if<GfIsGfVec<T>::value>::type
125 _DecodeInline(T *vec, uint32_t in) {
126  int8_t ivec[T::dimension];
127  memcpy(ivec, &in, sizeof(ivec));
128  for (int i = 0; i != T::dimension; ++i) {
129  (*vec)[i] = static_cast<typename T::ScalarType>(ivec[i]);
130  }
131 }
132 
134 // Inline GfMatrices when they are all zeros off the diagonal and the diagonal
135 // entries are exactly represented by int8_t.
136 template <class Matrix>
137 typename std::enable_if<GfIsGfMatrix<Matrix>::value, bool>::type
138 _EncodeInline(Matrix m, uint32_t *out) {
139  static_assert(Matrix::numRows == Matrix::numColumns,
140  "Requires square matrices");
141  static_assert(Matrix::numRows <= 4,
142  "Matrix dimension cannot exceed 4");
143 
144  int8_t diag[Matrix::numRows];
145  for (int i = 0; i != Matrix::numRows; ++i) {
146  for (int j = 0; j != Matrix::numColumns; ++j) {
147  if (((i != j) && m[i][j] != 0) ||
148  ((i == j) && !_IsExactlyRepresented(m[i][j], &diag[i]))) {
149  return false;
150  }
151  }
152  }
153 
154  // All zeros off diagonal and diagonal is exactly represented by int8_t's --
155  // store inline.
156  memcpy(out, diag, sizeof(diag));
157  return true;
158 }
159 template <class Matrix>
160 typename std::enable_if<GfIsGfMatrix<Matrix>::value>::type
161 _DecodeInline(Matrix *m, uint32_t in) {
162  int8_t diag[Matrix::numRows];
163  memcpy(diag, &in, sizeof(diag));
164  *m = Matrix(1);
165  for (int i = 0; i != Matrix::numRows; ++i) {
166  (*m)[i][i] = static_cast<typename Matrix::ScalarType>(diag[i]);
167  }
168 }
169 
171 // Encode VtDictionary inline if it's empty.
172 inline bool
173 _EncodeInline(VtDictionary const &dict, uint32_t *ival) {
174  if (dict.empty()) {
175  *ival = 0;
176  return true;
177  }
178  return false;
179 }
180 inline void
181 _DecodeInline(VtDictionary *dict, uint32_t ival) {
182  *dict = VtDictionary();
183 }
184 
185 } // Usd_CrateValueInliners
186 
187 
188 PXR_NAMESPACE_CLOSE_SCOPE
189 
190 #endif // USD_CRATE_VALUE_INLINERS_H
191 
A map with string keys and VtValue values.
Definition: dictionary.h:61
VT_API bool empty() const
true if the VtDictionary&#39;s size is 0.