7579724aa5fe185cf338cc41ac01265030d792ee
[WebKit.git] / Source / WebCore / Modules / indexeddb / server / IndexValueStore.cpp
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 "IndexValueStore.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBError.h"
32 #include "IDBKeyRangeData.h"
33
34 namespace WebCore {
35 namespace IDBServer {
36
37 IndexValueStore::IndexValueStore(bool unique)
38     : m_unique(unique)
39 {
40 }
41
42 const IDBKeyData* IndexValueStore::lowestValueForKey(const IDBKeyData& key) const
43 {
44     const auto& entry = m_records.get(key);
45     if (!entry)
46         return nullptr;
47
48     return entry->getLowest();
49 }
50
51 uint64_t IndexValueStore::countForKey(const IDBKeyData& key) const
52 {
53     const auto& entry = m_records.get(key);
54     if (!entry)
55         return 0;
56
57     return entry->getCount();
58 }
59
60 bool IndexValueStore::contains(const IDBKeyData& key) const
61 {
62     const auto& entry = m_records.get(key);
63     if (!entry)
64         return false;
65
66     ASSERT(entry->getCount());
67
68     return true;
69 }
70
71 IDBError IndexValueStore::addRecord(const IDBKeyData& indexKey, const IDBKeyData& valueKey)
72 {
73     auto result = m_records.add(indexKey, nullptr);
74
75     if (!result.isNewEntry && m_unique)
76         return IDBError(IDBExceptionCode::ConstraintError);
77
78     if (result.isNewEntry)
79         result.iterator->value = std::make_unique<IndexValueEntry>(m_unique);
80
81     result.iterator->value->addKey(valueKey);
82     m_orderedKeys.insert(indexKey);
83
84     return { };
85 }
86
87 void IndexValueStore::removeRecord(const IDBKeyData& indexKey, const IDBKeyData& valueKey)
88 {
89     auto iterator = m_records.find(indexKey);
90     if (!iterator->value)
91         return;
92
93     if (iterator->value->removeKey(valueKey))
94         m_records.remove(iterator);
95 }
96
97 void IndexValueStore::removeEntriesWithValueKey(const IDBKeyData& valueKey)
98 {
99     HashSet<IDBKeyData*> entryKeysToRemove;
100
101     for (auto& entry : m_records) {
102         if (entry.value->removeKey(valueKey))
103             entryKeysToRemove.add(&entry.key);
104     }
105
106     for (auto* entry : entryKeysToRemove) {
107         m_orderedKeys.erase(*entry);
108         m_records.remove(*entry);
109     }
110 }
111
112 IDBKeyData IndexValueStore::lowestKeyWithRecordInRange(const IDBKeyRangeData& range) const
113 {
114     if (range.isExactlyOneKey())
115         return m_records.contains(range.lowerKey) ? range.lowerKey : IDBKeyData();
116
117     auto lowestInRange = m_orderedKeys.lower_bound(range.lowerKey);
118
119     if (lowestInRange == m_orderedKeys.end())
120         return { };
121
122     if (range.lowerOpen && *lowestInRange == range.lowerKey)
123         ++lowestInRange;
124
125     if (lowestInRange == m_orderedKeys.end())
126         return { };
127
128     if (!range.upperKey.isNull()) {
129         if (lowestInRange->compare(range.upperKey) > 0)
130             return { };
131         if (range.upperOpen && *lowestInRange == range.upperKey)
132             return { };
133     }
134
135     return *lowestInRange;
136 }
137
138 } // namespace IDBServer
139 } // namespace WebCore
140
141 #endif // ENABLE(INDEXED_DATABASE)