dom/indexedDB/Key.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     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_dom_indexeddb_key_h__
     8 #define mozilla_dom_indexeddb_key_h__
    10 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
    12 #include "mozIStorageStatement.h"
    14 #include "js/Value.h"
    16 namespace IPC {
    17 template <typename T> struct ParamTraits;
    18 } // namespace IPC
    20 BEGIN_INDEXEDDB_NAMESPACE
    22 class Key
    23 {
    24   friend struct IPC::ParamTraits<Key>;
    26 public:
    27   Key()
    28   {
    29     Unset();
    30   }
    32   Key& operator=(const nsAString& aString)
    33   {
    34     SetFromString(aString);
    35     return *this;
    36   }
    38   Key& operator=(int64_t aInt)
    39   {
    40     SetFromInteger(aInt);
    41     return *this;
    42   }
    44   bool operator==(const Key& aOther) const
    45   {
    46     NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
    47                  "Don't compare unset keys!");
    49     return mBuffer.Equals(aOther.mBuffer);
    50   }
    52   bool operator!=(const Key& aOther) const
    53   {
    54     NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
    55                  "Don't compare unset keys!");
    57     return !mBuffer.Equals(aOther.mBuffer);
    58   }
    60   bool operator<(const Key& aOther) const
    61   {
    62     NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
    63                  "Don't compare unset keys!");
    65     return Compare(mBuffer, aOther.mBuffer) < 0;
    66   }
    68   bool operator>(const Key& aOther) const
    69   {
    70     NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
    71                  "Don't compare unset keys!");
    73     return Compare(mBuffer, aOther.mBuffer) > 0;
    74   }
    76   bool operator<=(const Key& aOther) const
    77   {
    78     NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
    79                  "Don't compare unset keys!");
    81     return Compare(mBuffer, aOther.mBuffer) <= 0;
    82   }
    84   bool operator>=(const Key& aOther) const
    85   {
    86     NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
    87                  "Don't compare unset keys!");
    89     return Compare(mBuffer, aOther.mBuffer) >= 0;
    90   }
    92   void
    93   Unset()
    94   {
    95     mBuffer.SetIsVoid(true);
    96   }
    98   bool IsUnset() const
    99   {
   100     return mBuffer.IsVoid();
   101   }
   103   bool IsFloat() const
   104   {
   105     return !IsUnset() && mBuffer.First() == eFloat;
   106   }
   108   bool IsDate() const
   109   {
   110     return !IsUnset() && mBuffer.First() == eDate;
   111   }
   113   bool IsString() const
   114   {
   115     return !IsUnset() && mBuffer.First() == eString;
   116   }
   118   bool IsArray() const
   119   {
   120     return !IsUnset() && mBuffer.First() >= eArray;
   121   }
   123   double ToFloat() const
   124   {
   125     NS_ASSERTION(IsFloat(), "Why'd you call this?");
   126     const unsigned char* pos = BufferStart();
   127     double res = DecodeNumber(pos, BufferEnd());
   128     NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
   129     return res;
   130   }
   132   double ToDateMsec() const
   133   {
   134     NS_ASSERTION(IsDate(), "Why'd you call this?");
   135     const unsigned char* pos = BufferStart();
   136     double res = DecodeNumber(pos, BufferEnd());
   137     NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
   138     return res;
   139   }
   141   void ToString(nsString& aString) const
   142   {
   143     NS_ASSERTION(IsString(), "Why'd you call this?");
   144     const unsigned char* pos = BufferStart();
   145     DecodeString(pos, BufferEnd(), aString);
   146     NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
   147   }
   149   void SetFromString(const nsAString& aString)
   150   {
   151     mBuffer.Truncate();
   152     EncodeString(aString, 0);
   153     TrimBuffer();
   154   }
   156   void SetFromInteger(int64_t aInt)
   157   {
   158     mBuffer.Truncate();
   159     EncodeNumber(double(aInt), eFloat);
   160     TrimBuffer();
   161   }
   163   nsresult SetFromJSVal(JSContext* aCx,
   164                         JS::Handle<JS::Value> aVal)
   165   {
   166     mBuffer.Truncate();
   168     if (aVal.isNull() || aVal.isUndefined()) {
   169       Unset();
   170       return NS_OK;
   171     }
   173     nsresult rv = EncodeJSVal(aCx, aVal, 0);
   174     if (NS_FAILED(rv)) {
   175       Unset();
   176       return rv;
   177     }
   178     TrimBuffer();
   180     return NS_OK;
   181   }
   183   nsresult ToJSVal(JSContext* aCx,
   184                    JS::MutableHandle<JS::Value> aVal) const
   185   {
   186     if (IsUnset()) {
   187       aVal.setUndefined();
   188       return NS_OK;
   189     }
   191     const unsigned char* pos = BufferStart();
   192     nsresult rv = DecodeJSVal(pos, BufferEnd(), aCx, 0, aVal);
   193     NS_ENSURE_SUCCESS(rv, rv);
   195     NS_ASSERTION(pos >= BufferEnd(),
   196                  "Didn't consume whole buffer");
   198     return NS_OK;
   199   }
   201   nsresult ToJSVal(JSContext* aCx,
   202                    JS::Heap<JS::Value>& aVal) const
   203   {
   204     JS::Rooted<JS::Value> value(aCx);
   205     nsresult rv = ToJSVal(aCx, &value);
   206     if (NS_SUCCEEDED(rv)) {
   207       aVal = value;
   208     }
   209     return rv;
   210   }
   212   nsresult AppendItem(JSContext* aCx,
   213                       bool aFirstOfArray,
   214                       JS::Handle<JS::Value> aVal)
   215   {
   216     nsresult rv = EncodeJSVal(aCx, aVal, aFirstOfArray ? eMaxType : 0);
   217     if (NS_FAILED(rv)) {
   218       Unset();
   219       return rv;
   220     }
   222     return NS_OK;
   223   }
   225   void FinishArray()
   226   {
   227     TrimBuffer();
   228   }
   230   const nsCString& GetBuffer() const
   231   {
   232     return mBuffer;
   233   }
   235   nsresult BindToStatement(mozIStorageStatement* aStatement,
   236                            const nsACString& aParamName) const
   237   {
   238     nsresult rv = aStatement->BindBlobByName(aParamName,
   239       reinterpret_cast<const uint8_t*>(mBuffer.get()), mBuffer.Length());
   241     return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   242   }
   244   nsresult SetFromStatement(mozIStorageStatement* aStatement,
   245                             uint32_t aIndex)
   246   {
   247     uint8_t* data;
   248     uint32_t dataLength = 0;
   250     nsresult rv = aStatement->GetBlob(aIndex, &dataLength, &data);
   251     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   253     mBuffer.Adopt(
   254       reinterpret_cast<char*>(const_cast<uint8_t*>(data)), dataLength);
   256     return NS_OK;
   257   }
   259   static
   260   int16_t CompareKeys(Key& aFirst, Key& aSecond)
   261   {
   262     int32_t result = Compare(aFirst.mBuffer, aSecond.mBuffer);
   264     if (result < 0) {
   265       return -1;
   266     }
   268     if (result > 0) {
   269       return 1;
   270     }
   272     return 0;
   273   }
   275 private:
   276   const unsigned char* BufferStart() const
   277   {
   278     return reinterpret_cast<const unsigned char*>(mBuffer.BeginReading());
   279   }
   281   const unsigned char* BufferEnd() const
   282   {
   283     return reinterpret_cast<const unsigned char*>(mBuffer.EndReading());
   284   }
   286   enum {
   287     eTerminator = 0,
   288     eFloat = 1,
   289     eDate = 2,
   290     eString = 3,
   291     eArray = 4,
   292     eMaxType = eArray
   293   };
   295   // Encoding helper. Trims trailing zeros off of mBuffer as a post-processing
   296   // step.
   297   void TrimBuffer()
   298   {
   299     const char* end = mBuffer.EndReading() - 1;
   300     while (!*end) {
   301       --end;
   302     }
   304     mBuffer.Truncate(end + 1 - mBuffer.BeginReading());
   305   }
   307   // Encoding functions. These append the encoded value to the end of mBuffer
   308   inline nsresult EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal,
   309                               uint8_t aTypeOffset)
   310   {
   311     return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0);
   312   }
   313   void EncodeString(const nsAString& aString, uint8_t aTypeOffset);
   314   void EncodeNumber(double aFloat, uint8_t aType);
   316   // Decoding functions. aPos points into mBuffer and is adjusted to point
   317   // past the consumed value.
   318   static inline nsresult DecodeJSVal(const unsigned char*& aPos,
   319                                      const unsigned char* aEnd, JSContext* aCx,
   320                                      uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal)
   321   {
   322     return DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset, aVal, 0);
   323   }
   325   static void DecodeString(const unsigned char*& aPos,
   326                            const unsigned char* aEnd,
   327                            nsString& aString);
   328   static double DecodeNumber(const unsigned char*& aPos,
   329                              const unsigned char* aEnd);
   331   nsCString mBuffer;
   333 private:
   334   nsresult EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
   335                                uint8_t aTypeOffset, uint16_t aRecursionDepth);
   337   static nsresult DecodeJSValInternal(const unsigned char*& aPos,
   338                                       const unsigned char* aEnd,
   339                                       JSContext* aCx, uint8_t aTypeOffset,
   340                                       JS::MutableHandle<JS::Value> aVal, uint16_t aRecursionDepth);
   341 };
   343 END_INDEXEDDB_NAMESPACE
   345 #endif /* mozilla_dom_indexeddb_key_h__ */

mercurial