Loading...
Searching...
No Matches
value.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_JS_VALUE_H
8#define PXR_BASE_JS_VALUE_H
9
11
12#include "pxr/pxr.h"
13#include "pxr/base/js/api.h"
14#include "pxr/base/js/types.h"
15#include "pxr/base/tf/delegatedCountPtr.h"
16
17#include <algorithm>
18#include <atomic>
19#include <cstdint>
20#include <string>
21#include <type_traits>
22#include <variant>
23#include <vector>
24
25PXR_NAMESPACE_OPEN_SCOPE
26
27// Value API Version
28// 1 (or undefined) - Initial version.
29// 2 - Changed Get{Array,Object} to GetJs{Array,Object}.
30#define JS_VALUE_API_VERSION 2
31
47{
48public:
50 enum Type {
51 ObjectType,
52 ArrayType,
53 StringType,
54 BoolType,
55 IntType,
56 RealType,
57 NullType
58 };
59
61 JS_API JsValue();
62
64 JS_API JsValue(const JsObject& value);
65
67 JS_API JsValue(JsObject&& value);
68
70 JS_API JsValue(const JsArray& value);
71
73 JS_API JsValue(JsArray&& value);
74
76 JS_API explicit JsValue(const char* value);
77
79 JS_API explicit JsValue(const std::string& value);
80
82 JS_API explicit JsValue(std::string&& value);
83
85 JS_API explicit JsValue(bool value);
86
88 JS_API explicit JsValue(int value);
89
91 JS_API explicit JsValue(int64_t value);
92
94 JS_API explicit JsValue(uint64_t value);
95
97 JS_API explicit JsValue(double value);
98
102 JS_API const JsObject& GetJsObject() const;
103
107 JS_API const JsArray& GetJsArray() const;
108
112 JS_API const std::string& GetString() const;
113
116 JS_API bool GetBool() const;
117
122 JS_API int GetInt() const;
123
127 JS_API int64_t GetInt64() const;
128
132 JS_API uint64_t GetUInt64() const;
133
136 JS_API double GetReal() const;
137
146 template <typename T,
147 typename ReturnType = typename std::conditional<
148 std::is_same<T, JsObject>::value ||
149 std::is_same<T, JsArray>::value ||
150 std::is_same<T, std::string>::value,
151 const T&, T>::type>
152 ReturnType Get() const {
153 return _Get(static_cast<T*>(nullptr));
154 }
155
162 template <typename T>
163 std::vector<T> GetArrayOf() const;
164
166 JS_API Type GetType() const;
167
169 JS_API std::string GetTypeName() const;
170
172 JS_API bool IsObject() const;
173
175 JS_API bool IsArray() const;
176
178 JS_API bool IsString() const;
179
181 JS_API bool IsBool() const;
182
184 JS_API bool IsInt() const;
185
187 JS_API bool IsReal() const;
188
190 JS_API bool IsUInt64() const;
191
194 template <typename T>
195 bool Is() const {
196 return _Is(static_cast<T*>(nullptr));
197 }
198
201 template <typename T>
202 bool IsArrayOf() const;
203
205 JS_API bool IsNull() const;
206
208 JS_API explicit operator bool() const;
209
212 JS_API bool operator==(const JsValue& other) const;
213
216 JS_API bool operator!=(const JsValue& other) const;
217
219 friend void swap(JsValue& lhs, JsValue& rhs) {
220 lhs._value.swap(rhs._value);
221 }
222
223private:
224 template <typename T>
225 struct _InvalidTypeHelper : public std::false_type { };
226
227 template <class T>
228 T _Get(T*) const {
229 static_assert(_InvalidTypeHelper<T>::value,
230 "Invalid type for JsValue");
231 return T();
232 }
233
234 const JsObject& _Get(JsObject*) const { return GetJsObject(); }
235 const JsArray& _Get(JsArray*) const { return GetJsArray(); }
236 const std::string& _Get(std::string*) const { return GetString(); }
237 bool _Get(bool*) const { return GetBool(); }
238 int _Get(int*) const { return GetInt(); }
239 int64_t _Get(int64_t*) const { return GetInt64(); }
240 uint64_t _Get(uint64_t*) const { return GetUInt64(); }
241 double _Get(double*) const { return GetReal(); }
242
243 template <class T>
244 bool _Is(T*) const {
245 static_assert(_InvalidTypeHelper<T>::value,
246 "Invalid type for JsValue");
247 return false;
248 }
249
250 bool _Is(JsObject*) const { return IsObject(); }
251 bool _Is(JsArray*) const { return IsArray(); }
252 bool _Is(std::string*) const { return IsString(); }
253 bool _Is(bool*) const { return IsBool(); }
254 bool _Is(int*) const { return IsInt(); }
255 bool _Is(int64_t*) const { return IsInt(); }
256 bool _Is(uint64_t*) const { return IsUInt64(); }
257 bool _Is(double*) const { return IsReal(); }
258
259 // Base class for types held indirectly.
260 //
261 // JsValue holds objects, arrays and strings indirectly. This serves two
262 // purposes. First, JsValue holds JsObject, which holds JsValues so
263 // indirection avoids needing JsValue to be complete while defining
264 // JsValue. Second, along with std::string, values of these types can be
265 // expensive to copy so they are reference counted instead.
266 //
267 // The template argument E is used to distinguish the holders in the
268 // JsValue's variant.
269 template <enum Type EnumValue>
270 struct _HolderBase
271 {
272 protected:
273 _HolderBase() = default;
274 ~_HolderBase() = default;
275
276 private:
277 friend void TfDelegatedCountIncrement(const _HolderBase *h) noexcept {
278 h->_refCount.fetch_add(1, std::memory_order_relaxed);
279 }
280
281 friend void TfDelegatedCountDecrement(const _HolderBase *h) noexcept {
282 const int rc = h->_refCount.fetch_sub(1, std::memory_order_release);
283 if (rc == 1) {
284 std::atomic_thread_fence(std::memory_order_acquire);
285 _Delete(h);
286 }
287 }
288
289 static JS_API void _Delete(const _HolderBase *) noexcept;
290
291 private:
292 mutable std::atomic<int> _refCount = 1;
293 };
294
295 template <typename> struct _Holder;
296 struct _IsValueEqualVisitor;
297
298 // A sentinel type held by default constructed JsValue objects, which
299 // corresponds to JSON 'null'.
300 struct _JsNull
301 {
302 bool operator==(const _JsNull& v) const {
303 return true;
304 }
305 bool operator!=(const _JsNull& v) const {
306 return false;
307 }
308 };
309
310 // The order these types are defined in the variant must match the
311 // order in which Type enumerators are defined. uint64_t is
312 // handled as a special case in the implementation.
313 using _Variant = std::variant<
317 bool, int64_t, double, _JsNull, uint64_t>;
318
319 _Variant _value;
320};
321
322template <typename T>
323inline std::vector<T> JsValue::GetArrayOf() const
324{
325 const JsArray& array = GetJsArray();
326 std::vector<T> result(array.size());
327 std::transform(array.begin(), array.end(), result.begin(),
328 [](const JsValue& v) { return v.Get<T>(); });
329 return result;
330}
331
332template <typename T>
333inline bool JsValue::IsArrayOf() const
334{
335 if (!IsArray()) {
336 return false;
337 }
338 const JsArray& array = GetJsArray();
339 return std::all_of(array.begin(), array.end(),
340 [](const JsValue& v) { return v.Is<T>(); });
341}
342
343PXR_NAMESPACE_CLOSE_SCOPE
344
345#endif // PXR_BASE_JS_VALUE_H
A discriminated union type for JSON values.
Definition: value.h:47
JS_API int64_t GetInt64() const
Returns the 64-bit integer held by this value.
JS_API JsValue(int64_t value)
Constructs a value holding a 64-bit signed integer.
Type
Type held by this JSON value.
Definition: value.h:50
JS_API JsValue(int value)
Constructs a value holding a signed integer.
JS_API JsValue(const JsObject &value)
Constructs a value holding the given object.
JS_API bool IsInt() const
Returns true if this value is holding an integer type.
JS_API JsValue(const std::string &value)
Constructs a value holding the given std::string.
ReturnType Get() const
Returns the value corresponding to the C++ type specified in the template parameter if it is holding ...
Definition: value.h:152
JS_API bool IsReal() const
Returns true if this value is holding a real type.
JS_API JsValue(const JsArray &value)
Constructs a value holding the given array.
JS_API const JsArray & GetJsArray() const
Returns the array held by this value.
JS_API JsValue(std::string &&value)
Constructs a value holding the given std::string rvalue reference.
JS_API bool IsUInt64() const
Returns true if this value is holding a 64-bit unsigned integer.
friend void swap(JsValue &lhs, JsValue &rhs)
Swap the value held by lhs with the value held by rhs.
Definition: value.h:219
JS_API bool IsObject() const
Returns true if this value is holding an object type.
JS_API Type GetType() const
Returns the type of this value.
JS_API std::string GetTypeName() const
Returns a display name for the type of this value.
JS_API double GetReal() const
Returns the double held by this value.
JS_API uint64_t GetUInt64() const
Returns the 64-bit unsigned integer held by this value.
JS_API bool operator!=(const JsValue &other) const
Returns true if values are of different type, or the underlying held values are not equal.
bool Is() const
Returns true if this value is holding a type that corresponds to the C++ type specified as the templa...
Definition: value.h:195
JS_API JsValue(uint64_t value)
Constructs a value holding a 64-bit unsigned integer.
std::vector< T > GetArrayOf() const
Returns a vector holding the elements of this value's array that correspond to the C++ type specified...
Definition: value.h:323
JS_API JsValue(double value)
Constructs a value holding a double.
JS_API JsValue(bool value)
Constructs a value holding a bool.
JS_API const JsObject & GetJsObject() const
Returns the object held by this value.
JS_API JsValue(JsArray &&value)
Constructs a value holding the given array rvalue reference.
JS_API JsValue(JsObject &&value)
Constructs a value holding the given object rvalue reference.
JS_API bool IsNull() const
Returns true if this value is null, false otherwise.
JS_API bool GetBool() const
Returns the bool held by this value.
JS_API bool operator==(const JsValue &other) const
Returns true of both values hold the same type and the underlying held values are equal.
JS_API JsValue(const char *value)
Constructs a value holding the given char array as a std::string.
JS_API bool IsBool() const
Returns true if this value is holding a boolean type.
JS_API const std::string & GetString() const
Returns the string held by this value.
bool IsArrayOf() const
Returns true if this value is holding an array whose elements all correspond to the C++ type specifie...
Definition: value.h:333
JS_API int GetInt() const
Returns the integer held by this value.
JS_API bool IsString() const
Returns true if this value is holding a string type.
JS_API JsValue()
Constructs a null value.
JS_API bool IsArray() const
Returns true if this value is holding an array type.
Stores a pointer to a ValueType which uses TfDelegatedCountIncrement and TfDelegatedCountDecrement to...