Bug 1104435 part 2 - Make AnimationPlayer derive from nsISupports; r=smaug
[gecko.git] / storage / src / Variant.h
blob298825e727d15e6e4c965ae07a29f628280c7577
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__
10 #include <utility>
12 #include "nsIVariant.h"
13 #include "nsString.h"
14 #include "nsTArray.h"
16 /**
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)
28 namespace mozilla {
29 namespace storage {
31 ////////////////////////////////////////////////////////////////////////////////
32 //// Base Class
34 class Variant_base : public nsIVariant
36 public:
37 NS_DECL_THREADSAFE_ISUPPORTS
38 NS_DECL_NSIVARIANT
40 protected:
41 virtual ~Variant_base() { }
44 ////////////////////////////////////////////////////////////////////////////////
45 //// Traits
47 /**
48 * Generics
51 template <typename DataType>
52 struct variant_traits
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)
64 *_storage = aData;
67 static inline void destroy(const StorageType& _storage)
68 { }
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 **)
101 { NO_CONVERSION }
104 #undef NO_CONVERSION
107 * INTEGER types
110 template < >
111 struct variant_traits<int64_t>
113 static inline uint16_t type() { return nsIDataType::VTYPE_INT64; }
115 template < >
116 struct variant_integer_traits<int64_t>
118 static inline nsresult asInt32(int64_t aValue,
119 int32_t *_result)
121 if (aValue > INT32_MAX || aValue < INT32_MIN)
122 return NS_ERROR_CANNOT_CONVERT_DATA;
124 *_result = static_cast<int32_t>(aValue);
125 return NS_OK;
127 static inline nsresult asInt64(int64_t aValue,
128 int64_t *_result)
130 *_result = aValue;
131 return NS_OK;
134 // xpcvariant just calls get double for integers...
135 template < >
136 struct variant_float_traits<int64_t>
138 static inline nsresult asDouble(int64_t aValue,
139 double *_result)
141 *_result = double(aValue);
142 return NS_OK;
147 * FLOAT types
150 template < >
151 struct variant_traits<double>
153 static inline uint16_t type() { return nsIDataType::VTYPE_DOUBLE; }
155 template < >
156 struct variant_float_traits<double>
158 static inline nsresult asDouble(double aValue,
159 double *_result)
161 *_result = aValue;
162 return NS_OK;
167 * TEXT types
170 template < >
171 struct variant_traits<nsString>
173 static inline uint16_t type() { return nsIDataType::VTYPE_ASTRING; }
175 template < >
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)
182 *_outData = aText;
184 static inline void destroy(const StorageType& _outData)
187 template < >
188 struct variant_text_traits<nsString>
190 static inline nsresult asUTF8String(const nsString &aValue,
191 nsACString &_result)
193 CopyUTF16toUTF8(aValue, _result);
194 return NS_OK;
196 static inline nsresult asString(const nsString &aValue,
197 nsAString &_result)
199 _result = aValue;
200 return NS_OK;
204 template < >
205 struct variant_traits<nsCString>
207 static inline uint16_t type() { return nsIDataType::VTYPE_UTF8STRING; }
209 template < >
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)
216 *_outData = aText;
218 static inline void destroy(const StorageType &aData)
221 template < >
222 struct variant_text_traits<nsCString>
224 static inline nsresult asUTF8String(const nsCString &aValue,
225 nsACString &_result)
227 _result = aValue;
228 return NS_OK;
230 static inline nsresult asString(const nsCString &aValue,
231 nsAString &_result)
233 CopyUTF8toUTF16(aValue, _result);
234 return NS_OK;
239 * BLOB types
242 template < >
243 struct variant_traits<uint8_t[]>
245 static inline uint16_t type() { return nsIDataType::VTYPE_ARRAY; }
247 template < >
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)
254 _outData->Clear();
255 _outData->SetCapacity(aBlob.second);
256 (void)_outData->AppendElements(static_cast<const uint8_t *>(aBlob.first),
257 aBlob.second);
259 static inline void destroy(const StorageType& _outData)
262 template < >
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)
269 *_outData = aBlob;
271 static inline void destroy(StorageType &aData)
273 if (aData.first) {
274 NS_Free(aData.first);
275 aData.first = nullptr;
279 template < >
280 struct variant_blob_traits<uint8_t[], false>
282 static inline nsresult asArray(FallibleTArray<uint8_t> &aData,
283 uint16_t *_type,
284 uint32_t *_size,
285 void **_result)
287 // For empty blobs, we return nullptr.
288 if (aData.Length() == 0) {
289 *_result = nullptr;
290 *_type = nsIDataType::VTYPE_UINT8;
291 *_size = 0;
292 return NS_OK;
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);
299 // Set type and size
300 *_type = nsIDataType::VTYPE_UINT8;
301 *_size = aData.Length();
302 return NS_OK;
306 template < >
307 struct variant_blob_traits<uint8_t[], true>
309 static inline nsresult asArray(std::pair<uint8_t *, int> &aData,
310 uint16_t *_type,
311 uint32_t *_size,
312 void **_result)
314 // For empty blobs, we return nullptr.
315 if (aData.second == 0) {
316 *_result = nullptr;
317 *_type = nsIDataType::VTYPE_UINT8;
318 *_size = 0;
319 return NS_OK;
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!
327 // Set type and size
328 *_type = nsIDataType::VTYPE_UINT8;
329 *_size = aData.second;
330 return NS_OK;
335 * nullptr type
338 class NullVariant : public Variant_base
340 public:
341 NS_IMETHOD GetDataType(uint16_t *_type)
343 NS_ENSURE_ARG_POINTER(_type);
344 *_type = nsIDataType::VTYPE_EMPTY;
345 return NS_OK;
348 NS_IMETHOD GetAsAUTF8String(nsACString &_str)
350 // Return a void string.
351 _str.Truncate(0);
352 _str.SetIsVoid(true);
353 return NS_OK;
356 NS_IMETHOD GetAsAString(nsAString &_str)
358 // Return a void string.
359 _str.Truncate(0);
360 _str.SetIsVoid(true);
361 return NS_OK;
365 ////////////////////////////////////////////////////////////////////////////////
366 //// Template Implementation
368 template <typename DataType, bool Adopting=false>
369 class Variant : public Variant_base
371 ~Variant()
373 variant_storage_traits<DataType, Adopting>::destroy(mData);
376 public:
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();
385 return NS_OK;
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,
413 nsIID *,
414 uint32_t *_size,
415 void **_data)
417 return variant_blob_traits<DataType, Adopting>::asArray(mData, _type, _size, _data);
420 private:
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__