2e8cedc7d9ec1faafa8a3dc433ea8b66a69c987c
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / IDBKeyData.cpp
1 /*
2  * Copyright (C) 2014 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "IDBKeyData.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "KeyedCoding.h"
32 #include <wtf/text/StringBuilder.h>
33
34 namespace WebCore {
35
36 IDBKeyData::IDBKeyData(const IDBKey* key)
37     : m_type(KeyType::Invalid)
38 {
39     if (!key) {
40         m_isNull = true;
41         return;
42     }
43
44     m_type = key->type();
45
46     switch (m_type) {
47     case KeyType::Invalid:
48         break;
49     case KeyType::Array: {
50         m_value = Vector<IDBKeyData>();
51         auto& array = WTF::get<Vector<IDBKeyData>>(m_value);
52         for (auto& key2 : key->array())
53             array.append(IDBKeyData(key2.get()));
54         break;
55     }
56     case KeyType::Binary:
57         m_value = key->binary();
58         break;
59     case KeyType::String:
60         m_value = key->string();
61         break;
62     case KeyType::Date:
63         m_value = key->date();
64         break;
65     case KeyType::Number:
66         m_value = key->number();
67         break;
68     case KeyType::Max:
69     case KeyType::Min:
70         break;
71     }
72 }
73
74 RefPtr<IDBKey> IDBKeyData::maybeCreateIDBKey() const
75 {
76     if (m_isNull)
77         return nullptr;
78
79     switch (m_type) {
80     case KeyType::Invalid:
81         return IDBKey::createInvalid();
82     case KeyType::Array: {
83         Vector<RefPtr<IDBKey>> array;
84         for (auto& keyData : WTF::get<Vector<IDBKeyData>>(m_value)) {
85             array.append(keyData.maybeCreateIDBKey());
86             ASSERT(array.last());
87         }
88         return IDBKey::createArray(array);
89     }
90     case KeyType::Binary:
91         return IDBKey::createBinary(WTF::get<ThreadSafeDataBuffer>(m_value));
92     case KeyType::String:
93         return IDBKey::createString(WTF::get<String>(m_value));
94     case KeyType::Date:
95         return IDBKey::createDate(WTF::get<double>(m_value));
96     case KeyType::Number:
97         return IDBKey::createNumber(WTF::get<double>(m_value));
98     case KeyType::Max:
99     case KeyType::Min:
100         ASSERT_NOT_REACHED();
101         return nullptr;
102     }
103
104     ASSERT_NOT_REACHED();
105     return nullptr;
106 }
107
108 IDBKeyData::IDBKeyData(const IDBKeyData& that, IsolatedCopyTag)
109 {
110     isolatedCopy(that, *this);
111 }
112
113 IDBKeyData IDBKeyData::isolatedCopy() const
114 {
115     return { *this, IsolatedCopy };
116 }
117
118 void IDBKeyData::isolatedCopy(const IDBKeyData& source, IDBKeyData& destination)
119 {
120     destination.m_type = source.m_type;
121     destination.m_isNull = source.m_isNull;
122
123     switch (source.m_type) {
124     case KeyType::Invalid:
125         return;
126     case KeyType::Array: {
127         destination.m_value = Vector<IDBKeyData>();
128         auto& destinationArray = WTF::get<Vector<IDBKeyData>>(destination.m_value);
129         for (auto& key : WTF::get<Vector<IDBKeyData>>(source.m_value))
130             destinationArray.append(key.isolatedCopy());
131         return;
132     }
133     case KeyType::Binary:
134         destination.m_value = WTF::get<ThreadSafeDataBuffer>(source.m_value);
135         return;
136     case KeyType::String:
137         destination.m_value = WTF::get<String>(source.m_value).isolatedCopy();
138         return;
139     case KeyType::Date:
140     case KeyType::Number:
141         destination.m_value = WTF::get<double>(source.m_value);
142         return;
143     case KeyType::Max:
144     case KeyType::Min:
145         return;
146     }
147
148     ASSERT_NOT_REACHED();
149 }
150
151 void IDBKeyData::encode(KeyedEncoder& encoder) const
152 {
153     encoder.encodeBool("null", m_isNull);
154     if (m_isNull)
155         return;
156
157     encoder.encodeEnum("type", m_type);
158
159     switch (m_type) {
160     case KeyType::Invalid:
161         return;
162     case KeyType::Array: {
163         auto& array = WTF::get<Vector<IDBKeyData>>(m_value);
164         encoder.encodeObjects("array", array.begin(), array.end(), [](KeyedEncoder& encoder, const IDBKeyData& key) {
165             key.encode(encoder);
166         });
167         return;
168     }
169     case KeyType::Binary: {
170         auto* data = WTF::get<ThreadSafeDataBuffer>(m_value).data();
171         encoder.encodeBool("hasBinary", !!data);
172         if (data)
173             encoder.encodeBytes("binary", data->data(), data->size());
174         return;
175     }
176     case KeyType::String:
177         encoder.encodeString("string", WTF::get<String>(m_value));
178         return;
179     case KeyType::Date:
180     case KeyType::Number:
181         encoder.encodeDouble("number", WTF::get<double>(m_value));
182         return;
183     case KeyType::Max:
184     case KeyType::Min:
185         return;
186     }
187
188     ASSERT_NOT_REACHED();
189 }
190
191 bool IDBKeyData::decode(KeyedDecoder& decoder, IDBKeyData& result)
192 {
193     if (!decoder.decodeBool("null", result.m_isNull))
194         return false;
195
196     if (result.m_isNull)
197         return true;
198
199     auto enumFunction = [](int64_t value) {
200         return value == KeyType::Max
201             || value == KeyType::Invalid
202             || value == KeyType::Array
203             || value == KeyType::Binary
204             || value == KeyType::String
205             || value == KeyType::Date
206             || value == KeyType::Number
207             || value == KeyType::Min;
208     };
209     if (!decoder.decodeEnum("type", result.m_type, enumFunction))
210         return false;
211
212     if (result.m_type == KeyType::Invalid)
213         return true;
214
215     if (result.m_type == KeyType::Max)
216         return true;
217
218     if (result.m_type == KeyType::Min)
219         return true;
220
221     if (result.m_type == KeyType::String) {
222         result.m_value = String();
223         return decoder.decodeString("string", WTF::get<String>(result.m_value));
224     }
225
226     if (result.m_type == KeyType::Number || result.m_type == KeyType::Date) {
227         result.m_value = 0.0;
228         return decoder.decodeDouble("number", WTF::get<double>(result.m_value));
229     }
230
231     if (result.m_type == KeyType::Binary) {
232         result.m_value = ThreadSafeDataBuffer();
233
234         bool hasBinaryData;
235         if (!decoder.decodeBool("hasBinary", hasBinaryData))
236             return false;
237
238         if (!hasBinaryData)
239             return true;
240
241         Vector<uint8_t> bytes;
242         if (!decoder.decodeBytes("binary", bytes))
243             return false;
244
245         result.m_value = ThreadSafeDataBuffer::create(WTFMove(bytes));
246         return true;
247     }
248
249     ASSERT(result.m_type == KeyType::Array);
250
251     auto arrayFunction = [](KeyedDecoder& decoder, IDBKeyData& result) {
252         return decode(decoder, result);
253     };
254     
255     result.m_value = Vector<IDBKeyData>();
256     return decoder.decodeObjects("array", WTF::get<Vector<IDBKeyData>>(result.m_value), arrayFunction);
257 }
258
259 int IDBKeyData::compare(const IDBKeyData& other) const
260 {
261     if (m_type == KeyType::Invalid) {
262         if (other.m_type != KeyType::Invalid)
263             return -1;
264         if (other.m_type == KeyType::Invalid)
265             return 0;
266     } else if (other.m_type == KeyType::Invalid)
267         return 1;
268
269     // The IDBKey::m_type enum is in reverse sort order.
270     if (m_type != other.m_type)
271         return m_type < other.m_type ? 1 : -1;
272
273     // The types are the same, so handle actual value comparison.
274     switch (m_type) {
275     case KeyType::Invalid:
276         // Invalid type should have been fully handled above
277         ASSERT_NOT_REACHED();
278         return 0;
279     case KeyType::Array: {
280         auto& array = WTF::get<Vector<IDBKeyData>>(m_value);
281         auto& otherArray = WTF::get<Vector<IDBKeyData>>(other.m_value);
282         for (size_t i = 0; i < array.size() && i < otherArray.size(); ++i) {
283             if (int result = array[i].compare(otherArray[i]))
284                 return result;
285         }
286         if (array.size() < otherArray.size())
287             return -1;
288         if (array.size() > otherArray.size())
289             return 1;
290         return 0;
291     }
292     case KeyType::Binary:
293         return compareBinaryKeyData(WTF::get<ThreadSafeDataBuffer>(m_value), WTF::get<ThreadSafeDataBuffer>(other.m_value));
294     case KeyType::String:
295         return codePointCompare(WTF::get<String>(m_value), WTF::get<String>(other.m_value));
296     case KeyType::Date:
297     case KeyType::Number: {
298         auto number = WTF::get<double>(m_value);
299         auto otherNumber = WTF::get<double>(other.m_value);
300
301         if (number == otherNumber)
302             return 0;
303         return number > otherNumber ? 1 : -1;
304     }
305     case KeyType::Max:
306     case KeyType::Min:
307         return 0;
308     }
309
310     ASSERT_NOT_REACHED();
311     return 0;
312 }
313
314 #if !LOG_DISABLED
315 String IDBKeyData::loggingString() const
316 {
317     if (m_isNull)
318         return "<null>";
319
320     String result;
321
322     switch (m_type) {
323     case KeyType::Invalid:
324         return "<invalid>";
325     case KeyType::Array: {
326         StringBuilder builder;
327         builder.appendLiteral("<array> - { ");
328         auto& array = WTF::get<Vector<IDBKeyData>>(m_value);
329         for (size_t i = 0; i < array.size(); ++i) {
330             builder.append(array[i].loggingString());
331             if (i < array.size() - 1)
332                 builder.appendLiteral(", ");
333         }
334         builder.appendLiteral(" }");
335         result = builder.toString();
336         break;
337     }
338     case KeyType::Binary: {
339         StringBuilder builder;
340         builder.append("<binary> - ");
341
342         auto* data = WTF::get<ThreadSafeDataBuffer>(m_value).data();
343         if (!data) {
344             builder.append("(null)");
345             result = builder.toString();
346             break;
347         }
348
349         size_t i = 0;
350         for (; i < 8 && i < data->size(); ++i)
351             builder.append(String::format("%02x", data->at(i)));
352
353         if (data->size() > 8)
354             builder.append("...");
355
356         result = builder.toString();
357         break;
358     }
359     case KeyType::String:
360         result = "<string> - " + WTF::get<String>(m_value);
361         break;
362     case KeyType::Date:
363         return String::format("<date> - %f", WTF::get<double>(m_value));
364     case KeyType::Number:
365         return String::format("<number> - %f", WTF::get<double>(m_value));
366     case KeyType::Max:
367         return "<maximum>";
368     case KeyType::Min:
369         return "<minimum>";
370     }
371
372     if (result.length() > 150) {
373         result.truncate(147);
374         result.append("..."_s);
375     }
376
377     return result;
378 }
379 #endif
380
381 void IDBKeyData::setArrayValue(const Vector<IDBKeyData>& value)
382 {
383     *this = IDBKeyData();
384     m_value = value;
385     m_type = KeyType::Array;
386     m_isNull = false;
387 }
388
389 void IDBKeyData::setBinaryValue(const ThreadSafeDataBuffer& value)
390 {
391     *this = IDBKeyData();
392     m_value = value;
393     m_type = KeyType::Binary;
394     m_isNull = false;
395 }
396
397 void IDBKeyData::setStringValue(const String& value)
398 {
399     *this = IDBKeyData();
400     m_value = value;
401     m_type = KeyType::String;
402     m_isNull = false;
403 }
404
405 void IDBKeyData::setDateValue(double value)
406 {
407     *this = IDBKeyData();
408     m_value = value;
409     m_type = KeyType::Date;
410     m_isNull = false;
411 }
412
413 void IDBKeyData::setNumberValue(double value)
414 {
415     *this = IDBKeyData();
416     m_value = value;
417     m_type = KeyType::Number;
418     m_isNull = false;
419 }
420
421 IDBKeyData IDBKeyData::deletedValue()
422 {
423     IDBKeyData result;
424     result.m_isNull = false;
425     result.m_isDeletedValue = true;
426     return result;
427 }
428
429 bool IDBKeyData::isValid() const
430 {
431     if (m_type == KeyType::Invalid)
432         return false;
433     
434     if (m_type == KeyType::Array) {
435         for (auto& key : array()) {
436             if (!key.isValid())
437                 return false;
438         }
439     }
440
441     return true;
442 }
443
444 bool IDBKeyData::operator<(const IDBKeyData& rhs) const
445 {
446     return compare(rhs) < 0;
447 }
448
449 bool IDBKeyData::operator==(const IDBKeyData& other) const
450 {
451     if (m_type != other.m_type || m_isNull != other.m_isNull || m_isDeletedValue != other.m_isDeletedValue)
452         return false;
453     switch (m_type) {
454     case KeyType::Invalid:
455     case KeyType::Max:
456     case KeyType::Min:
457         return true;
458     case KeyType::Number:
459     case KeyType::Date:
460         return WTF::get<double>(m_value) == WTF::get<double>(other.m_value);
461     case KeyType::String:
462         return WTF::get<String>(m_value) == WTF::get<String>(other.m_value);
463     case KeyType::Binary:
464         return WTF::get<ThreadSafeDataBuffer>(m_value) == WTF::get<ThreadSafeDataBuffer>(other.m_value);
465     case KeyType::Array:
466         return WTF::get<Vector<IDBKeyData>>(m_value) == WTF::get<Vector<IDBKeyData>>(other.m_value);
467     }
468     RELEASE_ASSERT_NOT_REACHED();
469 }
470
471 } // namespace WebCore
472
473 #endif // ENABLE(INDEXED_DATABASE)