1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_storage_Variant_h__
8 #define mozilla_storage_Variant_h__
12 #include "nsIVariant.h"
17 #define VARIANT_BASE_IID \
18 { /* 78888042-0fa3-4f7a-8b19-7996f99bf1aa */ \
19 0x78888042, 0x0fa3, 0x4f7a, \
20 { 0x8b, 0x19, 0x79, 0x96, 0xf9, 0x9b, 0xf1, 0xaa } \
24 * This class is used by the storage module whenever an nsIVariant needs to be
25 * returned. We provide traits for the basic sqlite types to make use easier.
26 * The following types map to the indicated sqlite type:
27 * int64_t -> INTEGER (use IntegerVariant)
28 * double -> FLOAT (use FloatVariant)
29 * nsString -> TEXT (use TextVariant)
30 * nsCString -> TEXT (use UTF8TextVariant)
31 * uint8_t[] -> BLOB (use BlobVariant)
32 * nullptr -> NULL (use NullVariant)
38 ////////////////////////////////////////////////////////////////////////////////
41 class Variant_base
: public nsIVariant
44 NS_DECL_THREADSAFE_ISUPPORTS
46 NS_DECLARE_STATIC_IID_ACCESSOR(VARIANT_BASE_IID
)
49 virtual ~Variant_base() { }
52 NS_DEFINE_STATIC_IID_ACCESSOR(Variant_base
,
55 ////////////////////////////////////////////////////////////////////////////////
62 template <typename DataType
>
65 static inline uint16_t type() { return nsIDataType::VTYPE_EMPTY
; }
68 template <typename DataType
, bool Adopting
=false>
69 struct variant_storage_traits
71 typedef DataType ConstructorType
;
72 typedef DataType StorageType
;
73 static inline void storage_conversion(const ConstructorType aData
, StorageType
* _storage
)
78 static inline void destroy(const StorageType
& _storage
)
82 #define NO_CONVERSION return NS_ERROR_CANNOT_CONVERT_DATA;
84 template <typename DataType
, bool Adopting
=false>
85 struct variant_integer_traits
87 typedef typename variant_storage_traits
<DataType
, Adopting
>::StorageType StorageType
;
88 static inline nsresult
asInt32(const StorageType
&, int32_t *) { NO_CONVERSION
}
89 static inline nsresult
asInt64(const StorageType
&, int64_t *) { NO_CONVERSION
}
92 template <typename DataType
, bool Adopting
=false>
93 struct variant_float_traits
95 typedef typename variant_storage_traits
<DataType
, Adopting
>::StorageType StorageType
;
96 static inline nsresult
asDouble(const StorageType
&, double *) { NO_CONVERSION
}
99 template <typename DataType
, bool Adopting
=false>
100 struct variant_text_traits
102 typedef typename variant_storage_traits
<DataType
, Adopting
>::StorageType StorageType
;
103 static inline nsresult
asUTF8String(const StorageType
&, nsACString
&) { NO_CONVERSION
}
104 static inline nsresult
asString(const StorageType
&, nsAString
&) { NO_CONVERSION
}
107 template <typename DataType
, bool Adopting
=false>
108 struct variant_blob_traits
110 typedef typename variant_storage_traits
<DataType
, Adopting
>::StorageType StorageType
;
111 static inline nsresult
asArray(const StorageType
&, uint16_t *, uint32_t *, void **)
122 struct variant_traits
<int64_t>
124 static inline uint16_t type() { return nsIDataType::VTYPE_INT64
; }
127 struct variant_integer_traits
<int64_t>
129 static inline nsresult
asInt32(int64_t aValue
,
132 if (aValue
> INT32_MAX
|| aValue
< INT32_MIN
)
133 return NS_ERROR_CANNOT_CONVERT_DATA
;
135 *_result
= static_cast<int32_t>(aValue
);
138 static inline nsresult
asInt64(int64_t aValue
,
145 // xpcvariant just calls get double for integers...
147 struct variant_float_traits
<int64_t>
149 static inline nsresult
asDouble(int64_t aValue
,
152 *_result
= double(aValue
);
162 struct variant_traits
<double>
164 static inline uint16_t type() { return nsIDataType::VTYPE_DOUBLE
; }
167 struct variant_float_traits
<double>
169 static inline nsresult
asDouble(double aValue
,
182 struct variant_traits
<nsString
>
184 static inline uint16_t type() { return nsIDataType::VTYPE_ASTRING
; }
187 struct variant_storage_traits
<nsString
>
189 typedef const nsAString
& ConstructorType
;
190 typedef nsString StorageType
;
191 static inline void storage_conversion(ConstructorType aText
, StorageType
* _outData
)
195 static inline void destroy(const StorageType
& _outData
)
199 struct variant_text_traits
<nsString
>
201 static inline nsresult
asUTF8String(const nsString
&aValue
,
204 CopyUTF16toUTF8(aValue
, _result
);
207 static inline nsresult
asString(const nsString
&aValue
,
216 struct variant_traits
<nsCString
>
218 static inline uint16_t type() { return nsIDataType::VTYPE_UTF8STRING
; }
221 struct variant_storage_traits
<nsCString
>
223 typedef const nsACString
& ConstructorType
;
224 typedef nsCString StorageType
;
225 static inline void storage_conversion(ConstructorType aText
, StorageType
* _outData
)
229 static inline void destroy(const StorageType
&aData
)
233 struct variant_text_traits
<nsCString
>
235 static inline nsresult
asUTF8String(const nsCString
&aValue
,
241 static inline nsresult
asString(const nsCString
&aValue
,
244 CopyUTF8toUTF16(aValue
, _result
);
254 struct variant_traits
<uint8_t[]>
256 static inline uint16_t type() { return nsIDataType::VTYPE_ARRAY
; }
259 struct variant_storage_traits
<uint8_t[], false>
261 typedef std::pair
<const void *, int> ConstructorType
;
262 typedef FallibleTArray
<uint8_t> StorageType
;
263 static inline void storage_conversion(ConstructorType aBlob
, StorageType
* _outData
)
266 (void)_outData
->AppendElements(static_cast<const uint8_t *>(aBlob
.first
),
267 aBlob
.second
, fallible
);
269 static inline void destroy(const StorageType
& _outData
)
273 struct variant_storage_traits
<uint8_t[], true>
275 typedef std::pair
<uint8_t *, int> ConstructorType
;
276 typedef std::pair
<uint8_t *, int> StorageType
;
277 static inline void storage_conversion(ConstructorType aBlob
, StorageType
* _outData
)
281 static inline void destroy(StorageType
&aData
)
285 aData
.first
= nullptr;
290 struct variant_blob_traits
<uint8_t[], false>
292 static inline nsresult
asArray(FallibleTArray
<uint8_t> &aData
,
297 // For empty blobs, we return nullptr.
298 if (aData
.Length() == 0) {
300 *_type
= nsIDataType::VTYPE_UINT8
;
305 // Otherwise, we copy the array.
306 *_result
= nsMemory::Clone(aData
.Elements(), aData
.Length() * sizeof(uint8_t));
307 NS_ENSURE_TRUE(*_result
, NS_ERROR_OUT_OF_MEMORY
);
310 *_type
= nsIDataType::VTYPE_UINT8
;
311 *_size
= aData
.Length();
317 struct variant_blob_traits
<uint8_t[], true>
319 static inline nsresult
asArray(std::pair
<uint8_t *, int> &aData
,
324 // For empty blobs, we return nullptr.
325 if (aData
.second
== 0) {
327 *_type
= nsIDataType::VTYPE_UINT8
;
332 // Otherwise, transfer the data out.
333 *_result
= aData
.first
;
334 aData
.first
= nullptr;
335 MOZ_ASSERT(*_result
); // We asked for it twice, better not use adopting!
338 *_type
= nsIDataType::VTYPE_UINT8
;
339 *_size
= aData
.second
;
348 class NullVariant
: public Variant_base
351 NS_IMETHOD
GetDataType(uint16_t *_type
) override
353 NS_ENSURE_ARG_POINTER(_type
);
354 *_type
= nsIDataType::VTYPE_EMPTY
;
358 NS_IMETHOD
GetAsAUTF8String(nsACString
&_str
) override
360 // Return a void string.
361 _str
.SetIsVoid(true);
365 NS_IMETHOD
GetAsAString(nsAString
&_str
) override
367 // Return a void string.
368 _str
.SetIsVoid(true);
373 ////////////////////////////////////////////////////////////////////////////////
374 //// Template Implementation
376 template <typename DataType
, bool Adopting
=false>
377 class Variant final
: public Variant_base
381 variant_storage_traits
<DataType
, Adopting
>::destroy(mData
);
385 explicit Variant(const typename variant_storage_traits
<DataType
, Adopting
>::ConstructorType aData
)
387 variant_storage_traits
<DataType
, Adopting
>::storage_conversion(aData
, &mData
);
390 NS_IMETHOD
GetDataType(uint16_t *_type
) override
392 *_type
= variant_traits
<DataType
>::type();
395 NS_IMETHOD
GetAsInt32(int32_t *_integer
) override
397 return variant_integer_traits
<DataType
, Adopting
>::asInt32(mData
, _integer
);
400 NS_IMETHOD
GetAsInt64(int64_t *_integer
) override
402 return variant_integer_traits
<DataType
, Adopting
>::asInt64(mData
, _integer
);
405 NS_IMETHOD
GetAsDouble(double *_double
) override
407 return variant_float_traits
<DataType
, Adopting
>::asDouble(mData
, _double
);
410 NS_IMETHOD
GetAsAUTF8String(nsACString
&_str
) override
412 return variant_text_traits
<DataType
, Adopting
>::asUTF8String(mData
, _str
);
415 NS_IMETHOD
GetAsAString(nsAString
&_str
) override
417 return variant_text_traits
<DataType
, Adopting
>::asString(mData
, _str
);
420 NS_IMETHOD
GetAsArray(uint16_t *_type
,
423 void **_data
) override
425 return variant_blob_traits
<DataType
, Adopting
>::asArray(mData
, _type
, _size
, _data
);
429 typename variant_storage_traits
<DataType
, Adopting
>::StorageType mData
;
432 ////////////////////////////////////////////////////////////////////////////////
433 //// Handy typedefs! Use these for the right mapping.
435 typedef Variant
<int64_t> IntegerVariant
;
436 typedef Variant
<double> FloatVariant
;
437 typedef Variant
<nsString
> TextVariant
;
438 typedef Variant
<nsCString
> UTF8TextVariant
;
439 typedef Variant
<uint8_t[], false> BlobVariant
;
440 typedef Variant
<uint8_t[], true> AdoptedBlobVariant
;
442 } // namespace storage
443 } // namespace mozilla
445 #include "Variant_inl.h"
447 #endif // mozilla_storage_Variant_h__