Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: content/browser/indexed_db/indexed_db_leveldb_coding.cc

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

Powered by Google App Engine
This is Rietveld 408576698