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