1/*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "IDBKey.h"
28
29#if ENABLE(INDEXED_DATABASE)
30
31#include "IDBKeyData.h"
32#include <JavaScriptCore/ArrayBufferView.h>
33#include <JavaScriptCore/JSArrayBuffer.h>
34#include <JavaScriptCore/JSArrayBufferView.h>
35#include <JavaScriptCore/JSCInlines.h>
36
37namespace WebCore {
38
39using IDBKeyVector = Vector<RefPtr<IDBKey>>;
40
41Ref<IDBKey> IDBKey::createBinary(const ThreadSafeDataBuffer& buffer)
42{
43 return adoptRef(*new IDBKey(buffer));
44}
45
46Ref<IDBKey> IDBKey::createBinary(JSC::JSArrayBuffer& arrayBuffer)
47{
48 auto* buffer = arrayBuffer.impl();
49 return adoptRef(*new IDBKey(ThreadSafeDataBuffer::copyData(buffer->data(), buffer->byteLength())));
50}
51
52Ref<IDBKey> IDBKey::createBinary(JSC::JSArrayBufferView& arrayBufferView)
53{
54 auto bufferView = arrayBufferView.possiblySharedImpl();
55 return adoptRef(*new IDBKey(ThreadSafeDataBuffer::copyData(bufferView->data(), bufferView->byteLength())));
56}
57
58IDBKey::IDBKey(IndexedDB::KeyType type, double number)
59 : m_type(type)
60 , m_value(number)
61 , m_sizeEstimate(OverheadSize + sizeof(double))
62{
63}
64
65IDBKey::IDBKey(const String& value)
66 : m_type(IndexedDB::KeyType::String)
67 , m_value(value)
68 , m_sizeEstimate(OverheadSize + value.length() * sizeof(UChar))
69{
70}
71
72IDBKey::IDBKey(const IDBKeyVector& keyArray, size_t arraySize)
73 : m_type(IndexedDB::KeyType::Array)
74 , m_value(keyArray)
75 , m_sizeEstimate(OverheadSize + arraySize)
76{
77}
78
79IDBKey::IDBKey(const ThreadSafeDataBuffer& buffer)
80 : m_type(IndexedDB::KeyType::Binary)
81 , m_value(buffer)
82 , m_sizeEstimate(OverheadSize + buffer.size())
83{
84}
85
86IDBKey::~IDBKey() = default;
87
88bool IDBKey::isValid() const
89{
90 if (m_type == IndexedDB::KeyType::Invalid)
91 return false;
92
93 if (m_type == IndexedDB::KeyType::Array) {
94 for (auto& key : WTF::get<IDBKeyVector>(m_value)) {
95 if (!key->isValid())
96 return false;
97 }
98 }
99
100 return true;
101}
102
103int IDBKey::compare(const IDBKey& other) const
104{
105 if (m_type != other.m_type)
106 return m_type > other.m_type ? -1 : 1;
107
108 switch (m_type) {
109 case IndexedDB::KeyType::Array: {
110 auto& array = WTF::get<IDBKeyVector>(m_value);
111 auto& otherArray = WTF::get<IDBKeyVector>(other.m_value);
112 for (size_t i = 0; i < array.size() && i < otherArray.size(); ++i) {
113 if (int result = array[i]->compare(*otherArray[i]))
114 return result;
115 }
116 if (array.size() < otherArray.size())
117 return -1;
118 if (array.size() > otherArray.size())
119 return 1;
120 return 0;
121 }
122 case IndexedDB::KeyType::Binary:
123 return compareBinaryKeyData(WTF::get<ThreadSafeDataBuffer>(m_value), WTF::get<ThreadSafeDataBuffer>(other.m_value));
124 case IndexedDB::KeyType::String:
125 return -codePointCompare(WTF::get<String>(other.m_value), WTF::get<String>(m_value));
126 case IndexedDB::KeyType::Date:
127 case IndexedDB::KeyType::Number: {
128 auto number = WTF::get<double>(m_value);
129 auto otherNumber = WTF::get<double>(other.m_value);
130 return (number < otherNumber) ? -1 : ((number > otherNumber) ? 1 : 0);
131 }
132 case IndexedDB::KeyType::Invalid:
133 case IndexedDB::KeyType::Min:
134 case IndexedDB::KeyType::Max:
135 ASSERT_NOT_REACHED();
136 return 0;
137 }
138
139 ASSERT_NOT_REACHED();
140 return 0;
141}
142
143bool IDBKey::isLessThan(const IDBKey& other) const
144{
145 return compare(other) == -1;
146}
147
148bool IDBKey::isEqual(const IDBKey& other) const
149{
150 return !compare(other);
151}
152
153#if !LOG_DISABLED
154String IDBKey::loggingString() const
155{
156 return IDBKeyData(this).loggingString();
157}
158#endif
159
160} // namespace WebCore
161
162#endif
163