Bug 1462329 [wpt PR 10991] - Server-Timing: test TAO:* for cross-origin resource...
[gecko.git] / storage / Variant.h
blobfbb10afd9c0b83b55d5a00b3640458b61dae4207
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 "nsMemory.h"
14 #include "nsString.h"
15 #include "nsTArray.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 } \
23 /**
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)
35 namespace mozilla {
36 namespace storage {
38 ////////////////////////////////////////////////////////////////////////////////
39 //// Base Class
41 class Variant_base : public nsIVariant
43 public:
44 NS_DECL_THREADSAFE_ISUPPORTS
45 NS_DECL_NSIVARIANT
46 NS_DECLARE_STATIC_IID_ACCESSOR(VARIANT_BASE_IID)
48 protected:
49 virtual ~Variant_base() { }
52 NS_DEFINE_STATIC_IID_ACCESSOR(Variant_base,
53 VARIANT_BASE_IID)
55 ////////////////////////////////////////////////////////////////////////////////
56 //// Traits
58 /**
59 * Generics
62 template <typename DataType>
63 struct variant_traits
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)
75 *_storage = aData;
78 static inline void destroy(const StorageType& _storage)
79 { }
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 **)
112 { NO_CONVERSION }
115 #undef NO_CONVERSION
118 * INTEGER types
121 template < >
122 struct variant_traits<int64_t>
124 static inline uint16_t type() { return nsIDataType::VTYPE_INT64; }
126 template < >
127 struct variant_integer_traits<int64_t>
129 static inline nsresult asInt32(int64_t aValue,
130 int32_t *_result)
132 if (aValue > INT32_MAX || aValue < INT32_MIN)
133 return NS_ERROR_CANNOT_CONVERT_DATA;
135 *_result = static_cast<int32_t>(aValue);
136 return NS_OK;
138 static inline nsresult asInt64(int64_t aValue,
139 int64_t *_result)
141 *_result = aValue;
142 return NS_OK;
145 // xpcvariant just calls get double for integers...
146 template < >
147 struct variant_float_traits<int64_t>
149 static inline nsresult asDouble(int64_t aValue,
150 double *_result)
152 *_result = double(aValue);
153 return NS_OK;
158 * FLOAT types
161 template < >
162 struct variant_traits<double>
164 static inline uint16_t type() { return nsIDataType::VTYPE_DOUBLE; }
166 template < >
167 struct variant_float_traits<double>
169 static inline nsresult asDouble(double aValue,
170 double *_result)
172 *_result = aValue;
173 return NS_OK;
178 * TEXT types
181 template < >
182 struct variant_traits<nsString>
184 static inline uint16_t type() { return nsIDataType::VTYPE_ASTRING; }
186 template < >
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)
193 *_outData = aText;
195 static inline void destroy(const StorageType& _outData)
198 template < >
199 struct variant_text_traits<nsString>
201 static inline nsresult asUTF8String(const nsString &aValue,
202 nsACString &_result)
204 CopyUTF16toUTF8(aValue, _result);
205 return NS_OK;
207 static inline nsresult asString(const nsString &aValue,
208 nsAString &_result)
210 _result = aValue;
211 return NS_OK;
215 template < >
216 struct variant_traits<nsCString>
218 static inline uint16_t type() { return nsIDataType::VTYPE_UTF8STRING; }
220 template < >
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)
227 *_outData = aText;
229 static inline void destroy(const StorageType &aData)
232 template < >
233 struct variant_text_traits<nsCString>
235 static inline nsresult asUTF8String(const nsCString &aValue,
236 nsACString &_result)
238 _result = aValue;
239 return NS_OK;
241 static inline nsresult asString(const nsCString &aValue,
242 nsAString &_result)
244 CopyUTF8toUTF16(aValue, _result);
245 return NS_OK;
250 * BLOB types
253 template < >
254 struct variant_traits<uint8_t[]>
256 static inline uint16_t type() { return nsIDataType::VTYPE_ARRAY; }
258 template < >
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)
265 _outData->Clear();
266 (void)_outData->AppendElements(static_cast<const uint8_t *>(aBlob.first),
267 aBlob.second, fallible);
269 static inline void destroy(const StorageType& _outData)
272 template < >
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)
279 *_outData = aBlob;
281 static inline void destroy(StorageType &aData)
283 if (aData.first) {
284 free(aData.first);
285 aData.first = nullptr;
289 template < >
290 struct variant_blob_traits<uint8_t[], false>
292 static inline nsresult asArray(FallibleTArray<uint8_t> &aData,
293 uint16_t *_type,
294 uint32_t *_size,
295 void **_result)
297 // For empty blobs, we return nullptr.
298 if (aData.Length() == 0) {
299 *_result = nullptr;
300 *_type = nsIDataType::VTYPE_UINT8;
301 *_size = 0;
302 return NS_OK;
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);
309 // Set type and size
310 *_type = nsIDataType::VTYPE_UINT8;
311 *_size = aData.Length();
312 return NS_OK;
316 template < >
317 struct variant_blob_traits<uint8_t[], true>
319 static inline nsresult asArray(std::pair<uint8_t *, int> &aData,
320 uint16_t *_type,
321 uint32_t *_size,
322 void **_result)
324 // For empty blobs, we return nullptr.
325 if (aData.second == 0) {
326 *_result = nullptr;
327 *_type = nsIDataType::VTYPE_UINT8;
328 *_size = 0;
329 return NS_OK;
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!
337 // Set type and size
338 *_type = nsIDataType::VTYPE_UINT8;
339 *_size = aData.second;
340 return NS_OK;
345 * nullptr type
348 class NullVariant : public Variant_base
350 public:
351 NS_IMETHOD GetDataType(uint16_t *_type) override
353 NS_ENSURE_ARG_POINTER(_type);
354 *_type = nsIDataType::VTYPE_EMPTY;
355 return NS_OK;
358 NS_IMETHOD GetAsAUTF8String(nsACString &_str) override
360 // Return a void string.
361 _str.SetIsVoid(true);
362 return NS_OK;
365 NS_IMETHOD GetAsAString(nsAString &_str) override
367 // Return a void string.
368 _str.SetIsVoid(true);
369 return NS_OK;
373 ////////////////////////////////////////////////////////////////////////////////
374 //// Template Implementation
376 template <typename DataType, bool Adopting=false>
377 class Variant final : public Variant_base
379 ~Variant()
381 variant_storage_traits<DataType, Adopting>::destroy(mData);
384 public:
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();
393 return NS_OK;
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,
421 nsIID *,
422 uint32_t *_size,
423 void **_data) override
425 return variant_blob_traits<DataType, Adopting>::asArray(mData, _type, _size, _data);
428 private:
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__