diff options
Diffstat (limited to 'dom/indexedDB/Key.h')
-rw-r--r-- | dom/indexedDB/Key.h | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/dom/indexedDB/Key.h b/dom/indexedDB/Key.h new file mode 100644 index 000000000..856089c97 --- /dev/null +++ b/dom/indexedDB/Key.h @@ -0,0 +1,365 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_indexeddb_key_h__ +#define mozilla_dom_indexeddb_key_h__ + +#include "js/RootingAPI.h" +#include "nsString.h" + +class mozIStorageStatement; +class mozIStorageValueArray; + +namespace IPC { + +template <typename> struct ParamTraits; + +} // namespace IPC + +namespace mozilla { +namespace dom { +namespace indexedDB { + +class Key +{ + friend struct IPC::ParamTraits<Key>; + + nsCString mBuffer; + +public: + enum { + eTerminator = 0, + eFloat = 0x10, + eDate = 0x20, + eString = 0x30, + eBinary = 0x40, + eArray = 0x50, + eMaxType = eArray + }; + + static const uint8_t kMaxArrayCollapse = uint8_t(3); + static const uint8_t kMaxRecursionDepth = uint8_t(64); + + Key() + { + Unset(); + } + + explicit + Key(const nsACString& aBuffer) + : mBuffer(aBuffer) + { } + + Key& + operator=(const nsAString& aString) + { + SetFromString(aString); + return *this; + } + + Key& + operator=(int64_t aInt) + { + SetFromInteger(aInt); + return *this; + } + + bool + operator==(const Key& aOther) const + { + Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid()); + + return mBuffer.Equals(aOther.mBuffer); + } + + bool + operator!=(const Key& aOther) const + { + Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid()); + + return !mBuffer.Equals(aOther.mBuffer); + } + + bool + operator<(const Key& aOther) const + { + Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid()); + + return Compare(mBuffer, aOther.mBuffer) < 0; + } + + bool + operator>(const Key& aOther) const + { + Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid()); + + return Compare(mBuffer, aOther.mBuffer) > 0; + } + + bool + operator<=(const Key& aOther) const + { + Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid()); + + return Compare(mBuffer, aOther.mBuffer) <= 0; + } + + bool + operator>=(const Key& aOther) const + { + Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid()); + + return Compare(mBuffer, aOther.mBuffer) >= 0; + } + + void + Unset() + { + mBuffer.SetIsVoid(true); + } + + bool + IsUnset() const + { + return mBuffer.IsVoid(); + } + + bool + IsFloat() const + { + return !IsUnset() && *BufferStart() == eFloat; + } + + bool + IsDate() const + { + return !IsUnset() && *BufferStart() == eDate; + } + + bool + IsString() const + { + return !IsUnset() && *BufferStart() == eString; + } + + bool + IsBinary() const + { + return !IsUnset() && *BufferStart() == eBinary; + } + + bool + IsArray() const + { + return !IsUnset() && *BufferStart() >= eArray; + } + + double + ToFloat() const + { + Assert(IsFloat()); + const unsigned char* pos = BufferStart(); + double res = DecodeNumber(pos, BufferEnd()); + Assert(pos >= BufferEnd()); + return res; + } + + double + ToDateMsec() const + { + Assert(IsDate()); + const unsigned char* pos = BufferStart(); + double res = DecodeNumber(pos, BufferEnd()); + Assert(pos >= BufferEnd()); + return res; + } + + void + ToString(nsString& aString) const + { + Assert(IsString()); + const unsigned char* pos = BufferStart(); + DecodeString(pos, BufferEnd(), aString); + Assert(pos >= BufferEnd()); + } + + void + SetFromString(const nsAString& aString) + { + mBuffer.Truncate(); + EncodeString(aString, 0); + TrimBuffer(); + } + + void + SetFromInteger(int64_t aInt) + { + mBuffer.Truncate(); + EncodeNumber(double(aInt), eFloat); + TrimBuffer(); + } + + nsresult + SetFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal); + + nsresult + ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) const; + + nsresult + ToJSVal(JSContext* aCx, JS::Heap<JS::Value>& aVal) const; + + nsresult + AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal); + +#ifdef ENABLE_INTL_API + nsresult + ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const; +#endif + + void + FinishArray() + { + TrimBuffer(); + } + + const nsCString& + GetBuffer() const + { + return mBuffer; + } + + nsresult + BindToStatement(mozIStorageStatement* aStatement, + const nsACString& aParamName) const; + + nsresult + SetFromStatement(mozIStorageStatement* aStatement, uint32_t aIndex); + + nsresult + SetFromValueArray(mozIStorageValueArray* aValues, uint32_t aIndex); + + static int16_t + CompareKeys(const Key& aFirst, const Key& aSecond) + { + int32_t result = Compare(aFirst.mBuffer, aSecond.mBuffer); + + if (result < 0) { + return -1; + } + + if (result > 0) { + return 1; + } + + return 0; + } + +private: + const unsigned char* + BufferStart() const + { + return reinterpret_cast<const unsigned char*>(mBuffer.BeginReading()); + } + + const unsigned char* + BufferEnd() const + { + return reinterpret_cast<const unsigned char*>(mBuffer.EndReading()); + } + + // Encoding helper. Trims trailing zeros off of mBuffer as a post-processing + // step. + void + TrimBuffer() + { + const char* end = mBuffer.EndReading() - 1; + while (!*end) { + --end; + } + + mBuffer.Truncate(end + 1 - mBuffer.BeginReading()); + } + + // Encoding functions. These append the encoded value to the end of mBuffer + nsresult + EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal, uint8_t aTypeOffset); + + void + EncodeString(const nsAString& aString, uint8_t aTypeOffset); + + template <typename T> + void + EncodeString(const T* aStart, const T* aEnd, uint8_t aTypeOffset); + + template <typename T> + void + EncodeAsString(const T* aStart, const T* aEnd, uint8_t aType); + +#ifdef ENABLE_INTL_API + nsresult + EncodeLocaleString(const nsDependentString& aString, uint8_t aTypeOffset, + const nsCString& aLocale); +#endif + + void + EncodeNumber(double aFloat, uint8_t aType); + + void + EncodeBinary(JSObject* aObject, bool aIsViewObject, uint8_t aTypeOffset); + + // Decoding functions. aPos points into mBuffer and is adjusted to point + // past the consumed value. + static nsresult + DecodeJSVal(const unsigned char*& aPos, + const unsigned char* aEnd, + JSContext* aCx, + JS::MutableHandle<JS::Value> aVal); + + static void + DecodeString(const unsigned char*& aPos, + const unsigned char* aEnd, + nsString& aString); + + static double + DecodeNumber(const unsigned char*& aPos, const unsigned char* aEnd); + + static JSObject* + DecodeBinary(const unsigned char*& aPos, + const unsigned char* aEnd, + JSContext* aCx); + + nsresult + EncodeJSValInternal(JSContext* aCx, + JS::Handle<JS::Value> aVal, + uint8_t aTypeOffset, + uint16_t aRecursionDepth); + + static nsresult + DecodeJSValInternal(const unsigned char*& aPos, + const unsigned char* aEnd, + JSContext* aCx, + uint8_t aTypeOffset, + JS::MutableHandle<JS::Value> aVal, + uint16_t aRecursionDepth); + + template <typename T> + nsresult + SetFromSource(T* aSource, uint32_t aIndex); + + void + Assert(bool aCondition) const +#ifdef DEBUG + ; +#else + { } +#endif +}; + +} // namespace indexedDB +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_indexeddb_key_h__ |