LCOV - code coverage report
Current view: top level - storage - Variant.h (source / functions) Hit Total Coverage
Test: output.info Lines: 55 126 43.7 %
Date: 2017-07-14 16:53:18 Functions: 35 122 28.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13