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

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: Accessor naming, use LevelDBSlice ctor explicitly 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 "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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698