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 * This class is used by the storage module whenever an nsIVariant needs to be
18 * returned. We provide traits for the basic sqlite types to make use easier.
19 * The following types map to the indicated sqlite type:
20 * int64_t -> INTEGER (use IntegerVariant)
21 * double -> FLOAT (use FloatVariant)
22 * nsString -> TEXT (use TextVariant)
23 * nsCString -> TEXT (use UTF8TextVariant)
24 * uint8_t[] -> BLOB (use BlobVariant)
25 * nullptr -> NULL (use NullVariant)
31 ////////////////////////////////////////////////////////////////////////////////
34 class Variant_base
: public nsIVariant
37 NS_DECL_THREADSAFE_ISUPPORTS
41 virtual ~Variant_base() { }
44 ////////////////////////////////////////////////////////////////////////////////
51 template <typename DataType
>
54 static inline uint16_t type() { return nsIDataType::VTYPE_EMPTY
; }
57 template <typename DataType
, bool Adopting
=false>
58 struct variant_storage_traits
60 typedef DataType ConstructorType
;
61 typedef DataType StorageType
;
62 static inline void storage_conversion(const ConstructorType aData
, StorageType
* _storage
)
67 static inline void destroy(const StorageType
& _storage
)
71 #define NO_CONVERSION return NS_ERROR_CANNOT_CONVERT_DATA;
73 template <typename DataType
, bool Adopting
=false>
74 struct variant_integer_traits
76 typedef typename variant_storage_traits
<DataType
, Adopting
>::StorageType StorageType
;
77 static inline nsresult
asInt32(const StorageType
&, int32_t *) { NO_CONVERSION
}
78 static inline nsresult
asInt64(const StorageType
&, int64_t *) { NO_CONVERSION
}
81 template <typename DataType
, bool Adopting
=false>
82 struct variant_float_traits
84 typedef typename variant_storage_traits
<DataType
, Adopting
>::StorageType StorageType
;
85 static inline nsresult
asDouble(const StorageType
&, double *) { NO_CONVERSION
}
88 template <typename DataType
, bool Adopting
=false>
89 struct variant_text_traits
91 typedef typename variant_storage_traits
<DataType
, Adopting
>::StorageType StorageType
;
92 static inline nsresult
asUTF8String(const StorageType
&, nsACString
&) { NO_CONVERSION
}
93 static inline nsresult
asString(const StorageType
&, nsAString
&) { NO_CONVERSION
}
96 template <typename DataType
, bool Adopting
=false>
97 struct variant_blob_traits
99 typedef typename variant_storage_traits
<DataType
, Adopting
>::StorageType StorageType
;
100 static inline nsresult
asArray(const StorageType
&, uint16_t *, uint32_t *, void **)
111 struct variant_traits
<int64_t>
113 static inline uint16_t type() { return nsIDataType::VTYPE_INT64
; }
116 struct variant_integer_traits
<int64_t>
118 static inline nsresult
asInt32(int64_t aValue
,
121 if (aValue
> INT32_MAX
|| aValue
< INT32_MIN
)
122 return NS_ERROR_CANNOT_CONVERT_DATA
;
124 *_result
= static_cast<int32_t>(aValue
);
127 static inline nsresult
asInt64(int64_t aValue
,
134 // xpcvariant just calls get double for integers...
136 struct variant_float_traits
<int64_t>
138 static inline nsresult
asDouble(int64_t aValue
,
141 *_result
= double(aValue
);
151 struct variant_traits
<double>
153 static inline uint16_t type() { return nsIDataType::VTYPE_DOUBLE
; }
156 struct variant_float_traits
<double>
158 static inline nsresult
asDouble(double aValue
,
171 struct variant_traits
<nsString
>
173 static inline uint16_t type() { return nsIDataType::VTYPE_ASTRING
; }
176 struct variant_storage_traits
<nsString
>
178 typedef const nsAString
& ConstructorType
;
179 typedef nsString StorageType
;
180 static inline void storage_conversion(ConstructorType aText
, StorageType
* _outData
)
184 static inline void destroy(const StorageType
& _outData
)
188 struct variant_text_traits
<nsString
>
190 static inline nsresult
asUTF8String(const nsString
&aValue
,
193 CopyUTF16toUTF8(aValue
, _result
);
196 static inline nsresult
asString(const nsString
&aValue
,
205 struct variant_traits
<nsCString
>
207 static inline uint16_t type() { return nsIDataType::VTYPE_UTF8STRING
; }
210 struct variant_storage_traits
<nsCString
>
212 typedef const nsACString
& ConstructorType
;
213 typedef nsCString StorageType
;
214 static inline void storage_conversion(ConstructorType aText
, StorageType
* _outData
)
218 static inline void destroy(const StorageType
&aData
)
222 struct variant_text_traits
<nsCString
>
224 static inline nsresult
asUTF8String(const nsCString
&aValue
,
230 static inline nsresult
asString(const nsCString
&aValue
,
233 CopyUTF8toUTF16(aValue
, _result
);
243 struct variant_traits
<uint8_t[]>
245 static inline uint16_t type() { return nsIDataType::VTYPE_ARRAY
; }
248 struct variant_storage_traits
<uint8_t[], false>
250 typedef std::pair
<const void *, int> ConstructorType
;
251 typedef FallibleTArray
<uint8_t> StorageType
;
252 static inline void storage_conversion(ConstructorType aBlob
, StorageType
* _outData
)
255 _outData
->SetCapacity(aBlob
.second
);
256 (void)_outData
->AppendElements(static_cast<const uint8_t *>(aBlob
.first
),
259 static inline void destroy(const StorageType
& _outData
)
263 struct variant_storage_traits
<uint8_t[], true>
265 typedef std::pair
<uint8_t *, int> ConstructorType
;
266 typedef std::pair
<uint8_t *, int> StorageType
;
267 static inline void storage_conversion(ConstructorType aBlob
, StorageType
* _outData
)
271 static inline void destroy(StorageType
&aData
)
274 NS_Free(aData
.first
);
275 aData
.first
= nullptr;
280 struct variant_blob_traits
<uint8_t[], false>
282 static inline nsresult
asArray(FallibleTArray
<uint8_t> &aData
,
287 // For empty blobs, we return nullptr.
288 if (aData
.Length() == 0) {
290 *_type
= nsIDataType::VTYPE_UINT8
;
295 // Otherwise, we copy the array.
296 *_result
= nsMemory::Clone(aData
.Elements(), aData
.Length() * sizeof(uint8_t));
297 NS_ENSURE_TRUE(*_result
, NS_ERROR_OUT_OF_MEMORY
);
300 *_type
= nsIDataType::VTYPE_UINT8
;
301 *_size
= aData
.Length();
307 struct variant_blob_traits
<uint8_t[], true>
309 static inline nsresult
asArray(std::pair
<uint8_t *, int> &aData
,
314 // For empty blobs, we return nullptr.
315 if (aData
.second
== 0) {
317 *_type
= nsIDataType::VTYPE_UINT8
;
322 // Otherwise, transfer the data out.
323 *_result
= aData
.first
;
324 aData
.first
= nullptr;
325 MOZ_ASSERT(*_result
); // We asked for it twice, better not use adopting!
328 *_type
= nsIDataType::VTYPE_UINT8
;
329 *_size
= aData
.second
;
338 class NullVariant
: public Variant_base
341 NS_IMETHOD
GetDataType(uint16_t *_type
)
343 NS_ENSURE_ARG_POINTER(_type
);
344 *_type
= nsIDataType::VTYPE_EMPTY
;
348 NS_IMETHOD
GetAsAUTF8String(nsACString
&_str
)
350 // Return a void string.
352 _str
.SetIsVoid(true);
356 NS_IMETHOD
GetAsAString(nsAString
&_str
)
358 // Return a void string.
360 _str
.SetIsVoid(true);
365 ////////////////////////////////////////////////////////////////////////////////
366 //// Template Implementation
368 template <typename DataType
, bool Adopting
=false>
369 class Variant
: public Variant_base
373 variant_storage_traits
<DataType
, Adopting
>::destroy(mData
);
377 explicit Variant(const typename variant_storage_traits
<DataType
, Adopting
>::ConstructorType aData
)
379 variant_storage_traits
<DataType
, Adopting
>::storage_conversion(aData
, &mData
);
382 NS_IMETHOD
GetDataType(uint16_t *_type
)
384 *_type
= variant_traits
<DataType
>::type();
387 NS_IMETHOD
GetAsInt32(int32_t *_integer
)
389 return variant_integer_traits
<DataType
, Adopting
>::asInt32(mData
, _integer
);
392 NS_IMETHOD
GetAsInt64(int64_t *_integer
)
394 return variant_integer_traits
<DataType
, Adopting
>::asInt64(mData
, _integer
);
397 NS_IMETHOD
GetAsDouble(double *_double
)
399 return variant_float_traits
<DataType
, Adopting
>::asDouble(mData
, _double
);
402 NS_IMETHOD
GetAsAUTF8String(nsACString
&_str
)
404 return variant_text_traits
<DataType
, Adopting
>::asUTF8String(mData
, _str
);
407 NS_IMETHOD
GetAsAString(nsAString
&_str
)
409 return variant_text_traits
<DataType
, Adopting
>::asString(mData
, _str
);
412 NS_IMETHOD
GetAsArray(uint16_t *_type
,
417 return variant_blob_traits
<DataType
, Adopting
>::asArray(mData
, _type
, _size
, _data
);
421 typename variant_storage_traits
<DataType
, Adopting
>::StorageType mData
;
424 ////////////////////////////////////////////////////////////////////////////////
425 //// Handy typedefs! Use these for the right mapping.
427 typedef Variant
<int64_t> IntegerVariant
;
428 typedef Variant
<double> FloatVariant
;
429 typedef Variant
<nsString
> TextVariant
;
430 typedef Variant
<nsCString
> UTF8TextVariant
;
431 typedef Variant
<uint8_t[], false> BlobVariant
;
432 typedef Variant
<uint8_t[], true> AdoptedBlobVariant
;
434 } // namespace storage
435 } // namespace mozilla
437 #include "Variant_inl.h"
439 #endif // mozilla_storage_Variant_h__