OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" | |
6 | |
7 #include <iterator> | |
8 #include <limits> | |
9 #include <string> | |
10 | |
11 #include "base/logging.h" | |
12 #include "base/string16.h" | |
13 #include "base/sys_byteorder.h" | |
14 #include "content/browser/indexed_db/leveldb/leveldb_slice.h" | |
15 #include "content/common/indexed_db/indexed_db_key.h" | |
16 #include "content/common/indexed_db/indexed_db_key_path.h" | |
17 #include "third_party/WebKit/Source/Platform/chromium/public/WebIDBKeyPath.h" | |
18 | |
19 // LevelDB stores key/value pairs. Keys and values are strings of bytes, | |
20 // normally of type std::vector<char>. | |
21 // | |
22 // The keys in the backing store are variable-length tuples with different types | |
23 // of fields. Each key in the backing store starts with a ternary prefix: | |
24 // (database id, object store id, index id). For each, 0 is reserved for | |
25 // meta-data. | |
26 // The prefix makes sure that data for a specific database, object store, and | |
27 // index are grouped together. The locality is important for performance: common | |
28 // operations should only need a minimal number of seek operations. For example, | |
29 // all the meta-data for a database is grouped together so that reading that | |
30 // meta-data only requires one seek. | |
31 // | |
32 // Each key type has a class (in square brackets below) which knows how to | |
33 // encode, decode, and compare that key type. | |
34 // | |
35 // Global meta-data have keys with prefix (0,0,0), followed by a type byte: | |
36 // | |
37 // <0, 0, 0, 0> => | |
38 // IndexedDB/LevelDB schema version [SchemaVersionKey] | |
39 // <0, 0, 0, 1> => The maximum | |
40 // database id ever allocated [MaxDatabaseIdKey] | |
41 // <0, 0, 0, 2> => | |
42 // SerializedScriptValue version [DataVersionKey] | |
43 // <0, 0, 0, 100, database id> => Existence | |
44 // implies the database id is in the free list [DatabaseFreeListKey] | |
45 // <0, 0, 0, 201, utf16 origin name, utf16 database name> => Database id | |
46 // [DatabaseNameKey] | |
47 // | |
48 // | |
49 // Database meta-data: | |
50 // | |
51 // Again, the prefix is followed by a type byte. | |
52 // | |
53 // <database id, 0, 0, 0> => utf16 origin name [DatabaseMetaDataKey] | |
54 // <database id, 0, 0, 1> => utf16 database name [DatabaseMetaDataKey] | |
55 // <database id, 0, 0, 2> => utf16 user version data [DatabaseMetaDataKey] | |
56 // <database id, 0, 0, 3> => maximum object store id ever allocated | |
57 // [DatabaseMetaDataKey] | |
58 // <database id, 0, 0, 4> => user integer version (var int) | |
59 // [DatabaseMetaDataKey] | |
60 // | |
61 // | |
62 // Object store meta-data: | |
63 // | |
64 // The prefix is followed by a type byte, then a variable-length integer, | |
65 // and then another type byte. | |
66 // | |
67 // <database id, 0, 0, 50, object store id, 0> => utf16 object store name | |
68 // [ObjectStoreMetaDataKey] | |
69 // <database id, 0, 0, 50, object store id, 1> => utf16 key path | |
70 // [ObjectStoreMetaDataKey] | |
71 // <database id, 0, 0, 50, object store id, 2> => has auto increment | |
72 // [ObjectStoreMetaDataKey] | |
73 // <database id, 0, 0, 50, object store id, 3> => is evictable | |
74 // [ObjectStoreMetaDataKey] | |
75 // <database id, 0, 0, 50, object store id, 4> => last "version" number | |
76 // [ObjectStoreMetaDataKey] | |
77 // <database id, 0, 0, 50, object store id, 5> => maximum index id ever | |
78 // allocated [ObjectStoreMetaDataKey] | |
79 // <database id, 0, 0, 50, object store id, 6> => has key path (vs. null) | |
80 // [ObjectStoreMetaDataKey] | |
81 // <database id, 0, 0, 50, object store id, 7> => key generator current | |
82 // number [ObjectStoreMetaDataKey] | |
83 // | |
84 // | |
85 // Index meta-data: | |
86 // | |
87 // The prefix is followed by a type byte, then two variable-length integers, | |
88 // and then another type byte. | |
89 // | |
90 // <database id, 0, 0, 100, object store id, index id, 0> => utf16 index | |
91 // name [IndexMetaDataKey] | |
92 // <database id, 0, 0, 100, object store id, index id, 1> => are index keys | |
93 // unique [IndexMetaDataKey] | |
94 // <database id, 0, 0, 100, object store id, index id, 2> => utf16 key path | |
95 // [IndexMetaDataKey] | |
96 // <database id, 0, 0, 100, object store id, index id, 3> => is index | |
97 // multi-entry [IndexMetaDataKey] | |
98 // | |
99 // | |
100 // Other object store and index meta-data: | |
101 // | |
102 // The prefix is followed by a type byte. The object store and index id are | |
103 // variable length integers, the utf16 strings are variable length strings. | |
104 // | |
105 // <database id, 0, 0, 150, object store id> => existence | |
106 // implies the object store id is in the free list [ObjectStoreFreeListKey] | |
107 // <database id, 0, 0, 151, object store id, index id> => existence | |
108 // implies the index id is in the free list [IndexFreeListKey] | |
109 // <database id, 0, 0, 200, utf16 object store name> => object | |
110 // store id [ObjectStoreNamesKey] | |
111 // <database id, 0, 0, 201, object store id, utf16 index name> => index id | |
112 // [IndexNamesKey] | |
113 // | |
114 // | |
115 // Object store data: | |
116 // | |
117 // The prefix is followed by a type byte. The user key is an encoded | |
118 // IndexedDBKey. | |
119 // | |
120 // <database id, object store id, 1, user key> => "version", serialized | |
121 // script value [ObjectStoreDataKey] | |
122 // | |
123 // | |
124 // "Exists" entry: | |
125 // | |
126 // The prefix is followed by a type byte. The user key is an encoded | |
127 // IndexedDBKey. | |
128 // | |
129 // <database id, object store id, 2, user key> => "version" [ExistsEntryKey] | |
130 // | |
131 // | |
132 // Index data: | |
133 // | |
134 // The prefix is followed by a type byte. The index key is an encoded | |
135 // IndexedDBKey. The sequence number is a variable length integer. | |
136 // The primary key is an encoded IndexedDBKey. | |
137 // | |
138 // <database id, object store id, index id, index key, sequence number, | |
139 // primary key> => "version", primary key [IndexDataKey] | |
140 // | |
141 // (The sequence number is obsolete; it was used to allow two entries with | |
142 // the same user (index) key in non-unique indexes prior to the inclusion of | |
143 // the primary key in the data. The "version" field is used to weed out | |
144 // stale | |
145 // index data. Whenever new object store data is inserted, it gets a new | |
146 // "version" number, and new index data is written with this number. When | |
147 // the index is used for look-ups, entries are validated against the | |
148 // "exists" entries, and records with old "version" numbers are deleted | |
149 // when they are encountered in get_primary_key_via_index, | |
150 // IndexCursorImpl::load_current_row, and | |
151 // IndexKeyCursorImpl::load_current_row). | |
152 | |
153 using WebKit::WebIDBKey; | |
154 using WebKit::WebIDBKeyPath; | |
155 | |
156 namespace content { | |
157 | |
158 // As most of the IndexedDBKeys and encoded values are short, we | |
159 // initialize some Vectors with a default inline buffer size to reduce | |
160 // the memory re-allocations when the Vectors are appended. | |
161 static const size_t kDefaultInlineBufferSize = 32; | |
162 | |
163 static const unsigned char kIndexedDBKeyNullTypeByte = 0; | |
164 static const unsigned char kIndexedDBKeyStringTypeByte = 1; | |
165 static const unsigned char kIndexedDBKeyDateTypeByte = 2; | |
166 static const unsigned char kIndexedDBKeyNumberTypeByte = 3; | |
167 static const unsigned char kIndexedDBKeyArrayTypeByte = 4; | |
168 static const unsigned char kIndexedDBKeyMinKeyTypeByte = 5; | |
169 | |
170 static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0; | |
171 static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0; | |
172 | |
173 static const unsigned char kObjectStoreDataIndexId = 1; | |
174 static const unsigned char kExistsEntryIndexId = 2; | |
175 | |
176 static const unsigned char kSchemaVersionTypeByte = 0; | |
177 static const unsigned char kMaxDatabaseIdTypeByte = 1; | |
178 static const unsigned char kDataVersionTypeByte = 2; | |
179 static const unsigned char kMaxSimpleGlobalMetaDataTypeByte = | |
180 3; // Insert before this and increment. | |
181 static const unsigned char kDatabaseFreeListTypeByte = 100; | |
182 static const unsigned char kDatabaseNameTypeByte = 201; | |
183 | |
184 static const unsigned char kObjectStoreMetaDataTypeByte = 50; | |
185 static const unsigned char kIndexMetaDataTypeByte = 100; | |
186 static const unsigned char kObjectStoreFreeListTypeByte = 150; | |
187 static const unsigned char kIndexFreeListTypeByte = 151; | |
188 static const unsigned char kObjectStoreNamesTypeByte = 200; | |
189 static const unsigned char kIndexNamesKeyTypeByte = 201; | |
190 | |
191 static const unsigned char kObjectMetaDataTypeMaximum = 255; | |
192 static const unsigned char kIndexMetaDataTypeMaximum = 255; | |
193 | |
194 const unsigned char kMinimumIndexId = 30; | |
195 | |
196 std::vector<char> EncodeByte(unsigned char c) { | |
197 std::vector<char> v; | |
198 v.reserve(kDefaultInlineBufferSize); | |
199 v.push_back(c); | |
200 | |
201 DCHECK_LE(v.size(), kDefaultInlineBufferSize); | |
202 return v; | |
203 } | |
204 | |
205 const char* DecodeByte(const char* p, | |
206 const char* limit, | |
207 unsigned char& found_char) { | |
208 if (p >= limit) | |
209 return 0; | |
210 | |
211 found_char = *p++; | |
212 return p; | |
213 } | |
214 | |
215 std::vector<char> MaxIDBKey() { return EncodeByte(kIndexedDBKeyNullTypeByte); } | |
216 | |
217 std::vector<char> MinIDBKey() { | |
218 return EncodeByte(kIndexedDBKeyMinKeyTypeByte); | |
219 } | |
220 | |
221 std::vector<char> EncodeBool(bool b) { | |
222 std::vector<char> ret; | |
223 ret.reserve(kDefaultInlineBufferSize); | |
224 ret.push_back(b ? 1 : 0); | |
225 | |
226 DCHECK_LE(ret.size(), kDefaultInlineBufferSize); | |
227 return ret; | |
228 } | |
229 | |
230 bool DecodeBool(const char* begin, const char* end) { | |
231 DCHECK_LT(begin, end); | |
232 return !!*begin; | |
233 } | |
234 | |
235 std::vector<char> EncodeInt(int64 nParam) { | |
236 #ifndef NDEBUG | |
237 // Exercised by unit tests in debug only. | |
238 DCHECK_GE(nParam, 0); | |
239 #endif | |
240 uint64 n = static_cast<uint64>(nParam); | |
241 std::vector<char> ret; | |
242 ret.reserve(kDefaultInlineBufferSize); | |
243 | |
244 do { | |
245 unsigned char c = n; | |
246 ret.push_back(c); | |
247 n >>= 8; | |
248 } while (n); | |
249 | |
250 DCHECK_LE(ret.size(), kDefaultInlineBufferSize); | |
251 return ret; | |
252 } | |
253 | |
254 static int CompareInts(int64 a, int64 b) { | |
255 #ifndef NDEBUG | |
256 // Exercised by unit tests in debug only. | |
257 DCHECK_GE(a, 0); | |
258 DCHECK_GE(b, 0); | |
259 #endif | |
260 int64 diff = a - b; | |
261 if (diff < 0) | |
262 return -1; | |
263 if (diff > 0) | |
264 return 1; | |
265 return 0; | |
266 } | |
267 | |
268 std::vector<char> EncodeVarInt(int64 nParam) { | |
269 #ifndef NDEBUG | |
270 // Exercised by unit tests in debug only. | |
271 DCHECK_GE(nParam, 0); | |
272 #endif | |
273 uint64 n = static_cast<uint64>(nParam); | |
274 std::vector<char> ret; | |
275 ret.reserve(kDefaultInlineBufferSize); | |
276 | |
277 do { | |
278 unsigned char c = n & 0x7f; | |
279 n >>= 7; | |
280 if (n) | |
281 c |= 0x80; | |
282 ret.push_back(c); | |
283 } while (n); | |
284 | |
285 DCHECK_LE(ret.size(), kDefaultInlineBufferSize); | |
286 return ret; | |
287 } | |
288 | |
289 const char* DecodeVarInt(const char* p, const char* limit, int64& found_int) { | |
290 DCHECK_GE(limit, p); | |
291 found_int = 0; | |
292 int shift = 0; | |
293 | |
294 do { | |
295 if (p >= limit) | |
296 return 0; | |
297 | |
298 unsigned char c = *p; | |
299 found_int |= static_cast<int64>(c & 0x7f) << shift; | |
300 shift += 7; | |
301 } while (*p++ & 0x80); | |
302 return p; | |
303 } | |
304 | |
305 std::vector<char> EncodeString(const string16& s) { | |
306 // Backing store is UTF-16BE, convert from host endianness. | |
307 size_t length = s.length(); | |
308 std::vector<char> ret(length * sizeof(char16)); | |
309 | |
310 const char16* src = s.c_str(); | |
311 char16* dst = reinterpret_cast<char16*>(&*ret.begin()); | |
312 for (unsigned i = 0; i < length; ++i) | |
313 *dst++ = htons(*src++); | |
314 | |
315 return ret; | |
316 } | |
317 | |
318 string16 DecodeString(const char* start, const char* end) { | |
319 // Backing store is UTF-16BE, convert to host endianness. | |
320 DCHECK_GE(end, start); | |
321 DCHECK(!((end - start) % sizeof(char16))); | |
322 | |
323 size_t length = (end - start) / sizeof(char16); | |
324 string16 decoded; | |
325 decoded.reserve(length); | |
326 const char16* encoded = reinterpret_cast<const char16*>(start); | |
327 for (unsigned i = 0; i < length; ++i) | |
328 decoded.push_back(ntohs(*encoded++)); | |
329 return decoded; | |
330 } | |
331 | |
332 std::vector<char> EncodeStringWithLength(const string16& s) { | |
333 std::vector<char> result = EncodeVarInt(s.length()); | |
334 std::vector<char> encoded_value = EncodeString(s); | |
335 result.insert(result.end(), encoded_value.begin(), encoded_value.end()); | |
336 return result; | |
337 } | |
338 | |
339 const char* DecodeStringWithLength(const char* p, | |
340 const char* limit, | |
341 string16& found_string) { | |
342 DCHECK_GE(limit, p); | |
343 int64 len; | |
344 p = DecodeVarInt(p, limit, len); | |
345 if (!p || len < 0 || p + len * 2 > limit) | |
346 return 0; | |
347 | |
348 found_string = DecodeString(p, p + len * 2); | |
349 p += len * 2; | |
350 return p; | |
351 } | |
352 | |
353 int CompareEncodedStringsWithLength(const char*& p, | |
354 const char* limit_p, | |
355 const char*& q, | |
356 const char* limit_q, | |
357 bool& ok) { | |
358 DCHECK_NE(&p, &q); | |
359 DCHECK_GE(limit_p, p); | |
360 DCHECK_GE(limit_q, q); | |
361 int64 len_p, len_q; | |
362 p = DecodeVarInt(p, limit_p, len_p); | |
363 q = DecodeVarInt(q, limit_q, len_q); | |
364 if (!p || !q || len_p < 0 || len_q < 0) { | |
365 ok = false; | |
366 return 0; | |
367 } | |
368 DCHECK(p && q); | |
369 DCHECK_GE(len_p, 0); | |
370 DCHECK_GE(len_q, 0); | |
371 DCHECK_LE(p + len_p * 2, limit_p); | |
372 DCHECK_LE(q + len_q * 2, limit_q); | |
373 | |
374 const char* start_p = p; | |
375 const char* start_q = q; | |
376 p += len_p * 2; | |
377 q += len_q * 2; | |
378 | |
379 if (p > limit_p || q > limit_q) { | |
380 ok = false; | |
381 return 0; | |
382 } | |
383 | |
384 ok = true; | |
385 const size_t lmin = static_cast<size_t>(len_p < len_q ? len_p : len_q); | |
386 if (int x = memcmp(start_p, start_q, lmin * 2)) | |
387 return x; | |
388 | |
389 if (len_p == len_q) | |
390 return 0; | |
391 | |
392 return (len_p > len_q) ? 1 : -1; | |
393 } | |
394 | |
395 std::vector<char> EncodeDouble(double x) { | |
396 // TODO(jsbell): It would be nice if we could be byte order independent. | |
397 const char* p = reinterpret_cast<char*>(&x); | |
398 std::vector<char> v; | |
399 v.reserve(kDefaultInlineBufferSize); | |
400 v.insert(v.end(), p, p + sizeof(x)); | |
401 | |
402 DCHECK_LE(v.size(), kDefaultInlineBufferSize); | |
403 return v; | |
404 } | |
405 | |
406 const char* DecodeDouble(const char* p, const char* limit, double* d) { | |
407 if (p + sizeof(*d) > limit) | |
408 return 0; | |
409 | |
410 char* x = reinterpret_cast<char*>(d); | |
411 for (size_t i = 0; i < sizeof(*d); ++i) | |
412 *x++ = *p++; | |
413 return p; | |
414 } | |
415 | |
416 std::vector<char> EncodeIDBKey(const IndexedDBKey& key) { | |
417 std::vector<char> ret; | |
418 ret.reserve(kDefaultInlineBufferSize); | |
419 EncodeIDBKey(key, ret); | |
420 return ret; | |
421 } | |
422 | |
423 void EncodeIDBKey(const IndexedDBKey& key, std::vector<char>& into) { | |
424 size_t previous_size = into.size(); | |
425 DCHECK(key.IsValid()); | |
426 switch (key.type()) { | |
427 case WebIDBKey::NullType: | |
428 case WebIDBKey::InvalidType: | |
429 case WebIDBKey::MinType: { | |
430 NOTREACHED(); | |
431 into.push_back(kIndexedDBKeyNullTypeByte); | |
432 return; | |
433 } | |
434 case WebIDBKey::ArrayType: { | |
435 into.push_back(kIndexedDBKeyArrayTypeByte); | |
436 size_t length = key.array().size(); | |
437 std::vector<char> encoded_length = EncodeVarInt(length); | |
438 into.insert(into.end(), encoded_length.begin(), encoded_length.end()); | |
439 for (size_t i = 0; i < length; ++i) | |
440 EncodeIDBKey(key.array()[i], into); | |
441 DCHECK_GT(into.size(), previous_size); | |
442 return; | |
443 } | |
444 case WebIDBKey::StringType: { | |
445 into.push_back(kIndexedDBKeyStringTypeByte); | |
446 std::vector<char> tmp = EncodeStringWithLength(key.string()); | |
447 into.insert(into.end(), tmp.begin(), tmp.end()); | |
448 DCHECK_GT(into.size(), previous_size); | |
449 return; | |
450 } | |
451 case WebIDBKey::DateType: { | |
452 into.push_back(kIndexedDBKeyDateTypeByte); | |
453 std::vector<char> tmp = EncodeDouble(key.date()); | |
454 into.insert(into.end(), tmp.begin(), tmp.end()); | |
455 DCHECK_EQ(static_cast<size_t>(9), | |
456 static_cast<size_t>(into.size() - previous_size)); | |
457 return; | |
458 } | |
459 case WebIDBKey::NumberType: { | |
460 into.push_back(kIndexedDBKeyNumberTypeByte); | |
461 std::vector<char> tmp = EncodeDouble(key.number()); | |
462 into.insert(into.end(), tmp.begin(), tmp.end()); | |
463 DCHECK_EQ(static_cast<size_t>(9), | |
464 static_cast<size_t>(into.size() - previous_size)); | |
465 return; | |
466 } | |
467 } | |
468 | |
469 NOTREACHED(); | |
470 } | |
471 | |
472 const char* DecodeIDBKey(const char* p, | |
473 const char* limit, | |
474 scoped_ptr<IndexedDBKey>* found_key) { | |
475 DCHECK_GE(limit, p); | |
476 if (p >= limit) | |
477 return 0; | |
478 | |
479 unsigned char type = *p++; | |
480 | |
481 switch (type) { | |
482 case kIndexedDBKeyNullTypeByte: | |
483 *found_key = make_scoped_ptr(new IndexedDBKey()); | |
484 return p; | |
485 | |
486 case kIndexedDBKeyArrayTypeByte: { | |
487 int64 length; | |
488 p = DecodeVarInt(p, limit, length); | |
489 if (!p || length < 0) | |
490 return 0; | |
491 IndexedDBKey::KeyArray array; | |
492 while (length--) { | |
493 scoped_ptr<IndexedDBKey> key; | |
494 p = DecodeIDBKey(p, limit, &key); | |
495 if (!p) | |
496 return 0; | |
497 array.push_back(*key); | |
498 } | |
499 *found_key = make_scoped_ptr(new IndexedDBKey(array)); | |
500 return p; | |
501 } | |
502 case kIndexedDBKeyStringTypeByte: { | |
503 string16 s; | |
504 p = DecodeStringWithLength(p, limit, s); | |
505 if (!p) | |
506 return 0; | |
507 *found_key = make_scoped_ptr(new IndexedDBKey(s)); | |
508 return p; | |
509 } | |
510 case kIndexedDBKeyDateTypeByte: { | |
511 double d; | |
512 p = DecodeDouble(p, limit, &d); | |
513 if (!p) | |
514 return 0; | |
515 *found_key = make_scoped_ptr(new IndexedDBKey(d, WebIDBKey::DateType)); | |
516 return p; | |
517 } | |
518 case kIndexedDBKeyNumberTypeByte: { | |
519 double d; | |
520 p = DecodeDouble(p, limit, &d); | |
521 if (!p) | |
522 return 0; | |
523 *found_key = make_scoped_ptr(new IndexedDBKey(d, WebIDBKey::NumberType)); | |
524 return p; | |
525 } | |
526 } | |
527 | |
528 NOTREACHED(); | |
529 return 0; | |
530 } | |
531 | |
532 const char* ExtractEncodedIDBKey(const char* start, | |
533 const char* limit, | |
534 std::vector<char>* result = 0) { | |
535 const char* p = start; | |
536 if (p >= limit) | |
537 return 0; | |
538 | |
539 unsigned char type = *p++; | |
540 | |
541 switch (type) { | |
542 case kIndexedDBKeyNullTypeByte: | |
543 case kIndexedDBKeyMinKeyTypeByte: | |
544 break; | |
545 case kIndexedDBKeyArrayTypeByte: { | |
546 int64 length; | |
547 p = DecodeVarInt(p, limit, length); | |
548 if (!p || length < 0) | |
549 return 0; | |
550 while (length--) { | |
551 p = ExtractEncodedIDBKey(p, limit); | |
552 if (!p) | |
553 return 0; | |
554 } | |
555 break; | |
556 } | |
557 case kIndexedDBKeyStringTypeByte: { | |
558 int64 length; | |
559 p = DecodeVarInt(p, limit, length); | |
560 if (!p || length < 0 || p + length * 2 > limit) | |
561 return 0; | |
562 p += length * 2; | |
563 break; | |
564 } | |
565 case kIndexedDBKeyDateTypeByte: | |
566 case kIndexedDBKeyNumberTypeByte: | |
567 if (p + sizeof(double) > limit) | |
568 return 0; | |
569 p += sizeof(double); | |
570 break; | |
571 } | |
572 | |
573 if (result) { | |
574 DCHECK(p); | |
575 DCHECK_LE(p, limit); | |
576 result->assign(start, p); | |
577 } | |
578 | |
579 return p; | |
580 } | |
581 | |
582 static WebIDBKey::Type KeyTypeByteToKeyType(unsigned char type) { | |
583 switch (type) { | |
584 case kIndexedDBKeyNullTypeByte: | |
585 return WebIDBKey::InvalidType; | |
586 case kIndexedDBKeyArrayTypeByte: | |
587 return WebIDBKey::ArrayType; | |
588 case kIndexedDBKeyStringTypeByte: | |
589 return WebIDBKey::StringType; | |
590 case kIndexedDBKeyDateTypeByte: | |
591 return WebIDBKey::DateType; | |
592 case kIndexedDBKeyNumberTypeByte: | |
593 return WebIDBKey::NumberType; | |
594 case kIndexedDBKeyMinKeyTypeByte: | |
595 return WebIDBKey::MinType; | |
596 } | |
597 | |
598 NOTREACHED(); | |
599 return WebIDBKey::InvalidType; | |
600 } | |
601 | |
602 static int CompareTypes(WebIDBKey::Type a, WebIDBKey::Type b) { return b - a; } | |
603 | |
604 int CompareEncodedIDBKeys(const char*& ptr_a, | |
605 const char* limit_a, | |
606 const char*& ptr_b, | |
607 const char* limit_b, | |
608 bool& ok) { | |
609 ok = true; | |
610 DCHECK_NE(&ptr_a, &ptr_b); | |
611 DCHECK_LT(ptr_a, limit_a); | |
612 DCHECK_LT(ptr_b, limit_b); | |
613 unsigned char type_a = *ptr_a++; | |
614 unsigned char type_b = *ptr_b++; | |
615 | |
616 if (int x = CompareTypes(KeyTypeByteToKeyType(type_a), | |
617 KeyTypeByteToKeyType(type_b))) | |
618 return x; | |
619 | |
620 switch (type_a) { | |
621 case kIndexedDBKeyNullTypeByte: | |
622 case kIndexedDBKeyMinKeyTypeByte: | |
623 // Null type or max type; no payload to compare. | |
624 return 0; | |
625 case kIndexedDBKeyArrayTypeByte: { | |
626 int64 length_a, length_b; | |
627 ptr_a = DecodeVarInt(ptr_a, limit_a, length_a); | |
628 ptr_b = DecodeVarInt(ptr_b, limit_b, length_b); | |
629 if (!ptr_a || !ptr_b || length_a < 0 || length_b < 0) { | |
630 ok = false; | |
631 return 0; | |
632 } | |
633 for (int64 i = 0; i < length_a && i < length_b; ++i) { | |
634 int result = CompareEncodedIDBKeys(ptr_a, limit_a, ptr_b, limit_b, ok); | |
635 if (!ok || result) | |
636 return result; | |
637 } | |
638 if (length_a < length_b) | |
639 return -1; | |
640 if (length_a > length_b) | |
641 return 1; | |
642 return 0; | |
643 } | |
644 case kIndexedDBKeyStringTypeByte: | |
645 return CompareEncodedStringsWithLength( | |
646 ptr_a, limit_a, ptr_b, limit_b, ok); | |
647 case kIndexedDBKeyDateTypeByte: | |
648 case kIndexedDBKeyNumberTypeByte: { | |
649 double d, e; | |
650 ptr_a = DecodeDouble(ptr_a, limit_a, &d); | |
651 ptr_b = DecodeDouble(ptr_b, limit_b, &e); | |
652 DCHECK(ptr_a); | |
653 DCHECK(ptr_b); | |
654 if (!ptr_a || !ptr_b) { | |
655 ok = false; | |
656 return 0; | |
657 } | |
658 if (d < e) | |
659 return -1; | |
660 if (d > e) | |
661 return 1; | |
662 return 0; | |
663 } | |
664 } | |
665 | |
666 NOTREACHED(); | |
667 return 0; | |
668 } | |
669 | |
670 int CompareEncodedIDBKeys(const std::vector<char>& key_a, | |
671 const std::vector<char>& key_b, | |
672 bool& ok) { | |
673 DCHECK_GE(key_a.size(), static_cast<size_t>(1)); | |
674 DCHECK_GE(key_b.size(), static_cast<size_t>(1)); | |
675 | |
676 const char* ptr_a = &*key_a.begin(); | |
677 const char* limit_a = &*key_a.rbegin() + 1; | |
678 const char* ptr_b = &*key_b.begin(); | |
679 const char* limit_b = &*key_b.rbegin() + 1; | |
680 | |
681 return CompareEncodedIDBKeys(ptr_a, limit_a, ptr_b, limit_b, ok); | |
682 } | |
683 | |
684 std::vector<char> EncodeIDBKeyPath(const IndexedDBKeyPath& key_path) { | |
685 // May be typed, or may be a raw string. An invalid leading | |
686 // byte is used to identify typed coding. New records are | |
687 // always written as typed. | |
688 std::vector<char> ret; | |
689 ret.reserve(kDefaultInlineBufferSize); | |
690 ret.push_back(kIndexedDBKeyPathTypeCodedByte1); | |
691 ret.push_back(kIndexedDBKeyPathTypeCodedByte2); | |
692 ret.push_back(static_cast<char>(key_path.type())); | |
693 switch (key_path.type()) { | |
694 case WebIDBKeyPath::NullType: | |
695 break; | |
696 case WebIDBKeyPath::StringType: { | |
697 std::vector<char> encoded_string = | |
698 EncodeStringWithLength(key_path.string()); | |
699 ret.insert(ret.end(), encoded_string.begin(), encoded_string.end()); | |
700 break; | |
701 } | |
702 case WebIDBKeyPath::ArrayType: { | |
703 const std::vector<string16>& array = key_path.array(); | |
704 size_t count = array.size(); | |
705 std::vector<char> encoded_count = EncodeVarInt(count); | |
706 ret.insert(ret.end(), encoded_count.begin(), encoded_count.end()); | |
707 for (size_t i = 0; i < count; ++i) { | |
708 std::vector<char> encoded_string = EncodeStringWithLength(array[i]); | |
709 ret.insert(ret.end(), encoded_string.begin(), encoded_string.end()); | |
710 } | |
711 break; | |
712 } | |
713 } | |
714 return ret; | |
715 } | |
716 | |
717 IndexedDBKeyPath DecodeIDBKeyPath(const char* p, const char* limit) { | |
718 // May be typed, or may be a raw string. An invalid leading | |
719 // byte sequence is used to identify typed coding. New records are | |
720 // always written as typed. | |
721 if (p == limit || | |
722 (limit - p >= 2 && (*p != kIndexedDBKeyPathTypeCodedByte1 || | |
723 *(p + 1) != kIndexedDBKeyPathTypeCodedByte2))) | |
724 return IndexedDBKeyPath(DecodeString(p, limit)); | |
725 p += 2; | |
726 | |
727 DCHECK_NE(p, limit); | |
728 WebIDBKeyPath::Type type = static_cast<WebIDBKeyPath::Type>(*p++); | |
729 switch (type) { | |
730 case WebIDBKeyPath::NullType: | |
731 DCHECK_EQ(p, limit); | |
732 return IndexedDBKeyPath(); | |
733 case WebIDBKeyPath::StringType: { | |
734 string16 string; | |
735 p = DecodeStringWithLength(p, limit, string); | |
736 DCHECK_EQ(p, limit); | |
737 return IndexedDBKeyPath(string); | |
738 } | |
739 case WebIDBKeyPath::ArrayType: { | |
740 std::vector<string16> array; | |
741 int64 count; | |
742 p = DecodeVarInt(p, limit, count); | |
743 DCHECK(p); | |
744 DCHECK_GE(count, 0); | |
745 while (count--) { | |
746 string16 string; | |
747 p = DecodeStringWithLength(p, limit, string); | |
748 DCHECK(p); | |
749 array.push_back(string); | |
750 } | |
751 DCHECK_EQ(p, limit); | |
752 return IndexedDBKeyPath(array); | |
753 } | |
754 } | |
755 NOTREACHED(); | |
756 return IndexedDBKeyPath(); | |
757 } | |
758 | |
759 namespace { | |
760 | |
761 template <typename KeyType> | |
762 int Compare(const LevelDBSlice& a, const LevelDBSlice& b, bool, bool& ok) { | |
763 KeyType key_a; | |
764 KeyType key_b; | |
765 | |
766 const char* ptr_a = KeyType::Decode(a.begin(), a.end(), &key_a); | |
767 DCHECK(ptr_a); | |
768 if (!ptr_a) { | |
769 ok = false; | |
770 return 0; | |
771 } | |
772 const char* ptr_b = KeyType::Decode(b.begin(), b.end(), &key_b); | |
773 DCHECK(ptr_b); | |
774 if (!ptr_b) { | |
775 ok = false; | |
776 return 0; | |
777 } | |
778 | |
779 ok = true; | |
780 return key_a.Compare(key_b); | |
781 } | |
782 | |
783 template <> | |
784 int Compare<ExistsEntryKey>(const LevelDBSlice& a, | |
785 const LevelDBSlice& b, | |
786 bool, | |
787 bool& ok) { | |
788 KeyPrefix prefix_a; | |
789 KeyPrefix prefix_b; | |
790 const char* ptr_a = KeyPrefix::Decode(a.begin(), a.end(), &prefix_a); | |
791 const char* ptr_b = KeyPrefix::Decode(b.begin(), b.end(), &prefix_b); | |
792 DCHECK(ptr_a); | |
793 DCHECK(ptr_b); | |
794 DCHECK(prefix_a.database_id_); | |
795 DCHECK(prefix_a.object_store_id_); | |
796 DCHECK_EQ(prefix_a.index_id_, ExistsEntryKey::kSpecialIndexNumber); | |
797 DCHECK(prefix_b.database_id_); | |
798 DCHECK(prefix_b.object_store_id_); | |
799 DCHECK_EQ(prefix_b.index_id_, ExistsEntryKey::kSpecialIndexNumber); | |
800 DCHECK_NE(ptr_a, a.end()); | |
801 DCHECK_NE(ptr_b, b.end()); | |
802 // Prefixes are not compared - it is assumed this was already done. | |
803 DCHECK(!prefix_a.Compare(prefix_b)); | |
804 | |
805 return CompareEncodedIDBKeys(ptr_a, a.end(), ptr_b, b.end(), ok); | |
806 } | |
807 | |
808 template <> | |
809 int Compare<ObjectStoreDataKey>(const LevelDBSlice& a, | |
810 const LevelDBSlice& b, | |
811 bool, | |
812 bool& ok) { | |
813 KeyPrefix prefix_a; | |
814 KeyPrefix prefix_b; | |
815 const char* ptr_a = KeyPrefix::Decode(a.begin(), a.end(), &prefix_a); | |
816 const char* ptr_b = KeyPrefix::Decode(b.begin(), b.end(), &prefix_b); | |
817 DCHECK(ptr_a); | |
818 DCHECK(ptr_b); | |
819 DCHECK(prefix_a.database_id_); | |
820 DCHECK(prefix_a.object_store_id_); | |
821 DCHECK_EQ(prefix_a.index_id_, ObjectStoreDataKey::kSpecialIndexNumber); | |
822 DCHECK(prefix_b.database_id_); | |
823 DCHECK(prefix_b.object_store_id_); | |
824 DCHECK_EQ(prefix_b.index_id_, ObjectStoreDataKey::kSpecialIndexNumber); | |
825 DCHECK_NE(ptr_a, a.end()); | |
826 DCHECK_NE(ptr_b, b.end()); | |
827 // Prefixes are not compared - it is assumed this was already done. | |
828 DCHECK(!prefix_a.Compare(prefix_b)); | |
829 | |
830 return CompareEncodedIDBKeys(ptr_a, a.end(), ptr_b, b.end(), ok); | |
831 } | |
832 | |
833 template <> | |
834 int Compare<IndexDataKey>(const LevelDBSlice& a, | |
835 const LevelDBSlice& b, | |
836 bool ignore_duplicates, | |
837 bool& ok) { | |
838 KeyPrefix prefix_a; | |
839 KeyPrefix prefix_b; | |
840 const char* ptr_a = KeyPrefix::Decode(a.begin(), a.end(), &prefix_a); | |
841 const char* ptr_b = KeyPrefix::Decode(b.begin(), b.end(), &prefix_b); | |
842 DCHECK(ptr_a); | |
843 DCHECK(ptr_b); | |
844 DCHECK(prefix_a.database_id_); | |
845 DCHECK(prefix_a.object_store_id_); | |
846 DCHECK_GE(prefix_a.index_id_, kMinimumIndexId); | |
847 DCHECK(prefix_b.database_id_); | |
848 DCHECK(prefix_b.object_store_id_); | |
849 DCHECK_GE(prefix_b.index_id_, kMinimumIndexId); | |
850 DCHECK_NE(ptr_a, a.end()); | |
851 DCHECK_NE(ptr_b, b.end()); | |
852 // Prefixes are not compared - it is assumed this was already done. | |
853 DCHECK(!prefix_a.Compare(prefix_b)); | |
854 | |
855 // index key | |
856 int result = CompareEncodedIDBKeys(ptr_a, a.end(), ptr_b, b.end(), ok); | |
857 if (!ok || result) | |
858 return result; | |
859 if (ignore_duplicates) | |
860 return 0; | |
861 | |
862 // sequence number [optional] | |
863 int64 sequence_number_a = -1; | |
864 int64 sequence_number_b = -1; | |
865 if (ptr_a != a.end()) | |
866 ptr_a = DecodeVarInt(ptr_a, a.end(), sequence_number_a); | |
867 if (ptr_b != b.end()) | |
868 ptr_b = DecodeVarInt(ptr_b, b.end(), sequence_number_b); | |
869 | |
870 // primary key [optional] | |
871 if (!ptr_a || !ptr_b) | |
872 return 0; | |
873 if (ptr_a == a.end() && ptr_b == b.end()) | |
874 return 0; | |
875 if (ptr_a == a.end()) | |
876 return -1; | |
877 if (ptr_b == b.end()) | |
878 return 1; | |
879 | |
880 result = CompareEncodedIDBKeys(ptr_a, a.end(), ptr_b, b.end(), ok); | |
881 if (!ok || result) | |
882 return result; | |
883 | |
884 return CompareInts(sequence_number_a, sequence_number_b); | |
885 } | |
886 | |
887 int Compare(const LevelDBSlice& a, | |
888 const LevelDBSlice& b, | |
889 bool index_keys, | |
890 bool& ok) { | |
891 const char* ptr_a = a.begin(); | |
892 const char* ptr_b = b.begin(); | |
893 const char* end_a = a.end(); | |
894 const char* end_b = b.end(); | |
895 | |
896 KeyPrefix prefix_a; | |
897 KeyPrefix prefix_b; | |
898 | |
899 ptr_a = KeyPrefix::Decode(ptr_a, end_a, &prefix_a); | |
900 ptr_b = KeyPrefix::Decode(ptr_b, end_b, &prefix_b); | |
901 DCHECK(ptr_a); | |
902 DCHECK(ptr_b); | |
903 if (!ptr_a || !ptr_b) { | |
904 ok = false; | |
905 return 0; | |
906 } | |
907 | |
908 ok = true; | |
909 if (int x = prefix_a.Compare(prefix_b)) | |
910 return x; | |
911 | |
912 if (prefix_a.type() == KeyPrefix::GLOBAL_METADATA) { | |
913 DCHECK_NE(ptr_a, end_a); | |
914 DCHECK_NE(ptr_b, end_b); | |
915 | |
916 unsigned char type_byte_a = *ptr_a++; | |
917 unsigned char type_byte_b = *ptr_b++; | |
918 | |
919 if (int x = type_byte_a - type_byte_b) | |
920 return x; | |
921 if (type_byte_a < kMaxSimpleGlobalMetaDataTypeByte) | |
922 return 0; | |
923 | |
924 const bool ignore_duplicates = false; | |
925 if (type_byte_a == kDatabaseFreeListTypeByte) | |
926 return Compare<DatabaseFreeListKey>(a, b, ignore_duplicates, ok); | |
927 if (type_byte_a == kDatabaseNameTypeByte) | |
928 return Compare<DatabaseNameKey>(a, b, ignore_duplicates, ok); | |
929 } | |
930 | |
931 if (prefix_a.type() == KeyPrefix::DATABASE_METADATA) { | |
932 DCHECK_NE(ptr_a, end_a); | |
933 DCHECK_NE(ptr_b, end_b); | |
934 | |
935 unsigned char type_byte_a = *ptr_a++; | |
936 unsigned char type_byte_b = *ptr_b++; | |
937 | |
938 if (int x = type_byte_a - type_byte_b) | |
939 return x; | |
940 if (type_byte_a < DatabaseMetaDataKey::MAX_SIMPLE_METADATA_TYPE) | |
941 return 0; | |
942 | |
943 const bool ignore_duplicates = false; | |
944 if (type_byte_a == kObjectStoreMetaDataTypeByte) | |
945 return Compare<ObjectStoreMetaDataKey>(a, b, ignore_duplicates, ok); | |
946 if (type_byte_a == kIndexMetaDataTypeByte) | |
947 return Compare<IndexMetaDataKey>(a, b, ignore_duplicates, ok); | |
948 if (type_byte_a == kObjectStoreFreeListTypeByte) | |
949 return Compare<ObjectStoreFreeListKey>(a, b, ignore_duplicates, ok); | |
950 if (type_byte_a == kIndexFreeListTypeByte) | |
951 return Compare<IndexFreeListKey>(a, b, ignore_duplicates, ok); | |
952 if (type_byte_a == kObjectStoreNamesTypeByte) | |
953 return Compare<ObjectStoreNamesKey>(a, b, ignore_duplicates, ok); | |
954 if (type_byte_a == kIndexNamesKeyTypeByte) | |
955 return Compare<IndexNamesKey>(a, b, ignore_duplicates, ok); | |
956 } | |
957 | |
958 if (prefix_a.type() == KeyPrefix::OBJECT_STORE_DATA) { | |
959 if (ptr_a == end_a && ptr_b == end_b) | |
960 return 0; | |
961 if (ptr_a == end_a) | |
962 return -1; | |
963 if (ptr_b == end_b) | |
964 return 1; // TODO(jsbell): This case of non-existing user keys should not | |
965 // have to be handled this way. | |
966 | |
967 const bool ignore_duplicates = false; | |
968 return Compare<ObjectStoreDataKey>(a, b, ignore_duplicates, ok); | |
969 } | |
970 if (prefix_a.type() == KeyPrefix::EXISTS_ENTRY) { | |
971 if (ptr_a == end_a && ptr_b == end_b) | |
972 return 0; | |
973 if (ptr_a == end_a) | |
974 return -1; | |
975 if (ptr_b == end_b) | |
976 return 1; // TODO(jsbell): This case of non-existing user keys should not | |
977 // have to be handled this way. | |
978 | |
979 const bool ignore_duplicates = false; | |
980 return Compare<ExistsEntryKey>(a, b, ignore_duplicates, ok); | |
981 } | |
982 if (prefix_a.type() == KeyPrefix::INDEX_DATA) { | |
983 if (ptr_a == end_a && ptr_b == end_b) | |
984 return 0; | |
985 if (ptr_a == end_a) | |
986 return -1; | |
987 if (ptr_b == end_b) | |
988 return 1; // TODO(jsbell): This case of non-existing user keys should not | |
989 // have to be handled this way. | |
990 | |
991 bool ignore_duplicates = index_keys; | |
992 return Compare<IndexDataKey>(a, b, ignore_duplicates, ok); | |
993 } | |
994 | |
995 NOTREACHED(); | |
996 ok = false; | |
997 return 0; | |
998 } | |
999 | |
1000 } // namespace | |
1001 | |
1002 int Compare(const LevelDBSlice& a, const LevelDBSlice& b, bool index_keys) { | |
1003 bool ok; | |
1004 int result = Compare(a, b, index_keys, ok); | |
1005 DCHECK(ok); | |
1006 if (!ok) | |
1007 return 0; | |
1008 return result; | |
1009 } | |
1010 | |
1011 KeyPrefix::KeyPrefix() | |
1012 : database_id_(INVALID_TYPE), | |
1013 object_store_id_(INVALID_TYPE), | |
1014 index_id_(INVALID_TYPE) {} | |
1015 | |
1016 KeyPrefix::KeyPrefix(int64 database_id) | |
1017 : database_id_(database_id), object_store_id_(0), index_id_(0) { | |
1018 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); | |
1019 } | |
1020 | |
1021 KeyPrefix::KeyPrefix(int64 database_id, int64 object_store_id) | |
1022 : database_id_(database_id), | |
1023 object_store_id_(object_store_id), | |
1024 index_id_(0) { | |
1025 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); | |
1026 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id)); | |
1027 } | |
1028 | |
1029 KeyPrefix::KeyPrefix(int64 database_id, int64 object_store_id, int64 index_id) | |
1030 : database_id_(database_id), | |
1031 object_store_id_(object_store_id), | |
1032 index_id_(index_id) { | |
1033 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); | |
1034 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id)); | |
1035 DCHECK(KeyPrefix::IsValidIndexId(index_id)); | |
1036 } | |
1037 | |
1038 KeyPrefix::KeyPrefix(enum Type type, | |
1039 int64 database_id, | |
1040 int64 object_store_id, | |
1041 int64 index_id) | |
1042 : database_id_(database_id), | |
1043 object_store_id_(object_store_id), | |
1044 index_id_(index_id) { | |
1045 DCHECK_EQ(type, INVALID_TYPE); | |
1046 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); | |
1047 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id)); | |
1048 } | |
1049 | |
1050 KeyPrefix KeyPrefix::CreateWithSpecialIndex(int64 database_id, | |
1051 int64 object_store_id, | |
1052 int64 index_id) { | |
1053 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); | |
1054 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id)); | |
1055 DCHECK(index_id); | |
1056 return KeyPrefix(INVALID_TYPE, database_id, object_store_id, index_id); | |
1057 } | |
1058 | |
1059 bool KeyPrefix::IsValidDatabaseId(int64 database_id) { | |
1060 return (database_id > 0) && (database_id < KeyPrefix::kMaxDatabaseId); | |
1061 } | |
1062 | |
1063 bool KeyPrefix::IsValidObjectStoreId(int64 object_store_id) { | |
1064 return (object_store_id > 0) && | |
1065 (object_store_id < KeyPrefix::kMaxObjectStoreId); | |
1066 } | |
1067 | |
1068 bool KeyPrefix::IsValidIndexId(int64 index_id) { | |
1069 return (index_id >= kMinimumIndexId) && (index_id < KeyPrefix::kMaxIndexId); | |
1070 } | |
1071 | |
1072 const char* KeyPrefix::Decode(const char* start, | |
1073 const char* limit, | |
1074 KeyPrefix* result) { | |
1075 if (start == limit) | |
1076 return 0; | |
1077 | |
1078 unsigned char first_byte = *start++; | |
1079 | |
1080 int database_id_bytes = ((first_byte >> 5) & 0x7) + 1; | |
1081 int object_store_id_bytes = ((first_byte >> 2) & 0x7) + 1; | |
1082 int index_id_bytes = (first_byte & 0x3) + 1; | |
1083 | |
1084 if (start + database_id_bytes + object_store_id_bytes + index_id_bytes > | |
1085 limit) | |
1086 return 0; | |
1087 | |
1088 result->database_id_ = DecodeInt(start, start + database_id_bytes); | |
1089 start += database_id_bytes; | |
1090 result->object_store_id_ = DecodeInt(start, start + object_store_id_bytes); | |
1091 start += object_store_id_bytes; | |
1092 result->index_id_ = DecodeInt(start, start + index_id_bytes); | |
1093 start += index_id_bytes; | |
1094 | |
1095 return start; | |
1096 } | |
1097 | |
1098 std::vector<char> KeyPrefix::EncodeEmpty() { | |
1099 const std::vector<char> result(4, 0); | |
1100 DCHECK(EncodeInternal(0, 0, 0) == std::vector<char>(4, 0)); | |
1101 return result; | |
1102 } | |
1103 | |
1104 std::vector<char> KeyPrefix::Encode() const { | |
1105 DCHECK(database_id_ != kInvalidId); | |
1106 DCHECK(object_store_id_ != kInvalidId); | |
1107 DCHECK(index_id_ != kInvalidId); | |
1108 return EncodeInternal(database_id_, object_store_id_, index_id_); | |
1109 } | |
1110 | |
1111 std::vector<char> KeyPrefix::EncodeInternal(int64 database_id, | |
1112 int64 object_store_id, | |
1113 int64 index_id) { | |
1114 std::vector<char> database_id_string = | |
1115 EncodeIntSafely(database_id, kMaxDatabaseId); | |
1116 std::vector<char> object_store_id_string = | |
1117 EncodeIntSafely(object_store_id, kMaxObjectStoreId); | |
1118 std::vector<char> index_id_string = EncodeIntSafely(index_id, kMaxIndexId); | |
1119 | |
1120 DCHECK(database_id_string.size() <= kMaxDatabaseIdSizeBytes); | |
1121 DCHECK(object_store_id_string.size() <= kMaxObjectStoreIdSizeBytes); | |
1122 DCHECK(index_id_string.size() <= kMaxIndexIdSizeBytes); | |
1123 | |
1124 unsigned char first_byte = | |
1125 (database_id_string.size() - 1) | |
1126 << (kMaxObjectStoreIdSizeBits + kMaxIndexIdSizeBits) | | |
1127 (object_store_id_string.size() - 1) << kMaxIndexIdSizeBits | | |
1128 (index_id_string.size() - 1); | |
1129 COMPILE_ASSERT(kMaxDatabaseIdSizeBits + kMaxObjectStoreIdSizeBits + | |
1130 kMaxIndexIdSizeBits == | |
1131 sizeof(first_byte) * 8, | |
1132 CANT_ENCODE_IDS); | |
1133 std::vector<char> ret; | |
1134 ret.reserve(kDefaultInlineBufferSize); | |
1135 ret.push_back(first_byte); | |
1136 ret.insert(ret.end(), database_id_string.begin(), database_id_string.end()); | |
1137 ret.insert( | |
1138 ret.end(), object_store_id_string.begin(), object_store_id_string.end()); | |
1139 ret.insert(ret.end(), index_id_string.begin(), index_id_string.end()); | |
1140 | |
1141 DCHECK_LE(ret.size(), kDefaultInlineBufferSize); | |
1142 return ret; | |
1143 } | |
1144 | |
1145 int KeyPrefix::Compare(const KeyPrefix& other) const { | |
1146 DCHECK(database_id_ != kInvalidId); | |
1147 DCHECK(object_store_id_ != kInvalidId); | |
1148 DCHECK(index_id_ != kInvalidId); | |
1149 | |
1150 if (database_id_ != other.database_id_) | |
1151 return CompareInts(database_id_, other.database_id_); | |
1152 if (object_store_id_ != other.object_store_id_) | |
1153 return CompareInts(object_store_id_, other.object_store_id_); | |
1154 if (index_id_ != other.index_id_) | |
1155 return CompareInts(index_id_, other.index_id_); | |
1156 return 0; | |
1157 } | |
1158 | |
1159 KeyPrefix::Type KeyPrefix::type() const { | |
1160 DCHECK(database_id_ != kInvalidId); | |
1161 DCHECK(object_store_id_ != kInvalidId); | |
1162 DCHECK(index_id_ != kInvalidId); | |
1163 | |
1164 if (!database_id_) | |
1165 return GLOBAL_METADATA; | |
1166 if (!object_store_id_) | |
1167 return DATABASE_METADATA; | |
1168 if (index_id_ == kObjectStoreDataIndexId) | |
1169 return OBJECT_STORE_DATA; | |
1170 if (index_id_ == kExistsEntryIndexId) | |
1171 return EXISTS_ENTRY; | |
1172 if (index_id_ >= kMinimumIndexId) | |
1173 return INDEX_DATA; | |
1174 | |
1175 NOTREACHED(); | |
1176 return INVALID_TYPE; | |
1177 } | |
1178 | |
1179 std::vector<char> SchemaVersionKey::Encode() { | |
1180 std::vector<char> ret = KeyPrefix::EncodeEmpty(); | |
1181 ret.push_back(kSchemaVersionTypeByte); | |
1182 return ret; | |
1183 } | |
1184 | |
1185 std::vector<char> MaxDatabaseIdKey::Encode() { | |
1186 std::vector<char> ret = KeyPrefix::EncodeEmpty(); | |
1187 ret.push_back(kMaxDatabaseIdTypeByte); | |
1188 return ret; | |
1189 } | |
1190 | |
1191 std::vector<char> DataVersionKey::Encode() { | |
1192 std::vector<char> ret = KeyPrefix::EncodeEmpty(); | |
1193 ret.push_back(kDataVersionTypeByte); | |
1194 return ret; | |
1195 } | |
1196 | |
1197 DatabaseFreeListKey::DatabaseFreeListKey() : database_id_(-1) {} | |
1198 | |
1199 const char* DatabaseFreeListKey::Decode(const char* start, | |
1200 const char* limit, | |
1201 DatabaseFreeListKey* result) { | |
1202 KeyPrefix prefix; | |
1203 const char* p = KeyPrefix::Decode(start, limit, &prefix); | |
1204 if (!p) | |
1205 return 0; | |
1206 DCHECK(!prefix.database_id_); | |
1207 DCHECK(!prefix.object_store_id_); | |
1208 DCHECK(!prefix.index_id_); | |
1209 if (p == limit) | |
1210 return 0; | |
1211 unsigned char type_byte = 0; | |
1212 p = DecodeByte(p, limit, type_byte); | |
1213 DCHECK_EQ(type_byte, kDatabaseFreeListTypeByte); | |
1214 if (p == limit) | |
1215 return 0; | |
1216 return DecodeVarInt(p, limit, result->database_id_); | |
1217 } | |
1218 | |
1219 std::vector<char> DatabaseFreeListKey::Encode(int64 database_id) { | |
1220 std::vector<char> ret = KeyPrefix::EncodeEmpty(); | |
1221 ret.push_back(kDatabaseFreeListTypeByte); | |
1222 std::vector<char> tmp = EncodeVarInt(database_id); | |
1223 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1224 return ret; | |
1225 } | |
1226 | |
1227 std::vector<char> DatabaseFreeListKey::EncodeMaxKey() { | |
1228 return Encode(std::numeric_limits<int64>::max()); | |
1229 } | |
1230 | |
1231 int64 DatabaseFreeListKey::DatabaseId() const { | |
1232 DCHECK_GE(database_id_, 0); | |
1233 return database_id_; | |
1234 } | |
1235 | |
1236 int DatabaseFreeListKey::Compare(const DatabaseFreeListKey& other) const { | |
1237 DCHECK_GE(database_id_, 0); | |
1238 return CompareInts(database_id_, other.database_id_); | |
1239 } | |
1240 | |
1241 const char* DatabaseNameKey::Decode(const char* start, | |
1242 const char* limit, | |
1243 DatabaseNameKey* result) { | |
1244 KeyPrefix prefix; | |
1245 const char* p = KeyPrefix::Decode(start, limit, &prefix); | |
1246 if (!p) | |
1247 return p; | |
1248 DCHECK(!prefix.database_id_); | |
1249 DCHECK(!prefix.object_store_id_); | |
1250 DCHECK(!prefix.index_id_); | |
1251 if (p == limit) | |
1252 return 0; | |
1253 unsigned char type_byte = 0; | |
1254 p = DecodeByte(p, limit, type_byte); | |
1255 DCHECK_EQ(type_byte, kDatabaseNameTypeByte); | |
1256 if (p == limit) | |
1257 return 0; | |
1258 p = DecodeStringWithLength(p, limit, result->origin_); | |
1259 if (!p) | |
1260 return 0; | |
1261 return DecodeStringWithLength(p, limit, result->database_name_); | |
1262 } | |
1263 | |
1264 std::vector<char> DatabaseNameKey::Encode(const string16& origin, | |
1265 const string16& database_name) { | |
1266 std::vector<char> ret = KeyPrefix::EncodeEmpty(); | |
1267 ret.push_back(kDatabaseNameTypeByte); | |
1268 std::vector<char> tmp = EncodeStringWithLength(origin); | |
1269 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1270 tmp = EncodeStringWithLength(database_name); | |
1271 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1272 return ret; | |
1273 } | |
1274 | |
1275 std::vector<char> DatabaseNameKey::EncodeMinKeyForOrigin( | |
1276 const string16& origin) { | |
1277 return Encode(origin, string16()); | |
1278 } | |
1279 | |
1280 std::vector<char> DatabaseNameKey::EncodeStopKeyForOrigin( | |
1281 const string16& origin) { | |
1282 // just after origin in collation order | |
1283 return EncodeMinKeyForOrigin(origin + base::char16('\x01')); | |
1284 } | |
1285 | |
1286 int DatabaseNameKey::Compare(const DatabaseNameKey& other) { | |
1287 if (int x = origin_.compare(other.origin_)) | |
1288 return x; | |
1289 return database_name_.compare(other.database_name_); | |
1290 } | |
1291 | |
1292 std::vector<char> DatabaseMetaDataKey::Encode(int64 database_id, | |
1293 MetaDataType meta_data_type) { | |
1294 KeyPrefix prefix(database_id); | |
1295 std::vector<char> ret = prefix.Encode(); | |
1296 ret.push_back(meta_data_type); | |
1297 return ret; | |
1298 } | |
1299 | |
1300 ObjectStoreMetaDataKey::ObjectStoreMetaDataKey() | |
1301 : object_store_id_(-1), meta_data_type_(-1) {} | |
1302 | |
1303 const char* ObjectStoreMetaDataKey::Decode(const char* start, | |
1304 const char* limit, | |
1305 ObjectStoreMetaDataKey* result) { | |
1306 KeyPrefix prefix; | |
1307 const char* p = KeyPrefix::Decode(start, limit, &prefix); | |
1308 if (!p) | |
1309 return 0; | |
1310 DCHECK(prefix.database_id_); | |
1311 DCHECK(!prefix.object_store_id_); | |
1312 DCHECK(!prefix.index_id_); | |
1313 if (p == limit) | |
1314 return 0; | |
1315 unsigned char type_byte = 0; | |
1316 p = DecodeByte(p, limit, type_byte); | |
1317 DCHECK_EQ(type_byte, kObjectStoreMetaDataTypeByte); | |
1318 if (p == limit) | |
1319 return 0; | |
1320 p = DecodeVarInt(p, limit, result->object_store_id_); | |
1321 if (!p) | |
1322 return 0; | |
1323 DCHECK(result->object_store_id_); | |
1324 if (p == limit) | |
1325 return 0; | |
1326 return DecodeByte(p, limit, result->meta_data_type_); | |
1327 } | |
1328 | |
1329 std::vector<char> ObjectStoreMetaDataKey::Encode(int64 database_id, | |
1330 int64 object_store_id, | |
1331 unsigned char meta_data_type) { | |
1332 KeyPrefix prefix(database_id); | |
1333 std::vector<char> ret = prefix.Encode(); | |
1334 ret.push_back(kObjectStoreMetaDataTypeByte); | |
1335 std::vector<char> tmp = EncodeVarInt(object_store_id); | |
1336 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1337 ret.push_back(meta_data_type); | |
1338 return ret; | |
1339 } | |
1340 | |
1341 std::vector<char> ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id) { | |
1342 return Encode(database_id, | |
1343 std::numeric_limits<int64>::max(), | |
1344 kObjectMetaDataTypeMaximum); | |
1345 } | |
1346 | |
1347 std::vector<char> ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id, | |
1348 int64 object_store_id) { | |
1349 return Encode(database_id, object_store_id, kObjectMetaDataTypeMaximum); | |
1350 } | |
1351 | |
1352 int64 ObjectStoreMetaDataKey::ObjectStoreId() const { | |
1353 DCHECK_GE(object_store_id_, 0); | |
1354 return object_store_id_; | |
1355 } | |
1356 unsigned char ObjectStoreMetaDataKey::MetaDataType() const { | |
1357 return meta_data_type_; | |
1358 } | |
1359 | |
1360 int ObjectStoreMetaDataKey::Compare(const ObjectStoreMetaDataKey& other) { | |
1361 DCHECK_GE(object_store_id_, 0); | |
1362 if (int x = CompareInts(object_store_id_, other.object_store_id_)) | |
1363 return x; | |
1364 int64 result = meta_data_type_ - other.meta_data_type_; | |
1365 if (result < 0) | |
1366 return -1; | |
1367 return (result > 0) ? 1 : result; | |
1368 } | |
1369 | |
1370 IndexMetaDataKey::IndexMetaDataKey() | |
1371 : object_store_id_(-1), index_id_(-1), meta_data_type_(0) {} | |
1372 | |
1373 const char* IndexMetaDataKey::Decode(const char* start, | |
1374 const char* limit, | |
1375 IndexMetaDataKey* result) { | |
1376 KeyPrefix prefix; | |
1377 const char* p = KeyPrefix::Decode(start, limit, &prefix); | |
1378 if (!p) | |
1379 return 0; | |
1380 DCHECK(prefix.database_id_); | |
1381 DCHECK(!prefix.object_store_id_); | |
1382 DCHECK(!prefix.index_id_); | |
1383 if (p == limit) | |
1384 return 0; | |
1385 unsigned char type_byte = 0; | |
1386 p = DecodeByte(p, limit, type_byte); | |
1387 DCHECK_EQ(type_byte, kIndexMetaDataTypeByte); | |
1388 if (p == limit) | |
1389 return 0; | |
1390 p = DecodeVarInt(p, limit, result->object_store_id_); | |
1391 if (!p) | |
1392 return 0; | |
1393 p = DecodeVarInt(p, limit, result->index_id_); | |
1394 if (!p) | |
1395 return 0; | |
1396 if (p == limit) | |
1397 return 0; | |
1398 return DecodeByte(p, limit, result->meta_data_type_); | |
1399 } | |
1400 | |
1401 std::vector<char> IndexMetaDataKey::Encode(int64 database_id, | |
1402 int64 object_store_id, | |
1403 int64 index_id, | |
1404 unsigned char meta_data_type) { | |
1405 KeyPrefix prefix(database_id); | |
1406 std::vector<char> ret = prefix.Encode(); | |
1407 ret.push_back(kIndexMetaDataTypeByte); | |
1408 std::vector<char> tmp = EncodeVarInt(object_store_id); | |
1409 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1410 tmp = EncodeVarInt(index_id); | |
1411 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1412 tmp = EncodeByte(meta_data_type); | |
1413 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1414 return ret; | |
1415 } | |
1416 | |
1417 std::vector<char> IndexMetaDataKey::EncodeMaxKey(int64 database_id, | |
1418 int64 object_store_id) { | |
1419 return Encode(database_id, | |
1420 object_store_id, | |
1421 std::numeric_limits<int64>::max(), | |
1422 kIndexMetaDataTypeMaximum); | |
1423 } | |
1424 | |
1425 std::vector<char> IndexMetaDataKey::EncodeMaxKey(int64 database_id, | |
1426 int64 object_store_id, | |
1427 int64 index_id) { | |
1428 return Encode( | |
1429 database_id, object_store_id, index_id, kIndexMetaDataTypeMaximum); | |
1430 } | |
1431 | |
1432 int IndexMetaDataKey::Compare(const IndexMetaDataKey& other) { | |
1433 DCHECK_GE(object_store_id_, 0); | |
1434 DCHECK_GE(index_id_, 0); | |
1435 | |
1436 if (int x = CompareInts(object_store_id_, other.object_store_id_)) | |
1437 return x; | |
1438 if (int x = CompareInts(index_id_, other.index_id_)) | |
1439 return x; | |
1440 return meta_data_type_ - other.meta_data_type_; | |
1441 } | |
1442 | |
1443 int64 IndexMetaDataKey::IndexId() const { | |
1444 DCHECK_GE(index_id_, 0); | |
1445 return index_id_; | |
1446 } | |
1447 | |
1448 ObjectStoreFreeListKey::ObjectStoreFreeListKey() : object_store_id_(-1) {} | |
1449 | |
1450 const char* ObjectStoreFreeListKey::Decode(const char* start, | |
1451 const char* limit, | |
1452 ObjectStoreFreeListKey* result) { | |
1453 KeyPrefix prefix; | |
1454 const char* p = KeyPrefix::Decode(start, limit, &prefix); | |
1455 if (!p) | |
1456 return 0; | |
1457 DCHECK(prefix.database_id_); | |
1458 DCHECK(!prefix.object_store_id_); | |
1459 DCHECK(!prefix.index_id_); | |
1460 if (p == limit) | |
1461 return 0; | |
1462 unsigned char type_byte = 0; | |
1463 p = DecodeByte(p, limit, type_byte); | |
1464 DCHECK_EQ(type_byte, kObjectStoreFreeListTypeByte); | |
1465 if (p == limit) | |
1466 return 0; | |
1467 return DecodeVarInt(p, limit, result->object_store_id_); | |
1468 } | |
1469 | |
1470 std::vector<char> ObjectStoreFreeListKey::Encode(int64 database_id, | |
1471 int64 object_store_id) { | |
1472 KeyPrefix prefix(database_id); | |
1473 std::vector<char> ret = prefix.Encode(); | |
1474 ret.push_back(kObjectStoreFreeListTypeByte); | |
1475 std::vector<char> tmp = EncodeVarInt(object_store_id); | |
1476 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1477 return ret; | |
1478 } | |
1479 | |
1480 std::vector<char> ObjectStoreFreeListKey::EncodeMaxKey(int64 database_id) { | |
1481 return Encode(database_id, std::numeric_limits<int64>::max()); | |
1482 } | |
1483 | |
1484 int64 ObjectStoreFreeListKey::ObjectStoreId() const { | |
1485 DCHECK_GE(object_store_id_, 0); | |
1486 return object_store_id_; | |
1487 } | |
1488 | |
1489 int ObjectStoreFreeListKey::Compare(const ObjectStoreFreeListKey& other) { | |
1490 // TODO(jsbell): It may seem strange that we're not comparing database id's, | |
1491 // but that comparison will have been made earlier. | |
1492 // We should probably make this more clear, though... | |
1493 DCHECK_GE(object_store_id_, 0); | |
1494 return CompareInts(object_store_id_, other.object_store_id_); | |
1495 } | |
1496 | |
1497 IndexFreeListKey::IndexFreeListKey() : object_store_id_(-1), index_id_(-1) {} | |
1498 | |
1499 const char* IndexFreeListKey::Decode(const char* start, | |
1500 const char* limit, | |
1501 IndexFreeListKey* result) { | |
1502 KeyPrefix prefix; | |
1503 const char* p = KeyPrefix::Decode(start, limit, &prefix); | |
1504 if (!p) | |
1505 return 0; | |
1506 DCHECK(prefix.database_id_); | |
1507 DCHECK(!prefix.object_store_id_); | |
1508 DCHECK(!prefix.index_id_); | |
1509 if (p == limit) | |
1510 return 0; | |
1511 unsigned char type_byte = 0; | |
1512 p = DecodeByte(p, limit, type_byte); | |
1513 DCHECK_EQ(type_byte, kIndexFreeListTypeByte); | |
1514 if (p == limit) | |
1515 return 0; | |
1516 p = DecodeVarInt(p, limit, result->object_store_id_); | |
1517 if (!p) | |
1518 return 0; | |
1519 return DecodeVarInt(p, limit, result->index_id_); | |
1520 } | |
1521 | |
1522 std::vector<char> IndexFreeListKey::Encode(int64 database_id, | |
1523 int64 object_store_id, | |
1524 int64 index_id) { | |
1525 KeyPrefix prefix(database_id); | |
1526 std::vector<char> ret = prefix.Encode(); | |
1527 ret.push_back(kIndexFreeListTypeByte); | |
1528 std::vector<char> tmp = EncodeVarInt(object_store_id); | |
1529 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1530 tmp = EncodeVarInt(index_id); | |
1531 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1532 return ret; | |
1533 } | |
1534 | |
1535 std::vector<char> IndexFreeListKey::EncodeMaxKey(int64 database_id, | |
1536 int64 object_store_id) { | |
1537 return Encode( | |
1538 database_id, object_store_id, std::numeric_limits<int64>::max()); | |
1539 } | |
1540 | |
1541 int IndexFreeListKey::Compare(const IndexFreeListKey& other) { | |
1542 DCHECK_GE(object_store_id_, 0); | |
1543 DCHECK_GE(index_id_, 0); | |
1544 if (int x = CompareInts(object_store_id_, other.object_store_id_)) | |
1545 return x; | |
1546 return CompareInts(index_id_, other.index_id_); | |
1547 } | |
1548 | |
1549 int64 IndexFreeListKey::ObjectStoreId() const { | |
1550 DCHECK_GE(object_store_id_, 0); | |
1551 return object_store_id_; | |
1552 } | |
1553 | |
1554 int64 IndexFreeListKey::IndexId() const { | |
1555 DCHECK_GE(index_id_, 0); | |
1556 return index_id_; | |
1557 } | |
1558 | |
1559 // TODO(jsbell): We never use this to look up object store ids, | |
1560 // because a mapping is kept in the IndexedDBDatabaseImpl. Can the | |
1561 // mapping become unreliable? Can we remove this? | |
1562 const char* ObjectStoreNamesKey::Decode(const char* start, | |
1563 const char* limit, | |
1564 ObjectStoreNamesKey* result) { | |
1565 KeyPrefix prefix; | |
1566 const char* p = KeyPrefix::Decode(start, limit, &prefix); | |
1567 if (!p) | |
1568 return 0; | |
1569 DCHECK(prefix.database_id_); | |
1570 DCHECK(!prefix.object_store_id_); | |
1571 DCHECK(!prefix.index_id_); | |
1572 if (p == limit) | |
1573 return 0; | |
1574 unsigned char type_byte = 0; | |
1575 p = DecodeByte(p, limit, type_byte); | |
1576 DCHECK_EQ(type_byte, kObjectStoreNamesTypeByte); | |
1577 return DecodeStringWithLength(p, limit, result->object_store_name_); | |
1578 } | |
1579 | |
1580 std::vector<char> ObjectStoreNamesKey::Encode( | |
1581 int64 database_id, | |
1582 const string16& object_store_name) { | |
1583 KeyPrefix prefix(database_id); | |
1584 std::vector<char> ret = prefix.Encode(); | |
1585 ret.push_back(kObjectStoreNamesTypeByte); | |
1586 std::vector<char> tmp = EncodeStringWithLength(object_store_name); | |
1587 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1588 return ret; | |
1589 } | |
1590 | |
1591 int ObjectStoreNamesKey::Compare(const ObjectStoreNamesKey& other) { | |
1592 return object_store_name_.compare(other.object_store_name_); | |
1593 } | |
1594 | |
1595 IndexNamesKey::IndexNamesKey() : object_store_id_(-1) {} | |
1596 | |
1597 // TODO(jsbell): We never use this to look up index ids, because a mapping | |
1598 // is kept at a higher level. | |
1599 const char* IndexNamesKey::Decode(const char* start, | |
1600 const char* limit, | |
1601 IndexNamesKey* result) { | |
1602 KeyPrefix prefix; | |
1603 const char* p = KeyPrefix::Decode(start, limit, &prefix); | |
1604 if (!p) | |
1605 return 0; | |
1606 DCHECK(prefix.database_id_); | |
1607 DCHECK(!prefix.object_store_id_); | |
1608 DCHECK(!prefix.index_id_); | |
1609 if (p == limit) | |
1610 return 0; | |
1611 unsigned char type_byte = 0; | |
1612 p = DecodeByte(p, limit, type_byte); | |
1613 DCHECK_EQ(type_byte, kIndexNamesKeyTypeByte); | |
1614 if (p == limit) | |
1615 return 0; | |
1616 p = DecodeVarInt(p, limit, result->object_store_id_); | |
1617 if (!p) | |
1618 return 0; | |
1619 return DecodeStringWithLength(p, limit, result->index_name_); | |
1620 } | |
1621 | |
1622 std::vector<char> IndexNamesKey::Encode(int64 database_id, | |
1623 int64 object_store_id, | |
1624 const string16& index_name) { | |
1625 KeyPrefix prefix(database_id); | |
1626 std::vector<char> ret = prefix.Encode(); | |
1627 ret.push_back(kIndexNamesKeyTypeByte); | |
1628 std::vector<char> tmp = EncodeVarInt(object_store_id); | |
1629 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1630 tmp = EncodeStringWithLength(index_name); | |
1631 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1632 return ret; | |
1633 } | |
1634 | |
1635 int IndexNamesKey::Compare(const IndexNamesKey& other) { | |
1636 DCHECK_GE(object_store_id_, 0); | |
1637 if (int x = CompareInts(object_store_id_, other.object_store_id_)) | |
1638 return x; | |
1639 return index_name_.compare(other.index_name_); | |
1640 } | |
1641 | |
1642 ObjectStoreDataKey::ObjectStoreDataKey() {} | |
1643 ObjectStoreDataKey::~ObjectStoreDataKey() {} | |
1644 | |
1645 const char* ObjectStoreDataKey::Decode(const char* start, | |
1646 const char* end, | |
1647 ObjectStoreDataKey* result) { | |
1648 KeyPrefix prefix; | |
1649 const char* p = KeyPrefix::Decode(start, end, &prefix); | |
1650 if (!p) | |
1651 return 0; | |
1652 DCHECK(prefix.database_id_); | |
1653 DCHECK(prefix.object_store_id_); | |
1654 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber); | |
1655 if (p == end) | |
1656 return 0; | |
1657 return ExtractEncodedIDBKey(p, end, &result->encoded_user_key_); | |
1658 } | |
1659 | |
1660 std::vector<char> ObjectStoreDataKey::Encode( | |
1661 int64 database_id, | |
1662 int64 object_store_id, | |
1663 const std::vector<char> encoded_user_key) { | |
1664 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex( | |
1665 database_id, object_store_id, kSpecialIndexNumber)); | |
1666 std::vector<char> ret = prefix.Encode(); | |
1667 ret.insert(ret.end(), encoded_user_key.begin(), encoded_user_key.end()); | |
1668 | |
1669 return ret; | |
1670 } | |
1671 | |
1672 std::vector<char> ObjectStoreDataKey::Encode(int64 database_id, | |
1673 int64 object_store_id, | |
1674 const IndexedDBKey& user_key) { | |
1675 return Encode(database_id, object_store_id, EncodeIDBKey(user_key)); | |
1676 } | |
1677 | |
1678 int ObjectStoreDataKey::Compare(const ObjectStoreDataKey& other, bool& ok) { | |
1679 return CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok); | |
1680 } | |
1681 | |
1682 scoped_ptr<IndexedDBKey> ObjectStoreDataKey::user_key() const { | |
1683 scoped_ptr<IndexedDBKey> key; | |
1684 DecodeIDBKey(&encoded_user_key_[0], | |
1685 &encoded_user_key_[0] + encoded_user_key_.size(), | |
1686 &key); | |
1687 return key.Pass(); | |
1688 } | |
1689 | |
1690 const int64 ObjectStoreDataKey::kSpecialIndexNumber = kObjectStoreDataIndexId; | |
1691 | |
1692 ExistsEntryKey::ExistsEntryKey() {} | |
1693 ExistsEntryKey::~ExistsEntryKey() {} | |
1694 | |
1695 const char* ExistsEntryKey::Decode(const char* start, | |
1696 const char* end, | |
1697 ExistsEntryKey* result) { | |
1698 KeyPrefix prefix; | |
1699 const char* p = KeyPrefix::Decode(start, end, &prefix); | |
1700 if (!p) | |
1701 return 0; | |
1702 DCHECK(prefix.database_id_); | |
1703 DCHECK(prefix.object_store_id_); | |
1704 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber); | |
1705 if (p == end) | |
1706 return 0; | |
1707 return ExtractEncodedIDBKey(p, end, &result->encoded_user_key_); | |
1708 } | |
1709 | |
1710 std::vector<char> ExistsEntryKey::Encode(int64 database_id, | |
1711 int64 object_store_id, | |
1712 const std::vector<char>& encoded_key) { | |
1713 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex( | |
1714 database_id, object_store_id, kSpecialIndexNumber)); | |
1715 std::vector<char> ret = prefix.Encode(); | |
1716 ret.insert(ret.end(), encoded_key.begin(), encoded_key.end()); | |
1717 return ret; | |
1718 } | |
1719 | |
1720 std::vector<char> ExistsEntryKey::Encode(int64 database_id, | |
1721 int64 object_store_id, | |
1722 const IndexedDBKey& user_key) { | |
1723 return Encode(database_id, object_store_id, EncodeIDBKey(user_key)); | |
1724 } | |
1725 | |
1726 int ExistsEntryKey::Compare(const ExistsEntryKey& other, bool& ok) { | |
1727 return CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok); | |
1728 } | |
1729 | |
1730 scoped_ptr<IndexedDBKey> ExistsEntryKey::user_key() const { | |
1731 scoped_ptr<IndexedDBKey> key; | |
1732 DecodeIDBKey(&encoded_user_key_[0], | |
1733 &encoded_user_key_[0] + encoded_user_key_.size(), | |
1734 &key); | |
1735 return key.Pass(); | |
1736 } | |
1737 | |
1738 const int64 ExistsEntryKey::kSpecialIndexNumber = kExistsEntryIndexId; | |
1739 | |
1740 IndexDataKey::IndexDataKey() | |
1741 : database_id_(-1), | |
1742 object_store_id_(-1), | |
1743 index_id_(-1), | |
1744 sequence_number_(-1) {} | |
1745 | |
1746 IndexDataKey::~IndexDataKey() {} | |
1747 | |
1748 const char* IndexDataKey::Decode(const char* start, | |
1749 const char* limit, | |
1750 IndexDataKey* result) { | |
1751 KeyPrefix prefix; | |
1752 const char* p = KeyPrefix::Decode(start, limit, &prefix); | |
1753 if (!p) | |
1754 return 0; | |
1755 DCHECK(prefix.database_id_); | |
1756 DCHECK(prefix.object_store_id_); | |
1757 DCHECK_GE(prefix.index_id_, kMinimumIndexId); | |
1758 result->database_id_ = prefix.database_id_; | |
1759 result->object_store_id_ = prefix.object_store_id_; | |
1760 result->index_id_ = prefix.index_id_; | |
1761 result->sequence_number_ = -1; | |
1762 result->encoded_primary_key_ = MinIDBKey(); | |
1763 | |
1764 p = ExtractEncodedIDBKey(p, limit, &result->encoded_user_key_); | |
1765 if (!p) | |
1766 return 0; | |
1767 | |
1768 // [optional] sequence number | |
1769 if (p == limit) | |
1770 return p; | |
1771 p = DecodeVarInt(p, limit, result->sequence_number_); | |
1772 if (!p) | |
1773 return 0; | |
1774 | |
1775 // [optional] primary key | |
1776 if (p == limit) | |
1777 return p; | |
1778 p = ExtractEncodedIDBKey(p, limit, &result->encoded_primary_key_); | |
1779 if (!p) | |
1780 return 0; | |
1781 | |
1782 return p; | |
1783 } | |
1784 | |
1785 std::vector<char> IndexDataKey::Encode( | |
1786 int64 database_id, | |
1787 int64 object_store_id, | |
1788 int64 index_id, | |
1789 const std::vector<char>& encoded_user_key, | |
1790 const std::vector<char>& encoded_primary_key, | |
1791 int64 sequence_number) { | |
1792 KeyPrefix prefix(database_id, object_store_id, index_id); | |
1793 std::vector<char> ret = prefix.Encode(); | |
1794 ret.insert(ret.end(), encoded_user_key.begin(), encoded_user_key.end()); | |
1795 std::vector<char> tmp = EncodeVarInt(sequence_number); | |
1796 ret.insert(ret.end(), tmp.begin(), tmp.end()); | |
1797 ret.insert(ret.end(), encoded_primary_key.begin(), encoded_primary_key.end()); | |
1798 return ret; | |
1799 } | |
1800 | |
1801 std::vector<char> IndexDataKey::Encode(int64 database_id, | |
1802 int64 object_store_id, | |
1803 int64 index_id, | |
1804 const IndexedDBKey& user_key) { | |
1805 return Encode(database_id, | |
1806 object_store_id, | |
1807 index_id, | |
1808 EncodeIDBKey(user_key), | |
1809 MinIDBKey()); | |
1810 } | |
1811 | |
1812 std::vector<char> IndexDataKey::EncodeMinKey(int64 database_id, | |
1813 int64 object_store_id, | |
1814 int64 index_id) { | |
1815 return Encode( | |
1816 database_id, object_store_id, index_id, MinIDBKey(), MinIDBKey()); | |
1817 } | |
1818 | |
1819 std::vector<char> IndexDataKey::EncodeMaxKey(int64 database_id, | |
1820 int64 object_store_id, | |
1821 int64 index_id) { | |
1822 return Encode(database_id, | |
1823 object_store_id, | |
1824 index_id, | |
1825 MaxIDBKey(), | |
1826 MaxIDBKey(), | |
1827 std::numeric_limits<int64>::max()); | |
1828 } | |
1829 | |
1830 int IndexDataKey::Compare(const IndexDataKey& other, | |
1831 bool ignore_duplicates, | |
1832 bool& ok) { | |
1833 DCHECK_GE(database_id_, 0); | |
1834 DCHECK_GE(object_store_id_, 0); | |
1835 DCHECK_GE(index_id_, 0); | |
1836 int result = | |
1837 CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok); | |
1838 if (!ok || result) | |
1839 return result; | |
1840 if (ignore_duplicates) | |
1841 return 0; | |
1842 result = CompareEncodedIDBKeys( | |
1843 encoded_primary_key_, other.encoded_primary_key_, ok); | |
1844 if (!ok || result) | |
1845 return result; | |
1846 return CompareInts(sequence_number_, other.sequence_number_); | |
1847 } | |
1848 | |
1849 int64 IndexDataKey::DatabaseId() const { | |
1850 DCHECK_GE(database_id_, 0); | |
1851 return database_id_; | |
1852 } | |
1853 | |
1854 int64 IndexDataKey::ObjectStoreId() const { | |
1855 DCHECK_GE(object_store_id_, 0); | |
1856 return object_store_id_; | |
1857 } | |
1858 | |
1859 int64 IndexDataKey::IndexId() const { | |
1860 DCHECK_GE(index_id_, 0); | |
1861 return index_id_; | |
1862 } | |
1863 | |
1864 scoped_ptr<IndexedDBKey> IndexDataKey::user_key() const { | |
1865 scoped_ptr<IndexedDBKey> key; | |
1866 DecodeIDBKey(&encoded_user_key_[0], | |
1867 &encoded_user_key_[0] + encoded_user_key_.size(), | |
1868 &key); | |
1869 return key.Pass(); | |
1870 } | |
1871 | |
1872 scoped_ptr<IndexedDBKey> IndexDataKey::primary_key() const { | |
1873 scoped_ptr<IndexedDBKey> key; | |
1874 DecodeIDBKey(&encoded_primary_key_[0], | |
1875 &encoded_primary_key_[0] + encoded_primary_key_.size(), | |
1876 &key); | |
1877 return key.Pass(); | |
1878 } | |
1879 | |
1880 } // namespace content | |
OLD | NEW |