From 34479e5664fc7846f9c9d68abf92f0753821a59f Mon Sep 17 00:00:00 2001 From: stelar7 Date: Mon, 11 Nov 2024 10:49:00 +0100 Subject: [PATCH] LibWeb: Add a Key type for IndexedDB --- Libraries/LibWeb/CMakeLists.txt | 3 +- Libraries/LibWeb/IndexedDB/Internal/Key.cpp | 157 ++++++++++++++++++++ Libraries/LibWeb/IndexedDB/Internal/Key.h | 57 +++++++ 3 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 Libraries/LibWeb/IndexedDB/Internal/Key.cpp create mode 100644 Libraries/LibWeb/IndexedDB/Internal/Key.h diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 2c1d0755969..90132af9401 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -510,9 +510,10 @@ set(SOURCES Infra/Strings.cpp IndexedDB/Internal/Algorithms.cpp IndexedDB/Internal/Database.cpp + IndexedDB/Internal/Key.cpp + IndexedDB/IDBDatabase.cpp IndexedDB/IDBFactory.cpp IndexedDB/IDBOpenDBRequest.cpp - IndexedDB/IDBDatabase.cpp IndexedDB/IDBRequest.cpp IndexedDB/IDBVersionChangeEvent.cpp Internals/Inspector.cpp diff --git a/Libraries/LibWeb/IndexedDB/Internal/Key.cpp b/Libraries/LibWeb/IndexedDB/Internal/Key.cpp new file mode 100644 index 00000000000..8fe25457386 --- /dev/null +++ b/Libraries/LibWeb/IndexedDB/Internal/Key.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2024, stelar7 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Web::IndexedDB { + +// https://w3c.github.io/IndexedDB/#compare-two-keys +i8 Key::compare_two_keys(Key a, Key b) +{ + // 1. Let ta be the type of a. + auto ta = a.type(); + + // 2. Let tb be the type of b. + auto tb = b.type(); + + // 3. If ta does not equal tb, then run these steps: + if (ta != tb) { + // 1. If ta is array, then return 1. + if (ta == KeyType::Array) + return 1; + + // 1. If tb is array, then return -1. + if (tb == KeyType::Array) + return -1; + + // 1. If ta is binary, then return 1. + if (ta == KeyType::Binary) + return 1; + + // 1. If tb is binary, then return -1. + if (tb == KeyType::Binary) + return -1; + + // 1. If ta is string, then return 1. + if (ta == KeyType::String) + return 1; + + // 1. If tb is string, then return -1. + if (tb == KeyType::String) + return -1; + + // 1. If ta is date, then return 1. + if (ta == KeyType::Date) + return 1; + + // 1. Assert: tb is date. + VERIFY(tb == KeyType::Date); + + // 1. Return -1. + return -1; + } + + // 4. Let va be the value of a. + auto va = a.value(); + + // 5. Let vb be the value of b. + auto vb = b.value(); + + // 6. Switch on ta: + switch (ta) { + // number + // date + case KeyType::Number: + case KeyType::Date: { + auto a_value = va.get(); + auto b_value = vb.get(); + + // 1. If va is greater than vb, then return 1. + if (a_value > b_value) + return 1; + + // 2. If va is less than vb, then return -1. + if (a_value < b_value) + return -1; + + // 3. Return 0. + return 0; + } + // string + case KeyType::String: { + auto a_value = va.get(); + auto b_value = vb.get(); + + // 1. If va is code unit less than vb, then return -1. + if (Infra::code_unit_less_than(a_value, b_value)) + return -1; + + // 2. If vb is code unit less than va, then return 1. + if (Infra::code_unit_less_than(b_value, a_value)) + return 1; + + // 3. Return 0. + return 0; + } + // binary + case KeyType::Binary: { + auto a_value = va.get(); + auto b_value = vb.get(); + + // 1. If va is byte less than vb, then return -1. + if (Infra::is_byte_less_than(a_value, b_value)) + return -1; + + // 2. If vb is byte less than va, then return 1. + if (Infra::is_byte_less_than(b_value, a_value)) + return 1; + + // 3. Return 0. + return 0; + } + // array + case KeyType::Array: { + auto a_value = va.get>(); + auto b_value = vb.get>(); + + // 1. Let length be the lesser of va’s size and vb’s size. + auto length = min(a_value.size(), b_value.size()); + + // 2. Let i be 0. + u64 i = 0; + + // 3. While i is less than length, then: + while (i < length) { + // 1. Let c be the result of recursively comparing two keys with va[i] and vb[i]. + auto c = compare_two_keys(a_value[i], b_value[i]); + + // 2. If c is not 0, return c. + if (c != 0) + return c; + + // 3. Increase i by 1. + i++; + } + + // 4. If va’s size is greater than vb’s size, then return 1. + if (a_value.size() > b_value.size()) + return 1; + + // 5. If va’s size is less than vb’s size, then return -1. + if (a_value.size() < b_value.size()) + return -1; + + // 6. Return 0. + return 0; + } + } + + VERIFY_NOT_REACHED(); +} + +} diff --git a/Libraries/LibWeb/IndexedDB/Internal/Key.h b/Libraries/LibWeb/IndexedDB/Internal/Key.h new file mode 100644 index 00000000000..1f80e28bd36 --- /dev/null +++ b/Libraries/LibWeb/IndexedDB/Internal/Key.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024, stelar7 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Web::IndexedDB { + +// https://w3c.github.io/IndexedDB/#key-construct +class Key { + // A key has an associated type which is one of: number, date, string, binary, or array. + enum KeyType { + Number, + Date, + String, + Binary, + Array, + }; + + // A key also has an associated value, which will be either: + // * an unrestricted double if type is number or date, + // * a DOMString if type is string, + // * a byte sequence if type is binary, + // * a list of other keys if type is array. + using KeyValue = Variant>; + +public: + [[nodiscard]] KeyType type() { return m_type; } + [[nodiscard]] KeyValue value() { return m_value; } + + [[nodiscard]] static Key create_number(double value) { return Key(Number, value); } + [[nodiscard]] static Key create_date(double value) { return Key(Date, value); } + [[nodiscard]] static Key create_string(AK::String const& value) { return Key(String, value); } + [[nodiscard]] static Key create_binary(ByteBuffer const& value) { return Key(Binary, value); } + [[nodiscard]] static Key create_array(Vector const& value) { return Key(Array, value); } + + [[nodiscard]] static i8 compare_two_keys(Key a, Key b); + +private: + Key(KeyType type, KeyValue value) + : m_type(type) + , m_value(value) + { + } + + KeyType m_type; + KeyValue m_value; +}; + +}