1/*
2 * Copyright (C) 2015 Apple 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 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "IndexValueEntry.h"
28
29#if ENABLE(INDEXED_DATABASE)
30
31#include "IDBCursorInfo.h"
32
33namespace WebCore {
34namespace IDBServer {
35
36IndexValueEntry::IndexValueEntry(bool unique)
37 : m_unique(unique)
38{
39 if (m_unique)
40 m_key = nullptr;
41 else
42 m_orderedKeys = new IDBKeyDataSet;
43}
44
45IndexValueEntry::~IndexValueEntry()
46{
47 if (m_unique)
48 delete m_key;
49 else
50 delete m_orderedKeys;
51}
52
53void IndexValueEntry::addKey(const IDBKeyData& key)
54{
55 if (m_unique) {
56 delete m_key;
57 m_key = new IDBKeyData(key);
58 return;
59 }
60
61 m_orderedKeys->insert(key);
62}
63
64bool IndexValueEntry::removeKey(const IDBKeyData& key)
65{
66 if (m_unique) {
67 if (m_key && *m_key == key) {
68 delete m_key;
69 m_key = nullptr;
70 return true;
71 }
72
73 return false;
74 }
75
76 return m_orderedKeys->erase(key);
77}
78
79const IDBKeyData* IndexValueEntry::getLowest() const
80{
81 if (m_unique)
82 return m_key;
83
84 if (m_orderedKeys->empty())
85 return nullptr;
86
87 return &(*m_orderedKeys->begin());
88}
89
90uint64_t IndexValueEntry::getCount() const
91{
92 if (m_unique)
93 return m_key ? 1 : 0;
94
95 return m_orderedKeys->size();
96}
97
98IndexValueEntry::Iterator::Iterator(IndexValueEntry& entry)
99 : m_entry(&entry)
100{
101 ASSERT(m_entry->m_key);
102}
103
104IndexValueEntry::Iterator::Iterator(IndexValueEntry& entry, IDBKeyDataSet::iterator iterator)
105 : m_entry(&entry)
106 , m_forwardIterator(iterator)
107{
108}
109
110IndexValueEntry::Iterator::Iterator(IndexValueEntry& entry, IDBKeyDataSet::reverse_iterator iterator)
111 : m_entry(&entry)
112 , m_forward(false)
113 , m_reverseIterator(iterator)
114{
115}
116
117const IDBKeyData& IndexValueEntry::Iterator::key() const
118{
119 ASSERT(isValid());
120 if (m_entry->unique()) {
121 ASSERT(m_entry->m_key);
122 return *m_entry->m_key;
123 }
124
125 return m_forward ? *m_forwardIterator : *m_reverseIterator;
126}
127
128bool IndexValueEntry::Iterator::isValid() const
129{
130#if !LOG_DISABLED
131 if (m_entry) {
132 if (m_entry->m_unique)
133 ASSERT(m_entry->m_key);
134 else
135 ASSERT(m_entry->m_orderedKeys);
136 }
137#endif
138
139 return m_entry;
140}
141
142void IndexValueEntry::Iterator::invalidate()
143{
144 m_entry = nullptr;
145}
146
147IndexValueEntry::Iterator& IndexValueEntry::Iterator::operator++()
148{
149 if (!isValid())
150 return *this;
151
152 if (m_entry->m_unique) {
153 invalidate();
154 return *this;
155 }
156
157 if (m_forward) {
158 ++m_forwardIterator;
159 if (m_forwardIterator == m_entry->m_orderedKeys->end())
160 invalidate();
161 } else {
162 ++m_reverseIterator;
163 if (m_reverseIterator == m_entry->m_orderedKeys->rend())
164 invalidate();
165 }
166
167 return *this;
168}
169
170IndexValueEntry::Iterator IndexValueEntry::begin()
171{
172 if (m_unique) {
173 ASSERT(m_key);
174 return { *this };
175 }
176
177 ASSERT(m_orderedKeys);
178 return { *this, m_orderedKeys->begin() };
179}
180
181IndexValueEntry::Iterator IndexValueEntry::reverseBegin(CursorDuplicity duplicity)
182{
183 if (m_unique) {
184 ASSERT(m_key);
185 return { *this };
186 }
187
188 ASSERT(m_orderedKeys);
189
190 if (duplicity == CursorDuplicity::Duplicates)
191 return { *this, m_orderedKeys->rbegin() };
192
193 auto iterator = m_orderedKeys->rend();
194 --iterator;
195 return { *this, iterator };
196}
197
198IndexValueEntry::Iterator IndexValueEntry::find(const IDBKeyData& key)
199{
200 if (m_unique) {
201 ASSERT(m_key);
202 return *m_key == key ? IndexValueEntry::Iterator(*this) : IndexValueEntry::Iterator();
203 }
204
205 ASSERT(m_orderedKeys);
206 auto iterator = m_orderedKeys->lower_bound(key);
207 if (iterator == m_orderedKeys->end())
208 return { };
209
210 return { *this, iterator };
211}
212
213IndexValueEntry::Iterator IndexValueEntry::reverseFind(const IDBKeyData& key, CursorDuplicity)
214{
215 if (m_unique) {
216 ASSERT(m_key);
217 return *m_key == key ? IndexValueEntry::Iterator(*this) : IndexValueEntry::Iterator();
218 }
219
220 ASSERT(m_orderedKeys);
221 auto iterator = IDBKeyDataSet::reverse_iterator(m_orderedKeys->upper_bound(key));
222 if (iterator == m_orderedKeys->rend())
223 return { };
224
225 return { *this, iterator };
226}
227
228
229} // namespace IDBServer
230} // namespace WebCore
231
232#endif // ENABLE(INDEXED_DATABASE)
233