diff options
Diffstat (limited to 'Source/WebCore/Modules/indexeddb/IDBKeyData.h')
-rw-r--r-- | Source/WebCore/Modules/indexeddb/IDBKeyData.h | 271 |
1 files changed, 255 insertions, 16 deletions
diff --git a/Source/WebCore/Modules/indexeddb/IDBKeyData.h b/Source/WebCore/Modules/indexeddb/IDBKeyData.h index 6a4f64a06..98f0b7359 100644 --- a/Source/WebCore/Modules/indexeddb/IDBKeyData.h +++ b/Source/WebCore/Modules/indexeddb/IDBKeyData.h @@ -23,43 +23,282 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef IDBKeyData_h -#define IDBKeyData_h +#pragma once #if ENABLE(INDEXED_DATABASE) #include "IDBKey.h" +#include <wtf/Variant.h> +#include <wtf/text/StringHash.h> namespace WebCore { class KeyedDecoder; class KeyedEncoder; -struct IDBKeyData { +class IDBKeyData { +public: IDBKeyData() - : type(IDBKey::InvalidType) - , numberValue(0) - , isNull(true) + : m_type(KeyType::Invalid) + , m_isNull(true) { } - IDBKeyData(const IDBKey*); + WEBCORE_EXPORT IDBKeyData(const IDBKey*); - PassRefPtr<IDBKey> maybeCreateIDBKey() const; + enum IsolatedCopyTag { IsolatedCopy }; + IDBKeyData(const IDBKeyData&, IsolatedCopyTag); + + static IDBKeyData minimum() + { + IDBKeyData result; + result.m_type = KeyType::Min; + result.m_isNull = false; + return result; + } + + static IDBKeyData maximum() + { + IDBKeyData result; + result.m_type = KeyType::Max; + result.m_isNull = false; + return result; + } + + WEBCORE_EXPORT RefPtr<IDBKey> maybeCreateIDBKey() const; IDBKeyData isolatedCopy() const; - void encode(KeyedEncoder&) const; - static bool decode(KeyedDecoder&, IDBKeyData&); + WEBCORE_EXPORT void encode(KeyedEncoder&) const; + WEBCORE_EXPORT static bool decode(KeyedDecoder&, IDBKeyData&); + + // compare() has the same semantics as strcmp(). + // - Returns negative if this IDBKeyData is less than other. + // - Returns positive if this IDBKeyData is greater than other. + // - Returns zero if this IDBKeyData is equal to other. + WEBCORE_EXPORT int compare(const IDBKeyData& other) const; + + void setArrayValue(const Vector<IDBKeyData>&); + void setBinaryValue(const ThreadSafeDataBuffer&); + void setStringValue(const String&); + void setDateValue(double); + WEBCORE_EXPORT void setNumberValue(double); + + template<class Encoder> void encode(Encoder&) const; + template<class Decoder> static bool decode(Decoder&, IDBKeyData&); + +#if !LOG_DISABLED + WEBCORE_EXPORT String loggingString() const; +#endif + + bool isNull() const { return m_isNull; } + bool isValid() const { return m_type != KeyType::Invalid; } + KeyType type() const { return m_type; } + + bool operator<(const IDBKeyData&) const; + bool operator>(const IDBKeyData& other) const + { + return !(*this < other) && !(*this == other); + } + + bool operator<=(const IDBKeyData& other) const + { + return !(*this > other); + } + + bool operator>=(const IDBKeyData& other) const + { + return !(*this < other); + } + + bool operator==(const IDBKeyData& other) const; + bool operator!=(const IDBKeyData& other) const + { + return !(*this == other); + } + + unsigned hash() const + { + Vector<unsigned> hashCodes; + hashCodes.append(static_cast<unsigned>(m_type)); + hashCodes.append(m_isNull ? 1 : 0); + hashCodes.append(m_isDeletedValue ? 1 : 0); + switch (m_type) { + case KeyType::Invalid: + case KeyType::Max: + case KeyType::Min: + break; + case KeyType::Number: + case KeyType::Date: + hashCodes.append(StringHasher::hashMemory<sizeof(double)>(&WTF::get<double>(m_value))); + break; + case KeyType::String: + hashCodes.append(StringHash::hash(WTF::get<String>(m_value))); + break; + case KeyType::Binary: { + auto* data = WTF::get<ThreadSafeDataBuffer>(m_value).data(); + if (!data) + hashCodes.append(0); + else + hashCodes.append(StringHasher::hashMemory(data->data(), data->size())); + break; + } + case KeyType::Array: + for (auto& key : WTF::get<Vector<IDBKeyData>>(m_value)) + hashCodes.append(key.hash()); + break; + } + + return StringHasher::hashMemory(hashCodes.data(), hashCodes.size() * sizeof(unsigned)); + } - IDBKey::Type type; - Vector<IDBKeyData> arrayValue; - String stringValue; - double numberValue; - bool isNull; + static IDBKeyData deletedValue(); + bool isDeletedValue() const { return m_isDeletedValue; } + + String string() const + { + ASSERT(m_type == KeyType::String); + return WTF::get<String>(m_value); + } + + double date() const + { + ASSERT(m_type == KeyType::Date); + return WTF::get<double>(m_value); + } + + double number() const + { + ASSERT(m_type == KeyType::Number); + return WTF::get<double>(m_value); + } + + const ThreadSafeDataBuffer& binary() const + { + ASSERT(m_type == KeyType::Binary); + return WTF::get<ThreadSafeDataBuffer>(m_value); + } + + const Vector<IDBKeyData>& array() const + { + ASSERT(m_type == KeyType::Array); + return WTF::get<Vector<IDBKeyData>>(m_value); + } + +private: + static void isolatedCopy(const IDBKeyData& source, IDBKeyData& destination); + + KeyType m_type; + Variant<Vector<IDBKeyData>, String, double, ThreadSafeDataBuffer> m_value; + + bool m_isNull { false }; + bool m_isDeletedValue { false }; }; +struct IDBKeyDataHash { + static unsigned hash(const IDBKeyData& a) { return a.hash(); } + static bool equal(const IDBKeyData& a, const IDBKeyData& b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = false; +}; + +struct IDBKeyDataHashTraits : public WTF::CustomHashTraits<IDBKeyData> { + static const bool emptyValueIsZero = false; + static const bool hasIsEmptyValueFunction = true; + + static void constructDeletedValue(IDBKeyData& key) + { + key = IDBKeyData::deletedValue(); + } + + static bool isDeletedValue(const IDBKeyData& key) + { + return key.isDeletedValue(); + } + + static IDBKeyData emptyValue() + { + return IDBKeyData(); + } + + static bool isEmptyValue(const IDBKeyData& key) + { + return key.isNull(); + } +}; + +template<class Encoder> +void IDBKeyData::encode(Encoder& encoder) const +{ + encoder << m_isNull; + if (m_isNull) + return; + + encoder.encodeEnum(m_type); + + switch (m_type) { + case KeyType::Invalid: + case KeyType::Max: + case KeyType::Min: + break; + case KeyType::Array: + encoder << WTF::get<Vector<IDBKeyData>>(m_value); + break; + case KeyType::Binary: + encoder << WTF::get<ThreadSafeDataBuffer>(m_value); + break; + case KeyType::String: + encoder << WTF::get<String>(m_value); + break; + case KeyType::Date: + case KeyType::Number: + encoder << WTF::get<double>(m_value); + break; + } +} + +template<class Decoder> +bool IDBKeyData::decode(Decoder& decoder, IDBKeyData& keyData) +{ + if (!decoder.decode(keyData.m_isNull)) + return false; + + if (keyData.m_isNull) + return true; + + if (!decoder.decodeEnum(keyData.m_type)) + return false; + + switch (keyData.m_type) { + case KeyType::Invalid: + case KeyType::Max: + case KeyType::Min: + break; + case KeyType::Array: + keyData.m_value = Vector<IDBKeyData>(); + if (!decoder.decode(WTF::get<Vector<IDBKeyData>>(keyData.m_value))) + return false; + break; + case KeyType::Binary: + keyData.m_value = ThreadSafeDataBuffer(); + if (!decoder.decode(WTF::get<ThreadSafeDataBuffer>(keyData.m_value))) + return false; + break; + case KeyType::String: + keyData.m_value = String(); + if (!decoder.decode(WTF::get<String>(keyData.m_value))) + return false; + break; + case KeyType::Date: + case KeyType::Number: + keyData.m_value = 0.0; + if (!decoder.decode(WTF::get<double>(keyData.m_value))) + return false; + break; + } + + return true; +} + } // namespace WebCore #endif // ENABLE(INDEXED_DATABASE) -#endif // IDBKeyData_h |