summaryrefslogtreecommitdiff
path: root/Source/WebCore/Modules/indexeddb/IDBKeyData.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/Modules/indexeddb/IDBKeyData.h')
-rw-r--r--Source/WebCore/Modules/indexeddb/IDBKeyData.h271
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