storage/src/Variant.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef mozilla_storage_Variant_h__
michael@0 8 #define mozilla_storage_Variant_h__
michael@0 9
michael@0 10 #include <utility>
michael@0 11
michael@0 12 #include "nsIVariant.h"
michael@0 13 #include "nsString.h"
michael@0 14 #include "nsTArray.h"
michael@0 15
michael@0 16 /**
michael@0 17 * This class is used by the storage module whenever an nsIVariant needs to be
michael@0 18 * returned. We provide traits for the basic sqlite types to make use easier.
michael@0 19 * The following types map to the indicated sqlite type:
michael@0 20 * int64_t -> INTEGER (use IntegerVariant)
michael@0 21 * double -> FLOAT (use FloatVariant)
michael@0 22 * nsString -> TEXT (use TextVariant)
michael@0 23 * nsCString -> TEXT (use UTF8TextVariant)
michael@0 24 * uint8_t[] -> BLOB (use BlobVariant)
michael@0 25 * nullptr -> NULL (use NullVariant)
michael@0 26 */
michael@0 27
michael@0 28 namespace mozilla {
michael@0 29 namespace storage {
michael@0 30
michael@0 31 ////////////////////////////////////////////////////////////////////////////////
michael@0 32 //// Base Class
michael@0 33
michael@0 34 class Variant_base : public nsIVariant
michael@0 35 {
michael@0 36 public:
michael@0 37 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 38 NS_DECL_NSIVARIANT
michael@0 39
michael@0 40 protected:
michael@0 41 virtual ~Variant_base() { }
michael@0 42 };
michael@0 43
michael@0 44 ////////////////////////////////////////////////////////////////////////////////
michael@0 45 //// Traits
michael@0 46
michael@0 47 /**
michael@0 48 * Generics
michael@0 49 */
michael@0 50
michael@0 51 template <typename DataType>
michael@0 52 struct variant_traits
michael@0 53 {
michael@0 54 static inline uint16_t type() { return nsIDataType::VTYPE_EMPTY; }
michael@0 55 };
michael@0 56
michael@0 57 template <typename DataType, bool Adopting=false>
michael@0 58 struct variant_storage_traits
michael@0 59 {
michael@0 60 typedef DataType ConstructorType;
michael@0 61 typedef DataType StorageType;
michael@0 62 static inline void storage_conversion(const ConstructorType aData, StorageType* _storage)
michael@0 63 {
michael@0 64 *_storage = aData;
michael@0 65 }
michael@0 66
michael@0 67 static inline void destroy(const StorageType& _storage)
michael@0 68 { }
michael@0 69 };
michael@0 70
michael@0 71 #define NO_CONVERSION return NS_ERROR_CANNOT_CONVERT_DATA;
michael@0 72
michael@0 73 template <typename DataType, bool Adopting=false>
michael@0 74 struct variant_integer_traits
michael@0 75 {
michael@0 76 typedef typename variant_storage_traits<DataType, Adopting>::StorageType StorageType;
michael@0 77 static inline nsresult asInt32(const StorageType &, int32_t *) { NO_CONVERSION }
michael@0 78 static inline nsresult asInt64(const StorageType &, int64_t *) { NO_CONVERSION }
michael@0 79 };
michael@0 80
michael@0 81 template <typename DataType, bool Adopting=false>
michael@0 82 struct variant_float_traits
michael@0 83 {
michael@0 84 typedef typename variant_storage_traits<DataType, Adopting>::StorageType StorageType;
michael@0 85 static inline nsresult asDouble(const StorageType &, double *) { NO_CONVERSION }
michael@0 86 };
michael@0 87
michael@0 88 template <typename DataType, bool Adopting=false>
michael@0 89 struct variant_text_traits
michael@0 90 {
michael@0 91 typedef typename variant_storage_traits<DataType, Adopting>::StorageType StorageType;
michael@0 92 static inline nsresult asUTF8String(const StorageType &, nsACString &) { NO_CONVERSION }
michael@0 93 static inline nsresult asString(const StorageType &, nsAString &) { NO_CONVERSION }
michael@0 94 };
michael@0 95
michael@0 96 template <typename DataType, bool Adopting=false>
michael@0 97 struct variant_blob_traits
michael@0 98 {
michael@0 99 typedef typename variant_storage_traits<DataType, Adopting>::StorageType StorageType;
michael@0 100 static inline nsresult asArray(const StorageType &, uint16_t *, uint32_t *, void **)
michael@0 101 { NO_CONVERSION }
michael@0 102 };
michael@0 103
michael@0 104 #undef NO_CONVERSION
michael@0 105
michael@0 106 /**
michael@0 107 * INTEGER types
michael@0 108 */
michael@0 109
michael@0 110 template < >
michael@0 111 struct variant_traits<int64_t>
michael@0 112 {
michael@0 113 static inline uint16_t type() { return nsIDataType::VTYPE_INT64; }
michael@0 114 };
michael@0 115 template < >
michael@0 116 struct variant_integer_traits<int64_t>
michael@0 117 {
michael@0 118 static inline nsresult asInt32(int64_t aValue,
michael@0 119 int32_t *_result)
michael@0 120 {
michael@0 121 if (aValue > INT32_MAX || aValue < INT32_MIN)
michael@0 122 return NS_ERROR_CANNOT_CONVERT_DATA;
michael@0 123
michael@0 124 *_result = static_cast<int32_t>(aValue);
michael@0 125 return NS_OK;
michael@0 126 }
michael@0 127 static inline nsresult asInt64(int64_t aValue,
michael@0 128 int64_t *_result)
michael@0 129 {
michael@0 130 *_result = aValue;
michael@0 131 return NS_OK;
michael@0 132 }
michael@0 133 };
michael@0 134 // xpcvariant just calls get double for integers...
michael@0 135 template < >
michael@0 136 struct variant_float_traits<int64_t>
michael@0 137 {
michael@0 138 static inline nsresult asDouble(int64_t aValue,
michael@0 139 double *_result)
michael@0 140 {
michael@0 141 *_result = double(aValue);
michael@0 142 return NS_OK;
michael@0 143 }
michael@0 144 };
michael@0 145
michael@0 146 /**
michael@0 147 * FLOAT types
michael@0 148 */
michael@0 149
michael@0 150 template < >
michael@0 151 struct variant_traits<double>
michael@0 152 {
michael@0 153 static inline uint16_t type() { return nsIDataType::VTYPE_DOUBLE; }
michael@0 154 };
michael@0 155 template < >
michael@0 156 struct variant_float_traits<double>
michael@0 157 {
michael@0 158 static inline nsresult asDouble(double aValue,
michael@0 159 double *_result)
michael@0 160 {
michael@0 161 *_result = aValue;
michael@0 162 return NS_OK;
michael@0 163 }
michael@0 164 };
michael@0 165
michael@0 166 /**
michael@0 167 * TEXT types
michael@0 168 */
michael@0 169
michael@0 170 template < >
michael@0 171 struct variant_traits<nsString>
michael@0 172 {
michael@0 173 static inline uint16_t type() { return nsIDataType::VTYPE_ASTRING; }
michael@0 174 };
michael@0 175 template < >
michael@0 176 struct variant_storage_traits<nsString>
michael@0 177 {
michael@0 178 typedef const nsAString & ConstructorType;
michael@0 179 typedef nsString StorageType;
michael@0 180 static inline void storage_conversion(ConstructorType aText, StorageType* _outData)
michael@0 181 {
michael@0 182 *_outData = aText;
michael@0 183 }
michael@0 184 static inline void destroy(const StorageType& _outData)
michael@0 185 { }
michael@0 186 };
michael@0 187 template < >
michael@0 188 struct variant_text_traits<nsString>
michael@0 189 {
michael@0 190 static inline nsresult asUTF8String(const nsString &aValue,
michael@0 191 nsACString &_result)
michael@0 192 {
michael@0 193 CopyUTF16toUTF8(aValue, _result);
michael@0 194 return NS_OK;
michael@0 195 }
michael@0 196 static inline nsresult asString(const nsString &aValue,
michael@0 197 nsAString &_result)
michael@0 198 {
michael@0 199 _result = aValue;
michael@0 200 return NS_OK;
michael@0 201 }
michael@0 202 };
michael@0 203
michael@0 204 template < >
michael@0 205 struct variant_traits<nsCString>
michael@0 206 {
michael@0 207 static inline uint16_t type() { return nsIDataType::VTYPE_UTF8STRING; }
michael@0 208 };
michael@0 209 template < >
michael@0 210 struct variant_storage_traits<nsCString>
michael@0 211 {
michael@0 212 typedef const nsACString & ConstructorType;
michael@0 213 typedef nsCString StorageType;
michael@0 214 static inline void storage_conversion(ConstructorType aText, StorageType* _outData)
michael@0 215 {
michael@0 216 *_outData = aText;
michael@0 217 }
michael@0 218 static inline void destroy(const StorageType &aData)
michael@0 219 { }
michael@0 220 };
michael@0 221 template < >
michael@0 222 struct variant_text_traits<nsCString>
michael@0 223 {
michael@0 224 static inline nsresult asUTF8String(const nsCString &aValue,
michael@0 225 nsACString &_result)
michael@0 226 {
michael@0 227 _result = aValue;
michael@0 228 return NS_OK;
michael@0 229 }
michael@0 230 static inline nsresult asString(const nsCString &aValue,
michael@0 231 nsAString &_result)
michael@0 232 {
michael@0 233 CopyUTF8toUTF16(aValue, _result);
michael@0 234 return NS_OK;
michael@0 235 }
michael@0 236 };
michael@0 237
michael@0 238 /**
michael@0 239 * BLOB types
michael@0 240 */
michael@0 241
michael@0 242 template < >
michael@0 243 struct variant_traits<uint8_t[]>
michael@0 244 {
michael@0 245 static inline uint16_t type() { return nsIDataType::VTYPE_ARRAY; }
michael@0 246 };
michael@0 247 template < >
michael@0 248 struct variant_storage_traits<uint8_t[], false>
michael@0 249 {
michael@0 250 typedef std::pair<const void *, int> ConstructorType;
michael@0 251 typedef FallibleTArray<uint8_t> StorageType;
michael@0 252 static inline void storage_conversion(ConstructorType aBlob, StorageType* _outData)
michael@0 253 {
michael@0 254 _outData->Clear();
michael@0 255 _outData->SetCapacity(aBlob.second);
michael@0 256 (void)_outData->AppendElements(static_cast<const uint8_t *>(aBlob.first),
michael@0 257 aBlob.second);
michael@0 258 }
michael@0 259 static inline void destroy(const StorageType& _outData)
michael@0 260 { }
michael@0 261 };
michael@0 262 template < >
michael@0 263 struct variant_storage_traits<uint8_t[], true>
michael@0 264 {
michael@0 265 typedef std::pair<uint8_t *, int> ConstructorType;
michael@0 266 typedef std::pair<uint8_t *, int> StorageType;
michael@0 267 static inline void storage_conversion(ConstructorType aBlob, StorageType* _outData)
michael@0 268 {
michael@0 269 *_outData = aBlob;
michael@0 270 }
michael@0 271 static inline void destroy(StorageType &aData)
michael@0 272 {
michael@0 273 if (aData.first) {
michael@0 274 NS_Free(aData.first);
michael@0 275 aData.first = nullptr;
michael@0 276 }
michael@0 277 }
michael@0 278 };
michael@0 279 template < >
michael@0 280 struct variant_blob_traits<uint8_t[], false>
michael@0 281 {
michael@0 282 static inline nsresult asArray(FallibleTArray<uint8_t> &aData,
michael@0 283 uint16_t *_type,
michael@0 284 uint32_t *_size,
michael@0 285 void **_result)
michael@0 286 {
michael@0 287 // For empty blobs, we return nullptr.
michael@0 288 if (aData.Length() == 0) {
michael@0 289 *_result = nullptr;
michael@0 290 *_type = nsIDataType::VTYPE_UINT8;
michael@0 291 *_size = 0;
michael@0 292 return NS_OK;
michael@0 293 }
michael@0 294
michael@0 295 // Otherwise, we copy the array.
michael@0 296 *_result = nsMemory::Clone(aData.Elements(), aData.Length() * sizeof(uint8_t));
michael@0 297 NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY);
michael@0 298
michael@0 299 // Set type and size
michael@0 300 *_type = nsIDataType::VTYPE_UINT8;
michael@0 301 *_size = aData.Length();
michael@0 302 return NS_OK;
michael@0 303 }
michael@0 304 };
michael@0 305
michael@0 306 template < >
michael@0 307 struct variant_blob_traits<uint8_t[], true>
michael@0 308 {
michael@0 309 static inline nsresult asArray(std::pair<uint8_t *, int> &aData,
michael@0 310 uint16_t *_type,
michael@0 311 uint32_t *_size,
michael@0 312 void **_result)
michael@0 313 {
michael@0 314 // For empty blobs, we return nullptr.
michael@0 315 if (aData.second == 0) {
michael@0 316 *_result = nullptr;
michael@0 317 *_type = nsIDataType::VTYPE_UINT8;
michael@0 318 *_size = 0;
michael@0 319 return NS_OK;
michael@0 320 }
michael@0 321
michael@0 322 // Otherwise, transfer the data out.
michael@0 323 *_result = aData.first;
michael@0 324 aData.first = nullptr;
michael@0 325 MOZ_ASSERT(*_result); // We asked for it twice, better not use adopting!
michael@0 326
michael@0 327 // Set type and size
michael@0 328 *_type = nsIDataType::VTYPE_UINT8;
michael@0 329 *_size = aData.second;
michael@0 330 return NS_OK;
michael@0 331 }
michael@0 332 };
michael@0 333
michael@0 334 /**
michael@0 335 * nullptr type
michael@0 336 */
michael@0 337
michael@0 338 class NullVariant : public Variant_base
michael@0 339 {
michael@0 340 public:
michael@0 341 NS_IMETHOD GetDataType(uint16_t *_type)
michael@0 342 {
michael@0 343 NS_ENSURE_ARG_POINTER(_type);
michael@0 344 *_type = nsIDataType::VTYPE_EMPTY;
michael@0 345 return NS_OK;
michael@0 346 }
michael@0 347
michael@0 348 NS_IMETHOD GetAsAUTF8String(nsACString &_str)
michael@0 349 {
michael@0 350 // Return a void string.
michael@0 351 _str.Truncate(0);
michael@0 352 _str.SetIsVoid(true);
michael@0 353 return NS_OK;
michael@0 354 }
michael@0 355
michael@0 356 NS_IMETHOD GetAsAString(nsAString &_str)
michael@0 357 {
michael@0 358 // Return a void string.
michael@0 359 _str.Truncate(0);
michael@0 360 _str.SetIsVoid(true);
michael@0 361 return NS_OK;
michael@0 362 }
michael@0 363 };
michael@0 364
michael@0 365 ////////////////////////////////////////////////////////////////////////////////
michael@0 366 //// Template Implementation
michael@0 367
michael@0 368 template <typename DataType, bool Adopting=false>
michael@0 369 class Variant : public Variant_base
michael@0 370 {
michael@0 371 ~Variant()
michael@0 372 {
michael@0 373 variant_storage_traits<DataType, Adopting>::destroy(mData);
michael@0 374 }
michael@0 375
michael@0 376 public:
michael@0 377 Variant(const typename variant_storage_traits<DataType, Adopting>::ConstructorType aData)
michael@0 378 {
michael@0 379 variant_storage_traits<DataType, Adopting>::storage_conversion(aData, &mData);
michael@0 380 }
michael@0 381
michael@0 382 NS_IMETHOD GetDataType(uint16_t *_type)
michael@0 383 {
michael@0 384 *_type = variant_traits<DataType>::type();
michael@0 385 return NS_OK;
michael@0 386 }
michael@0 387 NS_IMETHOD GetAsInt32(int32_t *_integer)
michael@0 388 {
michael@0 389 return variant_integer_traits<DataType, Adopting>::asInt32(mData, _integer);
michael@0 390 }
michael@0 391
michael@0 392 NS_IMETHOD GetAsInt64(int64_t *_integer)
michael@0 393 {
michael@0 394 return variant_integer_traits<DataType, Adopting>::asInt64(mData, _integer);
michael@0 395 }
michael@0 396
michael@0 397 NS_IMETHOD GetAsDouble(double *_double)
michael@0 398 {
michael@0 399 return variant_float_traits<DataType, Adopting>::asDouble(mData, _double);
michael@0 400 }
michael@0 401
michael@0 402 NS_IMETHOD GetAsAUTF8String(nsACString &_str)
michael@0 403 {
michael@0 404 return variant_text_traits<DataType, Adopting>::asUTF8String(mData, _str);
michael@0 405 }
michael@0 406
michael@0 407 NS_IMETHOD GetAsAString(nsAString &_str)
michael@0 408 {
michael@0 409 return variant_text_traits<DataType, Adopting>::asString(mData, _str);
michael@0 410 }
michael@0 411
michael@0 412 NS_IMETHOD GetAsArray(uint16_t *_type,
michael@0 413 nsIID *,
michael@0 414 uint32_t *_size,
michael@0 415 void **_data)
michael@0 416 {
michael@0 417 return variant_blob_traits<DataType, Adopting>::asArray(mData, _type, _size, _data);
michael@0 418 }
michael@0 419
michael@0 420 private:
michael@0 421 typename variant_storage_traits<DataType, Adopting>::StorageType mData;
michael@0 422 };
michael@0 423
michael@0 424 ////////////////////////////////////////////////////////////////////////////////
michael@0 425 //// Handy typedefs! Use these for the right mapping.
michael@0 426
michael@0 427 typedef Variant<int64_t> IntegerVariant;
michael@0 428 typedef Variant<double> FloatVariant;
michael@0 429 typedef Variant<nsString> TextVariant;
michael@0 430 typedef Variant<nsCString> UTF8TextVariant;
michael@0 431 typedef Variant<uint8_t[], false> BlobVariant;
michael@0 432 typedef Variant<uint8_t[], true> AdoptedBlobVariant;
michael@0 433
michael@0 434 } // namespace storage
michael@0 435 } // namespace mozilla
michael@0 436
michael@0 437 #include "Variant_inl.h"
michael@0 438
michael@0 439 #endif // mozilla_storage_Variant_h__

mercurial