Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_leveldb_coding.cc
blob2de9b6d585db798e7ecc3fee710bae07de6e5bc0
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.
5 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
7 #include <iterator>
8 #include <limits>
10 #include "base/logging.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/sys_byteorder.h"
14 #include "content/common/indexed_db/indexed_db_key.h"
15 #include "content/common/indexed_db/indexed_db_key_path.h"
17 // LevelDB Coding Scheme
18 // =====================
20 // LevelDB stores key/value pairs. Keys and values are strings of bytes,
21 // normally of type std::string.
23 // The keys in the backing store are variable-length tuples with different
24 // types of fields. Each key in the backing store starts with a ternary
25 // prefix: (database id, object store id, index id). For each, 0 is reserved
26 // for metadata. See KeyPrefix::Decode() for details of the prefix coding.
28 // The prefix makes sure that data for a specific database, object store, and
29 // index are grouped together. The locality is important for performance:
30 // common operations should only need a minimal number of seek operations. For
31 // example, all the metadata for a database is grouped together so that
32 // reading that metadata only requires one seek.
34 // Each key type has a class (in square brackets below) which knows how to
35 // encode, decode, and compare that key type.
37 // Strings (origins, names, etc) are encoded as UTF-16BE.
40 // Global metadata
41 // ---------------
42 // The prefix is <0, 0, 0>, followed by a metadata type byte:
44 // <0, 0, 0, 0> => backing store schema version [SchemaVersionKey]
45 // <0, 0, 0, 1> => maximum allocated database [MaxDatabaseIdKey]
46 // <0, 0, 0, 2> => SerializedScriptValue version [DataVersionKey]
47 // <0, 0, 0, 3>
48 // => Blob journal
49 // The format of the journal is: {database_id, blobKey}*.
50 // If the blobKey is kAllBlobsKey, the whole database should be deleted.
51 // [BlobJournalKey]
52 // <0, 0, 0, 4> => Live blob journal; same format. [LiveBlobJournalKey]
53 // <0, 0, 0, 100, database id>
54 // => Existence implies the database id is in the free list
55 // [DatabaseFreeListKey]
56 // <0, 0, 0, 201, origin, database name> => Database id [DatabaseNameKey]
59 // Database metadata: [DatabaseMetaDataKey]
60 // ----------------------------------------
61 // The prefix is <database id, 0, 0> followed by a metadata type byte:
63 // <database id, 0, 0, 0> => origin name
64 // <database id, 0, 0, 1> => database name
65 // <database id, 0, 0, 2> => IDB string version data (obsolete)
66 // <database id, 0, 0, 3> => maximum allocated object store id
67 // <database id, 0, 0, 4> => IDB integer version (var int)
68 // <database id, 0, 0, 5> => blob key generator current number
71 // Object store metadata: [ObjectStoreMetaDataKey]
72 // -----------------------------------------------
73 // The prefix is <database id, 0, 0>, followed by a type byte (50), then the
74 // object store id (var int), then a metadata type byte.
76 // <database id, 0, 0, 50, object store id, 0> => object store name
77 // <database id, 0, 0, 50, object store id, 1> => key path
78 // <database id, 0, 0, 50, object store id, 2> => auto increment flag
79 // <database id, 0, 0, 50, object store id, 3> => is evictable
80 // <database id, 0, 0, 50, object store id, 4> => last "version" number
81 // <database id, 0, 0, 50, object store id, 5> => maximum allocated index id
82 // <database id, 0, 0, 50, object store id, 6> => has key path flag (obsolete)
83 // <database id, 0, 0, 50, object store id, 7> => key generator current number
85 // The key path was originally just a string (#1) or null (identified by flag,
86 // #6). To support null, string, or array the coding is now identified by the
87 // leading bytes in #1 - see EncodeIDBKeyPath.
89 // The "version" field is used to weed out stale index data. Whenever new
90 // object store data is inserted, it gets a new "version" number, and new
91 // index data is written with this number. When the index is used for
92 // look-ups, entries are validated against the "exists" entries, and records
93 // with old "version" numbers are deleted when they are encountered in
94 // GetPrimaryKeyViaIndex, IndexCursorImpl::LoadCurrentRow and
95 // IndexKeyCursorImpl::LoadCurrentRow.
98 // Index metadata: [IndexMetaDataKey]
99 // ----------------------------------
100 // The prefix is <database id, 0, 0>, followed by a type byte (100), then the
101 // object store id (var int), then the index id (var int), then a metadata
102 // type byte.
104 // <database id, 0, 0, 100, object store id, index id, 0> => index name
105 // <database id, 0, 0, 100, object store id, index id, 1> => unique flag
106 // <database id, 0, 0, 100, object store id, index id, 2> => key path
107 // <database id, 0, 0, 100, object store id, index id, 3> => multi-entry flag
110 // Other object store and index metadata
111 // -------------------------------------
112 // The prefix is <database id, 0, 0> followed by a type byte. The object
113 // store and index id are variable length integers, the names are variable
114 // length strings.
116 // <database id, 0, 0, 150, object store id>
117 // => existence implies the object store id is in the free list
118 // [ObjectStoreFreeListKey]
119 // <database id, 0, 0, 151, object store id, index id>
120 // => existence implies the index id is in the free list [IndexFreeListKey]
121 // <database id, 0, 0, 200, object store name>
122 // => object store id [ObjectStoreNamesKey]
123 // <database id, 0, 0, 201, object store id, index name>
124 // => index id [IndexNamesKey]
127 // Object store data: [ObjectStoreDataKey]
128 // ---------------------------------------
129 // The prefix is followed by a type byte and the encoded IDB primary key. The
130 // data has a "version" prefix followed by the serialized script value.
132 // <database id, object store id, 1, user key>
133 // => "version", serialized script value
136 // "Exists" entry: [ExistsEntryKey]
137 // --------------------------------
138 // The prefix is followed by a type byte and the encoded IDB primary key.
140 // <database id, object store id, 2, user key> => "version"
143 // Blob entry table: [BlobEntryKey]
144 // --------------------------------
146 // The prefix is followed by a type byte and the encoded IDB primary key.
148 // <database id, object store id, 3, user key> => array of IndexedDBBlobInfo
151 // Index data
152 // ----------
153 // The prefix is followed by a type byte, the encoded IDB index key, a
154 // "sequence" number (obsolete; var int), and the encoded IDB primary key.
156 // <database id, object store id, index id, index key, sequence number,
157 // primary key> => "version", primary key [IndexDataKey]
159 // The sequence number is obsolete; it was used to allow two entries with the
160 // same user (index) key in non-unique indexes prior to the inclusion of the
161 // primary key in the data.
163 using base::StringPiece;
164 using blink::WebIDBKeyType;
165 using blink::WebIDBKeyTypeArray;
166 using blink::WebIDBKeyTypeBinary;
167 using blink::WebIDBKeyTypeDate;
168 using blink::WebIDBKeyTypeInvalid;
169 using blink::WebIDBKeyTypeMin;
170 using blink::WebIDBKeyTypeNull;
171 using blink::WebIDBKeyTypeNumber;
172 using blink::WebIDBKeyTypeString;
173 using blink::WebIDBKeyPathType;
174 using blink::WebIDBKeyPathTypeArray;
175 using blink::WebIDBKeyPathTypeNull;
176 using blink::WebIDBKeyPathTypeString;
178 namespace content {
180 // As most of the IndexedDBKeys and encoded values are short, we
181 // initialize some std::vectors with a default inline buffer size to reduce
182 // the memory re-allocations when the std::vectors are appended.
183 static const size_t kDefaultInlineBufferSize = 32;
185 static const unsigned char kIndexedDBKeyNullTypeByte = 0;
186 static const unsigned char kIndexedDBKeyStringTypeByte = 1;
187 static const unsigned char kIndexedDBKeyDateTypeByte = 2;
188 static const unsigned char kIndexedDBKeyNumberTypeByte = 3;
189 static const unsigned char kIndexedDBKeyArrayTypeByte = 4;
190 static const unsigned char kIndexedDBKeyMinKeyTypeByte = 5;
191 static const unsigned char kIndexedDBKeyBinaryTypeByte = 6;
193 static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0;
194 static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0;
196 static const unsigned char kObjectStoreDataIndexId = 1;
197 static const unsigned char kExistsEntryIndexId = 2;
198 static const unsigned char kBlobEntryIndexId = 3;
200 static const unsigned char kSchemaVersionTypeByte = 0;
201 static const unsigned char kMaxDatabaseIdTypeByte = 1;
202 static const unsigned char kDataVersionTypeByte = 2;
203 static const unsigned char kBlobJournalTypeByte = 3;
204 static const unsigned char kLiveBlobJournalTypeByte = 4;
205 static const unsigned char kMaxSimpleGlobalMetaDataTypeByte =
206 5; // Insert before this and increment.
207 static const unsigned char kDatabaseFreeListTypeByte = 100;
208 static const unsigned char kDatabaseNameTypeByte = 201;
210 static const unsigned char kObjectStoreMetaDataTypeByte = 50;
211 static const unsigned char kIndexMetaDataTypeByte = 100;
212 static const unsigned char kObjectStoreFreeListTypeByte = 150;
213 static const unsigned char kIndexFreeListTypeByte = 151;
214 static const unsigned char kObjectStoreNamesTypeByte = 200;
215 static const unsigned char kIndexNamesKeyTypeByte = 201;
217 static const unsigned char kObjectMetaDataTypeMaximum = 255;
218 static const unsigned char kIndexMetaDataTypeMaximum = 255;
220 const unsigned char kMinimumIndexId = 30;
222 inline void EncodeIntSafely(int64 nParam, int64 max, std::string* into) {
223 DCHECK_LE(nParam, max);
224 return EncodeInt(nParam, into);
227 std::string MaxIDBKey() {
228 std::string ret;
229 EncodeByte(kIndexedDBKeyNullTypeByte, &ret);
230 return ret;
233 std::string MinIDBKey() {
234 std::string ret;
235 EncodeByte(kIndexedDBKeyMinKeyTypeByte, &ret);
236 return ret;
239 void EncodeByte(unsigned char value, std::string* into) {
240 into->push_back(value);
243 void EncodeBool(bool value, std::string* into) {
244 into->push_back(value ? 1 : 0);
247 void EncodeInt(int64 value, std::string* into) {
248 #ifndef NDEBUG
249 // Exercised by unit tests in debug only.
250 DCHECK_GE(value, 0);
251 #endif
252 uint64 n = static_cast<uint64>(value);
254 do {
255 unsigned char c = n;
256 into->push_back(c);
257 n >>= 8;
258 } while (n);
261 void EncodeVarInt(int64 value, std::string* into) {
262 #ifndef NDEBUG
263 // Exercised by unit tests in debug only.
264 DCHECK_GE(value, 0);
265 #endif
266 uint64 n = static_cast<uint64>(value);
268 do {
269 unsigned char c = n & 0x7f;
270 n >>= 7;
271 if (n)
272 c |= 0x80;
273 into->push_back(c);
274 } while (n);
277 void EncodeString(const base::string16& value, std::string* into) {
278 if (value.empty())
279 return;
280 // Backing store is UTF-16BE, convert from host endianness.
281 size_t length = value.length();
282 size_t current = into->size();
283 into->resize(into->size() + length * sizeof(base::char16));
285 const base::char16* src = value.c_str();
286 base::char16* dst =
287 reinterpret_cast<base::char16*>(&*into->begin() + current);
288 for (unsigned i = 0; i < length; ++i)
289 *dst++ = htons(*src++);
292 void EncodeBinary(const std::string& value, std::string* into) {
293 EncodeVarInt(value.length(), into);
294 into->append(value.begin(), value.end());
295 DCHECK(into->size() >= value.size());
298 void EncodeStringWithLength(const base::string16& value, std::string* into) {
299 EncodeVarInt(value.length(), into);
300 EncodeString(value, into);
303 void EncodeDouble(double value, std::string* into) {
304 // This always has host endianness.
305 const char* p = reinterpret_cast<char*>(&value);
306 into->insert(into->end(), p, p + sizeof(value));
309 void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
310 size_t previous_size = into->size();
311 DCHECK(value.IsValid());
312 switch (value.type()) {
313 case WebIDBKeyTypeArray: {
314 EncodeByte(kIndexedDBKeyArrayTypeByte, into);
315 size_t length = value.array().size();
316 EncodeVarInt(length, into);
317 for (size_t i = 0; i < length; ++i)
318 EncodeIDBKey(value.array()[i], into);
319 DCHECK_GT(into->size(), previous_size);
320 return;
322 case WebIDBKeyTypeBinary:
323 EncodeByte(kIndexedDBKeyBinaryTypeByte, into);
324 EncodeBinary(value.binary(), into);
325 DCHECK_GT(into->size(), previous_size);
326 return;
327 case WebIDBKeyTypeString:
328 EncodeByte(kIndexedDBKeyStringTypeByte, into);
329 EncodeStringWithLength(value.string(), into);
330 DCHECK_GT(into->size(), previous_size);
331 return;
332 case WebIDBKeyTypeDate:
333 EncodeByte(kIndexedDBKeyDateTypeByte, into);
334 EncodeDouble(value.date(), into);
335 DCHECK_EQ(9u, static_cast<size_t>(into->size() - previous_size));
336 return;
337 case WebIDBKeyTypeNumber:
338 EncodeByte(kIndexedDBKeyNumberTypeByte, into);
339 EncodeDouble(value.number(), into);
340 DCHECK_EQ(9u, static_cast<size_t>(into->size() - previous_size));
341 return;
342 case WebIDBKeyTypeNull:
343 case WebIDBKeyTypeInvalid:
344 case WebIDBKeyTypeMin:
345 default:
346 NOTREACHED();
347 EncodeByte(kIndexedDBKeyNullTypeByte, into);
348 return;
352 void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) {
353 // May be typed, or may be a raw string. An invalid leading
354 // byte is used to identify typed coding. New records are
355 // always written as typed.
356 EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into);
357 EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into);
358 EncodeByte(static_cast<char>(value.type()), into);
359 switch (value.type()) {
360 case WebIDBKeyPathTypeNull:
361 break;
362 case WebIDBKeyPathTypeString: {
363 EncodeStringWithLength(value.string(), into);
364 break;
366 case WebIDBKeyPathTypeArray: {
367 const std::vector<base::string16>& array = value.array();
368 size_t count = array.size();
369 EncodeVarInt(count, into);
370 for (size_t i = 0; i < count; ++i) {
371 EncodeStringWithLength(array[i], into);
373 break;
378 void EncodeBlobJournal(const BlobJournalType& journal, std::string* into) {
379 BlobJournalType::const_iterator iter;
380 for (iter = journal.begin(); iter != journal.end(); ++iter) {
381 EncodeVarInt(iter->first, into);
382 EncodeVarInt(iter->second, into);
386 bool DecodeByte(StringPiece* slice, unsigned char* value) {
387 if (slice->empty())
388 return false;
390 *value = (*slice)[0];
391 slice->remove_prefix(1);
392 return true;
395 bool DecodeBool(StringPiece* slice, bool* value) {
396 if (slice->empty())
397 return false;
399 *value = !!(*slice)[0];
400 slice->remove_prefix(1);
401 return true;
404 bool DecodeInt(StringPiece* slice, int64* value) {
405 if (slice->empty())
406 return false;
408 StringPiece::const_iterator it = slice->begin();
409 int shift = 0;
410 int64 ret = 0;
411 while (it != slice->end()) {
412 unsigned char c = *it++;
413 ret |= static_cast<int64>(c) << shift;
414 shift += 8;
416 *value = ret;
417 slice->remove_prefix(it - slice->begin());
418 return true;
421 bool DecodeVarInt(StringPiece* slice, int64* value) {
422 if (slice->empty())
423 return false;
425 StringPiece::const_iterator it = slice->begin();
426 int shift = 0;
427 int64 ret = 0;
428 do {
429 if (it == slice->end())
430 return false;
432 unsigned char c = *it;
433 ret |= static_cast<int64>(c & 0x7f) << shift;
434 shift += 7;
435 } while (*it++ & 0x80);
436 *value = ret;
437 slice->remove_prefix(it - slice->begin());
438 return true;
441 bool DecodeString(StringPiece* slice, base::string16* value) {
442 if (slice->empty()) {
443 value->clear();
444 return true;
447 // Backing store is UTF-16BE, convert to host endianness.
448 DCHECK(!(slice->size() % sizeof(base::char16)));
449 size_t length = slice->size() / sizeof(base::char16);
450 base::string16 decoded;
451 decoded.reserve(length);
452 const base::char16* encoded =
453 reinterpret_cast<const base::char16*>(slice->begin());
454 for (unsigned i = 0; i < length; ++i)
455 decoded.push_back(ntohs(*encoded++));
457 *value = decoded;
458 slice->remove_prefix(length * sizeof(base::char16));
459 return true;
462 bool DecodeStringWithLength(StringPiece* slice, base::string16* value) {
463 if (slice->empty())
464 return false;
466 int64 length = 0;
467 if (!DecodeVarInt(slice, &length) || length < 0)
468 return false;
469 size_t bytes = length * sizeof(base::char16);
470 if (slice->size() < bytes)
471 return false;
473 StringPiece subpiece(slice->begin(), bytes);
474 slice->remove_prefix(bytes);
475 if (!DecodeString(&subpiece, value))
476 return false;
478 return true;
481 bool DecodeBinary(StringPiece* slice, std::string* value) {
482 if (slice->empty())
483 return false;
485 int64 length = 0;
486 if (!DecodeVarInt(slice, &length) || length < 0)
487 return false;
488 size_t size = length;
489 if (slice->size() < size)
490 return false;
492 value->assign(slice->begin(), size);
493 slice->remove_prefix(size);
494 return true;
497 bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) {
498 if (slice->empty())
499 return false;
501 unsigned char type = (*slice)[0];
502 slice->remove_prefix(1);
504 switch (type) {
505 case kIndexedDBKeyNullTypeByte:
506 *value = make_scoped_ptr(new IndexedDBKey());
507 return true;
509 case kIndexedDBKeyArrayTypeByte: {
510 int64 length = 0;
511 if (!DecodeVarInt(slice, &length) || length < 0)
512 return false;
513 IndexedDBKey::KeyArray array;
514 while (length--) {
515 scoped_ptr<IndexedDBKey> key;
516 if (!DecodeIDBKey(slice, &key))
517 return false;
518 array.push_back(*key);
520 *value = make_scoped_ptr(new IndexedDBKey(array));
521 return true;
523 case kIndexedDBKeyBinaryTypeByte: {
524 std::string binary;
525 if (!DecodeBinary(slice, &binary))
526 return false;
527 *value = make_scoped_ptr(new IndexedDBKey(binary));
528 return true;
530 case kIndexedDBKeyStringTypeByte: {
531 base::string16 s;
532 if (!DecodeStringWithLength(slice, &s))
533 return false;
534 *value = make_scoped_ptr(new IndexedDBKey(s));
535 return true;
537 case kIndexedDBKeyDateTypeByte: {
538 double d;
539 if (!DecodeDouble(slice, &d))
540 return false;
541 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKeyTypeDate));
542 return true;
544 case kIndexedDBKeyNumberTypeByte: {
545 double d;
546 if (!DecodeDouble(slice, &d))
547 return false;
548 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKeyTypeNumber));
549 return true;
553 NOTREACHED();
554 return false;
557 bool DecodeDouble(StringPiece* slice, double* value) {
558 if (slice->size() < sizeof(*value))
559 return false;
561 memcpy(value, slice->begin(), sizeof(*value));
562 slice->remove_prefix(sizeof(*value));
563 return true;
566 bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) {
567 // May be typed, or may be a raw string. An invalid leading
568 // byte sequence is used to identify typed coding. New records are
569 // always written as typed.
570 if (slice->size() < 3 || (*slice)[0] != kIndexedDBKeyPathTypeCodedByte1 ||
571 (*slice)[1] != kIndexedDBKeyPathTypeCodedByte2) {
572 base::string16 s;
573 if (!DecodeString(slice, &s))
574 return false;
575 *value = IndexedDBKeyPath(s);
576 return true;
579 slice->remove_prefix(2);
580 DCHECK(!slice->empty());
581 WebIDBKeyPathType type = static_cast<WebIDBKeyPathType>((*slice)[0]);
582 slice->remove_prefix(1);
584 switch (type) {
585 case WebIDBKeyPathTypeNull:
586 DCHECK(slice->empty());
587 *value = IndexedDBKeyPath();
588 return true;
589 case WebIDBKeyPathTypeString: {
590 base::string16 string;
591 if (!DecodeStringWithLength(slice, &string))
592 return false;
593 DCHECK(slice->empty());
594 *value = IndexedDBKeyPath(string);
595 return true;
597 case WebIDBKeyPathTypeArray: {
598 std::vector<base::string16> array;
599 int64 count;
600 if (!DecodeVarInt(slice, &count))
601 return false;
602 DCHECK_GE(count, 0);
603 while (count--) {
604 base::string16 string;
605 if (!DecodeStringWithLength(slice, &string))
606 return false;
607 array.push_back(string);
609 DCHECK(slice->empty());
610 *value = IndexedDBKeyPath(array);
611 return true;
614 NOTREACHED();
615 return false;
618 bool DecodeBlobJournal(StringPiece* slice, BlobJournalType* journal) {
619 BlobJournalType output;
620 while (!slice->empty()) {
621 int64 database_id = -1;
622 int64 blob_key = -1;
623 if (!DecodeVarInt(slice, &database_id))
624 return false;
625 if (!KeyPrefix::IsValidDatabaseId(database_id))
626 return false;
627 if (!DecodeVarInt(slice, &blob_key))
628 return false;
629 if (!DatabaseMetaDataKey::IsValidBlobKey(blob_key) &&
630 (blob_key != DatabaseMetaDataKey::kAllBlobsKey)) {
631 return false;
633 output.push_back(std::make_pair(database_id, blob_key));
635 journal->swap(output);
636 return true;
639 bool ConsumeEncodedIDBKey(StringPiece* slice) {
640 unsigned char type = (*slice)[0];
641 slice->remove_prefix(1);
643 switch (type) {
644 case kIndexedDBKeyNullTypeByte:
645 case kIndexedDBKeyMinKeyTypeByte:
646 return true;
647 case kIndexedDBKeyArrayTypeByte: {
648 int64 length;
649 if (!DecodeVarInt(slice, &length))
650 return false;
651 while (length--) {
652 if (!ConsumeEncodedIDBKey(slice))
653 return false;
655 return true;
657 case kIndexedDBKeyBinaryTypeByte: {
658 int64 length = 0;
659 if (!DecodeVarInt(slice, &length) || length < 0)
660 return false;
661 if (slice->size() < static_cast<size_t>(length))
662 return false;
663 slice->remove_prefix(length);
664 return true;
666 case kIndexedDBKeyStringTypeByte: {
667 int64 length = 0;
668 if (!DecodeVarInt(slice, &length) || length < 0)
669 return false;
670 if (slice->size() < static_cast<size_t>(length) * sizeof(base::char16))
671 return false;
672 slice->remove_prefix(length * sizeof(base::char16));
673 return true;
675 case kIndexedDBKeyDateTypeByte:
676 case kIndexedDBKeyNumberTypeByte:
677 if (slice->size() < sizeof(double))
678 return false;
679 slice->remove_prefix(sizeof(double));
680 return true;
682 NOTREACHED();
683 return false;
686 bool ExtractEncodedIDBKey(StringPiece* slice, std::string* result) {
687 const char* start = slice->begin();
688 if (!ConsumeEncodedIDBKey(slice))
689 return false;
691 if (result)
692 result->assign(start, slice->begin());
693 return true;
696 static WebIDBKeyType KeyTypeByteToKeyType(unsigned char type) {
697 switch (type) {
698 case kIndexedDBKeyNullTypeByte:
699 return WebIDBKeyTypeInvalid;
700 case kIndexedDBKeyArrayTypeByte:
701 return WebIDBKeyTypeArray;
702 case kIndexedDBKeyBinaryTypeByte:
703 return WebIDBKeyTypeBinary;
704 case kIndexedDBKeyStringTypeByte:
705 return WebIDBKeyTypeString;
706 case kIndexedDBKeyDateTypeByte:
707 return WebIDBKeyTypeDate;
708 case kIndexedDBKeyNumberTypeByte:
709 return WebIDBKeyTypeNumber;
710 case kIndexedDBKeyMinKeyTypeByte:
711 return WebIDBKeyTypeMin;
714 NOTREACHED();
715 return WebIDBKeyTypeInvalid;
718 int CompareEncodedStringsWithLength(StringPiece* slice1,
719 StringPiece* slice2,
720 bool* ok) {
721 int64 len1, len2;
722 if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
723 *ok = false;
724 return 0;
726 DCHECK_GE(len1, 0);
727 DCHECK_GE(len2, 0);
728 if (len1 < 0 || len2 < 0) {
729 *ok = false;
730 return 0;
732 DCHECK_GE(slice1->size(), len1 * sizeof(base::char16));
733 DCHECK_GE(slice2->size(), len2 * sizeof(base::char16));
734 if (slice1->size() < len1 * sizeof(base::char16) ||
735 slice2->size() < len2 * sizeof(base::char16)) {
736 *ok = false;
737 return 0;
740 // Extract the string data, and advance the passed slices.
741 StringPiece string1(slice1->begin(), len1 * sizeof(base::char16));
742 StringPiece string2(slice2->begin(), len2 * sizeof(base::char16));
743 slice1->remove_prefix(len1 * sizeof(base::char16));
744 slice2->remove_prefix(len2 * sizeof(base::char16));
746 *ok = true;
747 // Strings are UTF-16BE encoded, so a simple memcmp is sufficient.
748 return string1.compare(string2);
751 int CompareEncodedBinary(StringPiece* slice1,
752 StringPiece* slice2,
753 bool* ok) {
754 int64 len1, len2;
755 if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
756 *ok = false;
757 return 0;
759 DCHECK_GE(len1, 0);
760 DCHECK_GE(len2, 0);
761 if (len1 < 0 || len2 < 0) {
762 *ok = false;
763 return 0;
765 size_t size1 = len1;
766 size_t size2 = len2;
768 DCHECK_GE(slice1->size(), size1);
769 DCHECK_GE(slice2->size(), size2);
770 if (slice1->size() < size1 || slice2->size() < size2) {
771 *ok = false;
772 return 0;
775 // Extract the binary data, and advance the passed slices.
776 StringPiece binary1(slice1->begin(), size1);
777 StringPiece binary2(slice2->begin(), size2);
778 slice1->remove_prefix(size1);
779 slice2->remove_prefix(size2);
781 *ok = true;
782 // This is the same as a memcmp()
783 return binary1.compare(binary2);
786 static int CompareInts(int64 a, int64 b) {
787 #ifndef NDEBUG
788 // Exercised by unit tests in debug only.
789 DCHECK_GE(a, 0);
790 DCHECK_GE(b, 0);
791 #endif
792 int64 diff = a - b;
793 if (diff < 0)
794 return -1;
795 if (diff > 0)
796 return 1;
797 return 0;
800 static inline int CompareSizes(size_t a, size_t b) {
801 if (a > b)
802 return 1;
803 if (b > a)
804 return -1;
805 return 0;
808 static int CompareTypes(WebIDBKeyType a, WebIDBKeyType b) { return b - a; }
810 int CompareEncodedIDBKeys(StringPiece* slice_a,
811 StringPiece* slice_b,
812 bool* ok) {
813 DCHECK(!slice_a->empty());
814 DCHECK(!slice_b->empty());
815 *ok = true;
816 unsigned char type_a = (*slice_a)[0];
817 unsigned char type_b = (*slice_b)[0];
818 slice_a->remove_prefix(1);
819 slice_b->remove_prefix(1);
821 if (int x = CompareTypes(KeyTypeByteToKeyType(type_a),
822 KeyTypeByteToKeyType(type_b)))
823 return x;
825 switch (type_a) {
826 case kIndexedDBKeyNullTypeByte:
827 case kIndexedDBKeyMinKeyTypeByte:
828 // Null type or max type; no payload to compare.
829 return 0;
830 case kIndexedDBKeyArrayTypeByte: {
831 int64 length_a, length_b;
832 if (!DecodeVarInt(slice_a, &length_a) ||
833 !DecodeVarInt(slice_b, &length_b)) {
834 *ok = false;
835 return 0;
837 for (int64 i = 0; i < length_a && i < length_b; ++i) {
838 int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
839 if (!*ok || result)
840 return result;
842 return length_a - length_b;
844 case kIndexedDBKeyBinaryTypeByte:
845 return CompareEncodedBinary(slice_a, slice_b, ok);
846 case kIndexedDBKeyStringTypeByte:
847 return CompareEncodedStringsWithLength(slice_a, slice_b, ok);
848 case kIndexedDBKeyDateTypeByte:
849 case kIndexedDBKeyNumberTypeByte: {
850 double d, e;
851 if (!DecodeDouble(slice_a, &d) || !DecodeDouble(slice_b, &e)) {
852 *ok = false;
853 return 0;
855 if (d < e)
856 return -1;
857 if (d > e)
858 return 1;
859 return 0;
863 NOTREACHED();
864 return 0;
867 namespace {
869 template <typename KeyType>
870 int Compare(const StringPiece& a,
871 const StringPiece& b,
872 bool only_compare_index_keys,
873 bool* ok) {
874 KeyType key_a;
875 KeyType key_b;
877 StringPiece slice_a(a);
878 if (!KeyType::Decode(&slice_a, &key_a)) {
879 *ok = false;
880 return 0;
882 StringPiece slice_b(b);
883 if (!KeyType::Decode(&slice_b, &key_b)) {
884 *ok = false;
885 return 0;
888 *ok = true;
889 return key_a.Compare(key_b);
892 template <typename KeyType>
893 int CompareSuffix(StringPiece* a,
894 StringPiece* b,
895 bool only_compare_index_keys,
896 bool* ok) {
897 NOTREACHED();
898 return 0;
901 template <>
902 int CompareSuffix<ExistsEntryKey>(StringPiece* slice_a,
903 StringPiece* slice_b,
904 bool only_compare_index_keys,
905 bool* ok) {
906 DCHECK(!slice_a->empty());
907 DCHECK(!slice_b->empty());
908 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
911 template <>
912 int CompareSuffix<ObjectStoreDataKey>(StringPiece* slice_a,
913 StringPiece* slice_b,
914 bool only_compare_index_keys,
915 bool* ok) {
916 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
919 template <>
920 int CompareSuffix<BlobEntryKey>(StringPiece* slice_a,
921 StringPiece* slice_b,
922 bool only_compare_index_keys,
923 bool* ok) {
924 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
927 template <>
928 int CompareSuffix<IndexDataKey>(StringPiece* slice_a,
929 StringPiece* slice_b,
930 bool only_compare_index_keys,
931 bool* ok) {
932 // index key
933 int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
934 if (!*ok || result)
935 return result;
936 if (only_compare_index_keys)
937 return 0;
939 // sequence number [optional]
940 int64 sequence_number_a = -1;
941 int64 sequence_number_b = -1;
942 if (!slice_a->empty() && !DecodeVarInt(slice_a, &sequence_number_a))
943 return 0;
944 if (!slice_b->empty() && !DecodeVarInt(slice_b, &sequence_number_b))
945 return 0;
947 if (slice_a->empty() || slice_b->empty())
948 return CompareSizes(slice_a->size(), slice_b->size());
950 // primary key [optional]
951 result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
952 if (!*ok || result)
953 return result;
955 return CompareInts(sequence_number_a, sequence_number_b);
958 int Compare(const StringPiece& a,
959 const StringPiece& b,
960 bool only_compare_index_keys,
961 bool* ok) {
962 StringPiece slice_a(a);
963 StringPiece slice_b(b);
964 KeyPrefix prefix_a;
965 KeyPrefix prefix_b;
966 bool ok_a = KeyPrefix::Decode(&slice_a, &prefix_a);
967 bool ok_b = KeyPrefix::Decode(&slice_b, &prefix_b);
968 DCHECK(ok_a);
969 DCHECK(ok_b);
970 if (!ok_a || !ok_b) {
971 *ok = false;
972 return 0;
975 *ok = true;
976 if (int x = prefix_a.Compare(prefix_b))
977 return x;
979 switch (prefix_a.type()) {
980 case KeyPrefix::GLOBAL_METADATA: {
981 DCHECK(!slice_a.empty());
982 DCHECK(!slice_b.empty());
984 unsigned char type_byte_a;
985 if (!DecodeByte(&slice_a, &type_byte_a)) {
986 *ok = false;
987 return 0;
990 unsigned char type_byte_b;
991 if (!DecodeByte(&slice_b, &type_byte_b)) {
992 *ok = false;
993 return 0;
996 if (int x = type_byte_a - type_byte_b)
997 return x;
998 if (type_byte_a < kMaxSimpleGlobalMetaDataTypeByte)
999 return 0;
1001 // Compare<> is used (which re-decodes the prefix) rather than an
1002 // specialized CompareSuffix<> because metadata is relatively uncommon
1003 // in the database.
1005 if (type_byte_a == kDatabaseFreeListTypeByte) {
1006 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1007 return Compare<DatabaseFreeListKey>(a, b, only_compare_index_keys, ok);
1009 if (type_byte_a == kDatabaseNameTypeByte) {
1010 return Compare<DatabaseNameKey>(
1011 a, b, /*only_compare_index_keys*/ false, ok);
1013 break;
1016 case KeyPrefix::DATABASE_METADATA: {
1017 DCHECK(!slice_a.empty());
1018 DCHECK(!slice_b.empty());
1020 unsigned char type_byte_a;
1021 if (!DecodeByte(&slice_a, &type_byte_a)) {
1022 *ok = false;
1023 return 0;
1026 unsigned char type_byte_b;
1027 if (!DecodeByte(&slice_b, &type_byte_b)) {
1028 *ok = false;
1029 return 0;
1032 if (int x = type_byte_a - type_byte_b)
1033 return x;
1034 if (type_byte_a < DatabaseMetaDataKey::MAX_SIMPLE_METADATA_TYPE)
1035 return 0;
1037 // Compare<> is used (which re-decodes the prefix) rather than an
1038 // specialized CompareSuffix<> because metadata is relatively uncommon
1039 // in the database.
1041 if (type_byte_a == kObjectStoreMetaDataTypeByte) {
1042 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1043 return Compare<ObjectStoreMetaDataKey>(
1044 a, b, only_compare_index_keys, ok);
1046 if (type_byte_a == kIndexMetaDataTypeByte) {
1047 return Compare<IndexMetaDataKey>(
1048 a, b, /*only_compare_index_keys*/ false, ok);
1050 if (type_byte_a == kObjectStoreFreeListTypeByte) {
1051 return Compare<ObjectStoreFreeListKey>(
1052 a, b, only_compare_index_keys, ok);
1054 if (type_byte_a == kIndexFreeListTypeByte) {
1055 return Compare<IndexFreeListKey>(
1056 a, b, /*only_compare_index_keys*/ false, ok);
1058 if (type_byte_a == kObjectStoreNamesTypeByte) {
1059 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1060 return Compare<ObjectStoreNamesKey>(
1061 a, b, only_compare_index_keys, ok);
1063 if (type_byte_a == kIndexNamesKeyTypeByte) {
1064 return Compare<IndexNamesKey>(
1065 a, b, /*only_compare_index_keys*/ false, ok);
1067 break;
1070 case KeyPrefix::OBJECT_STORE_DATA: {
1071 // Provide a stable ordering for invalid data.
1072 if (slice_a.empty() || slice_b.empty())
1073 return CompareSizes(slice_a.size(), slice_b.size());
1075 return CompareSuffix<ObjectStoreDataKey>(
1076 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1079 case KeyPrefix::EXISTS_ENTRY: {
1080 // Provide a stable ordering for invalid data.
1081 if (slice_a.empty() || slice_b.empty())
1082 return CompareSizes(slice_a.size(), slice_b.size());
1084 return CompareSuffix<ExistsEntryKey>(
1085 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1088 case KeyPrefix::BLOB_ENTRY: {
1089 // Provide a stable ordering for invalid data.
1090 if (slice_a.empty() || slice_b.empty())
1091 return CompareSizes(slice_a.size(), slice_b.size());
1093 return CompareSuffix<BlobEntryKey>(
1094 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1097 case KeyPrefix::INDEX_DATA: {
1098 // Provide a stable ordering for invalid data.
1099 if (slice_a.empty() || slice_b.empty())
1100 return CompareSizes(slice_a.size(), slice_b.size());
1102 return CompareSuffix<IndexDataKey>(
1103 &slice_a, &slice_b, only_compare_index_keys, ok);
1106 case KeyPrefix::INVALID_TYPE:
1107 break;
1110 NOTREACHED();
1111 *ok = false;
1112 return 0;
1115 } // namespace
1117 int Compare(const StringPiece& a,
1118 const StringPiece& b,
1119 bool only_compare_index_keys) {
1120 bool ok;
1121 int result = Compare(a, b, only_compare_index_keys, &ok);
1122 DCHECK(ok);
1123 if (!ok)
1124 return 0;
1125 return result;
1128 KeyPrefix::KeyPrefix()
1129 : database_id_(INVALID_TYPE),
1130 object_store_id_(INVALID_TYPE),
1131 index_id_(INVALID_TYPE) {}
1133 KeyPrefix::KeyPrefix(int64 database_id)
1134 : database_id_(database_id), object_store_id_(0), index_id_(0) {
1135 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1138 KeyPrefix::KeyPrefix(int64 database_id, int64 object_store_id)
1139 : database_id_(database_id),
1140 object_store_id_(object_store_id),
1141 index_id_(0) {
1142 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1143 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1146 KeyPrefix::KeyPrefix(int64 database_id, int64 object_store_id, int64 index_id)
1147 : database_id_(database_id),
1148 object_store_id_(object_store_id),
1149 index_id_(index_id) {
1150 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1151 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1152 DCHECK(KeyPrefix::IsValidIndexId(index_id));
1155 KeyPrefix::KeyPrefix(enum Type type,
1156 int64 database_id,
1157 int64 object_store_id,
1158 int64 index_id)
1159 : database_id_(database_id),
1160 object_store_id_(object_store_id),
1161 index_id_(index_id) {
1162 DCHECK_EQ(type, INVALID_TYPE);
1163 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1164 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1167 KeyPrefix KeyPrefix::CreateWithSpecialIndex(int64 database_id,
1168 int64 object_store_id,
1169 int64 index_id) {
1170 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1171 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1172 DCHECK(index_id);
1173 return KeyPrefix(INVALID_TYPE, database_id, object_store_id, index_id);
1176 bool KeyPrefix::IsValidDatabaseId(int64 database_id) {
1177 return (database_id > 0) && (database_id < KeyPrefix::kMaxDatabaseId);
1180 bool KeyPrefix::IsValidObjectStoreId(int64 object_store_id) {
1181 return (object_store_id > 0) &&
1182 (object_store_id < KeyPrefix::kMaxObjectStoreId);
1185 bool KeyPrefix::IsValidIndexId(int64 index_id) {
1186 return (index_id >= kMinimumIndexId) && (index_id < KeyPrefix::kMaxIndexId);
1189 bool KeyPrefix::Decode(StringPiece* slice, KeyPrefix* result) {
1190 unsigned char first_byte;
1191 if (!DecodeByte(slice, &first_byte))
1192 return false;
1194 size_t database_id_bytes = ((first_byte >> 5) & 0x7) + 1;
1195 size_t object_store_id_bytes = ((first_byte >> 2) & 0x7) + 1;
1196 size_t index_id_bytes = (first_byte & 0x3) + 1;
1198 if (database_id_bytes + object_store_id_bytes + index_id_bytes >
1199 slice->size())
1200 return false;
1203 StringPiece tmp(slice->begin(), database_id_bytes);
1204 if (!DecodeInt(&tmp, &result->database_id_))
1205 return false;
1207 slice->remove_prefix(database_id_bytes);
1209 StringPiece tmp(slice->begin(), object_store_id_bytes);
1210 if (!DecodeInt(&tmp, &result->object_store_id_))
1211 return false;
1213 slice->remove_prefix(object_store_id_bytes);
1215 StringPiece tmp(slice->begin(), index_id_bytes);
1216 if (!DecodeInt(&tmp, &result->index_id_))
1217 return false;
1219 slice->remove_prefix(index_id_bytes);
1220 return true;
1223 std::string KeyPrefix::EncodeEmpty() {
1224 const std::string result(4, 0);
1225 DCHECK(EncodeInternal(0, 0, 0) == std::string(4, 0));
1226 return result;
1229 std::string KeyPrefix::Encode() const {
1230 DCHECK(database_id_ != kInvalidId);
1231 DCHECK(object_store_id_ != kInvalidId);
1232 DCHECK(index_id_ != kInvalidId);
1233 return EncodeInternal(database_id_, object_store_id_, index_id_);
1236 std::string KeyPrefix::EncodeInternal(int64 database_id,
1237 int64 object_store_id,
1238 int64 index_id) {
1239 std::string database_id_string;
1240 std::string object_store_id_string;
1241 std::string index_id_string;
1243 EncodeIntSafely(database_id, kMaxDatabaseId, &database_id_string);
1244 EncodeIntSafely(object_store_id, kMaxObjectStoreId, &object_store_id_string);
1245 EncodeIntSafely(index_id, kMaxIndexId, &index_id_string);
1247 DCHECK(database_id_string.size() <= kMaxDatabaseIdSizeBytes);
1248 DCHECK(object_store_id_string.size() <= kMaxObjectStoreIdSizeBytes);
1249 DCHECK(index_id_string.size() <= kMaxIndexIdSizeBytes);
1251 unsigned char first_byte =
1252 (database_id_string.size() - 1) << (kMaxObjectStoreIdSizeBits +
1253 kMaxIndexIdSizeBits) |
1254 (object_store_id_string.size() - 1) << kMaxIndexIdSizeBits |
1255 (index_id_string.size() - 1);
1256 COMPILE_ASSERT(kMaxDatabaseIdSizeBits + kMaxObjectStoreIdSizeBits +
1257 kMaxIndexIdSizeBits ==
1258 sizeof(first_byte) * 8,
1259 CANT_ENCODE_IDS);
1260 std::string ret;
1261 ret.reserve(kDefaultInlineBufferSize);
1262 ret.push_back(first_byte);
1263 ret.append(database_id_string);
1264 ret.append(object_store_id_string);
1265 ret.append(index_id_string);
1267 DCHECK_LE(ret.size(), kDefaultInlineBufferSize);
1268 return ret;
1271 int KeyPrefix::Compare(const KeyPrefix& other) const {
1272 DCHECK(database_id_ != kInvalidId);
1273 DCHECK(object_store_id_ != kInvalidId);
1274 DCHECK(index_id_ != kInvalidId);
1276 if (database_id_ != other.database_id_)
1277 return CompareInts(database_id_, other.database_id_);
1278 if (object_store_id_ != other.object_store_id_)
1279 return CompareInts(object_store_id_, other.object_store_id_);
1280 if (index_id_ != other.index_id_)
1281 return CompareInts(index_id_, other.index_id_);
1282 return 0;
1285 KeyPrefix::Type KeyPrefix::type() const {
1286 DCHECK(database_id_ != kInvalidId);
1287 DCHECK(object_store_id_ != kInvalidId);
1288 DCHECK(index_id_ != kInvalidId);
1290 if (!database_id_)
1291 return GLOBAL_METADATA;
1292 if (!object_store_id_)
1293 return DATABASE_METADATA;
1294 if (index_id_ == kObjectStoreDataIndexId)
1295 return OBJECT_STORE_DATA;
1296 if (index_id_ == kExistsEntryIndexId)
1297 return EXISTS_ENTRY;
1298 if (index_id_ == kBlobEntryIndexId)
1299 return BLOB_ENTRY;
1300 if (index_id_ >= kMinimumIndexId)
1301 return INDEX_DATA;
1303 NOTREACHED();
1304 return INVALID_TYPE;
1307 std::string SchemaVersionKey::Encode() {
1308 std::string ret = KeyPrefix::EncodeEmpty();
1309 ret.push_back(kSchemaVersionTypeByte);
1310 return ret;
1313 std::string MaxDatabaseIdKey::Encode() {
1314 std::string ret = KeyPrefix::EncodeEmpty();
1315 ret.push_back(kMaxDatabaseIdTypeByte);
1316 return ret;
1319 std::string DataVersionKey::Encode() {
1320 std::string ret = KeyPrefix::EncodeEmpty();
1321 ret.push_back(kDataVersionTypeByte);
1322 return ret;
1325 std::string BlobJournalKey::Encode() {
1326 std::string ret = KeyPrefix::EncodeEmpty();
1327 ret.push_back(kBlobJournalTypeByte);
1328 return ret;
1331 std::string LiveBlobJournalKey::Encode() {
1332 std::string ret = KeyPrefix::EncodeEmpty();
1333 ret.push_back(kLiveBlobJournalTypeByte);
1334 return ret;
1337 DatabaseFreeListKey::DatabaseFreeListKey() : database_id_(-1) {}
1339 bool DatabaseFreeListKey::Decode(StringPiece* slice,
1340 DatabaseFreeListKey* result) {
1341 KeyPrefix prefix;
1342 if (!KeyPrefix::Decode(slice, &prefix))
1343 return false;
1344 DCHECK(!prefix.database_id_);
1345 DCHECK(!prefix.object_store_id_);
1346 DCHECK(!prefix.index_id_);
1347 unsigned char type_byte = 0;
1348 if (!DecodeByte(slice, &type_byte))
1349 return false;
1350 DCHECK_EQ(type_byte, kDatabaseFreeListTypeByte);
1351 if (!DecodeVarInt(slice, &result->database_id_))
1352 return false;
1353 return true;
1356 std::string DatabaseFreeListKey::Encode(int64 database_id) {
1357 std::string ret = KeyPrefix::EncodeEmpty();
1358 ret.push_back(kDatabaseFreeListTypeByte);
1359 EncodeVarInt(database_id, &ret);
1360 return ret;
1363 std::string DatabaseFreeListKey::EncodeMaxKey() {
1364 return Encode(std::numeric_limits<int64>::max());
1367 int64 DatabaseFreeListKey::DatabaseId() const {
1368 DCHECK_GE(database_id_, 0);
1369 return database_id_;
1372 int DatabaseFreeListKey::Compare(const DatabaseFreeListKey& other) const {
1373 DCHECK_GE(database_id_, 0);
1374 return CompareInts(database_id_, other.database_id_);
1377 bool DatabaseNameKey::Decode(StringPiece* slice, DatabaseNameKey* result) {
1378 KeyPrefix prefix;
1379 if (!KeyPrefix::Decode(slice, &prefix))
1380 return false;
1381 DCHECK(!prefix.database_id_);
1382 DCHECK(!prefix.object_store_id_);
1383 DCHECK(!prefix.index_id_);
1384 unsigned char type_byte = 0;
1385 if (!DecodeByte(slice, &type_byte))
1386 return false;
1387 DCHECK_EQ(type_byte, kDatabaseNameTypeByte);
1388 if (!DecodeStringWithLength(slice, &result->origin_))
1389 return false;
1390 if (!DecodeStringWithLength(slice, &result->database_name_))
1391 return false;
1392 return true;
1395 std::string DatabaseNameKey::Encode(const std::string& origin_identifier,
1396 const base::string16& database_name) {
1397 std::string ret = KeyPrefix::EncodeEmpty();
1398 ret.push_back(kDatabaseNameTypeByte);
1399 EncodeStringWithLength(base::ASCIIToUTF16(origin_identifier), &ret);
1400 EncodeStringWithLength(database_name, &ret);
1401 return ret;
1404 std::string DatabaseNameKey::EncodeMinKeyForOrigin(
1405 const std::string& origin_identifier) {
1406 return Encode(origin_identifier, base::string16());
1409 std::string DatabaseNameKey::EncodeStopKeyForOrigin(
1410 const std::string& origin_identifier) {
1411 // just after origin in collation order
1412 return EncodeMinKeyForOrigin(origin_identifier + '\x01');
1415 int DatabaseNameKey::Compare(const DatabaseNameKey& other) {
1416 if (int x = origin_.compare(other.origin_))
1417 return x;
1418 return database_name_.compare(other.database_name_);
1421 bool DatabaseMetaDataKey::IsValidBlobKey(int64 blob_key) {
1422 return blob_key >= kBlobKeyGeneratorInitialNumber;
1425 const int64 DatabaseMetaDataKey::kAllBlobsKey = 1;
1426 const int64 DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber = 2;
1427 const int64 DatabaseMetaDataKey::kInvalidBlobKey = -1;
1429 std::string DatabaseMetaDataKey::Encode(int64 database_id,
1430 MetaDataType meta_data_type) {
1431 KeyPrefix prefix(database_id);
1432 std::string ret = prefix.Encode();
1433 ret.push_back(meta_data_type);
1434 return ret;
1437 ObjectStoreMetaDataKey::ObjectStoreMetaDataKey()
1438 : object_store_id_(-1), meta_data_type_(-1) {}
1440 bool ObjectStoreMetaDataKey::Decode(StringPiece* slice,
1441 ObjectStoreMetaDataKey* result) {
1442 KeyPrefix prefix;
1443 if (!KeyPrefix::Decode(slice, &prefix))
1444 return false;
1445 DCHECK(prefix.database_id_);
1446 DCHECK(!prefix.object_store_id_);
1447 DCHECK(!prefix.index_id_);
1448 unsigned char type_byte = 0;
1449 if (!DecodeByte(slice, &type_byte))
1450 return false;
1451 DCHECK_EQ(type_byte, kObjectStoreMetaDataTypeByte);
1452 if (!DecodeVarInt(slice, &result->object_store_id_))
1453 return false;
1454 DCHECK(result->object_store_id_);
1455 if (!DecodeByte(slice, &result->meta_data_type_))
1456 return false;
1457 return true;
1460 std::string ObjectStoreMetaDataKey::Encode(int64 database_id,
1461 int64 object_store_id,
1462 unsigned char meta_data_type) {
1463 KeyPrefix prefix(database_id);
1464 std::string ret = prefix.Encode();
1465 ret.push_back(kObjectStoreMetaDataTypeByte);
1466 EncodeVarInt(object_store_id, &ret);
1467 ret.push_back(meta_data_type);
1468 return ret;
1471 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id) {
1472 return Encode(database_id,
1473 std::numeric_limits<int64>::max(),
1474 kObjectMetaDataTypeMaximum);
1477 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id,
1478 int64 object_store_id) {
1479 return Encode(database_id, object_store_id, kObjectMetaDataTypeMaximum);
1482 int64 ObjectStoreMetaDataKey::ObjectStoreId() const {
1483 DCHECK_GE(object_store_id_, 0);
1484 return object_store_id_;
1486 unsigned char ObjectStoreMetaDataKey::MetaDataType() const {
1487 return meta_data_type_;
1490 int ObjectStoreMetaDataKey::Compare(const ObjectStoreMetaDataKey& other) {
1491 DCHECK_GE(object_store_id_, 0);
1492 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1493 return x;
1494 return meta_data_type_ - other.meta_data_type_;
1497 IndexMetaDataKey::IndexMetaDataKey()
1498 : object_store_id_(-1), index_id_(-1), meta_data_type_(0) {}
1500 bool IndexMetaDataKey::Decode(StringPiece* slice, IndexMetaDataKey* result) {
1501 KeyPrefix prefix;
1502 if (!KeyPrefix::Decode(slice, &prefix))
1503 return false;
1504 DCHECK(prefix.database_id_);
1505 DCHECK(!prefix.object_store_id_);
1506 DCHECK(!prefix.index_id_);
1507 unsigned char type_byte = 0;
1508 if (!DecodeByte(slice, &type_byte))
1509 return false;
1510 DCHECK_EQ(type_byte, kIndexMetaDataTypeByte);
1511 if (!DecodeVarInt(slice, &result->object_store_id_))
1512 return false;
1513 if (!DecodeVarInt(slice, &result->index_id_))
1514 return false;
1515 if (!DecodeByte(slice, &result->meta_data_type_))
1516 return false;
1517 return true;
1520 std::string IndexMetaDataKey::Encode(int64 database_id,
1521 int64 object_store_id,
1522 int64 index_id,
1523 unsigned char meta_data_type) {
1524 KeyPrefix prefix(database_id);
1525 std::string ret = prefix.Encode();
1526 ret.push_back(kIndexMetaDataTypeByte);
1527 EncodeVarInt(object_store_id, &ret);
1528 EncodeVarInt(index_id, &ret);
1529 EncodeByte(meta_data_type, &ret);
1530 return ret;
1533 std::string IndexMetaDataKey::EncodeMaxKey(int64 database_id,
1534 int64 object_store_id) {
1535 return Encode(database_id,
1536 object_store_id,
1537 std::numeric_limits<int64>::max(),
1538 kIndexMetaDataTypeMaximum);
1541 std::string IndexMetaDataKey::EncodeMaxKey(int64 database_id,
1542 int64 object_store_id,
1543 int64 index_id) {
1544 return Encode(
1545 database_id, object_store_id, index_id, kIndexMetaDataTypeMaximum);
1548 int IndexMetaDataKey::Compare(const IndexMetaDataKey& other) {
1549 DCHECK_GE(object_store_id_, 0);
1550 DCHECK_GE(index_id_, 0);
1552 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1553 return x;
1554 if (int x = CompareInts(index_id_, other.index_id_))
1555 return x;
1556 return meta_data_type_ - other.meta_data_type_;
1559 int64 IndexMetaDataKey::IndexId() const {
1560 DCHECK_GE(index_id_, 0);
1561 return index_id_;
1564 ObjectStoreFreeListKey::ObjectStoreFreeListKey() : object_store_id_(-1) {}
1566 bool ObjectStoreFreeListKey::Decode(StringPiece* slice,
1567 ObjectStoreFreeListKey* result) {
1568 KeyPrefix prefix;
1569 if (!KeyPrefix::Decode(slice, &prefix))
1570 return false;
1571 DCHECK(prefix.database_id_);
1572 DCHECK(!prefix.object_store_id_);
1573 DCHECK(!prefix.index_id_);
1574 unsigned char type_byte = 0;
1575 if (!DecodeByte(slice, &type_byte))
1576 return false;
1577 DCHECK_EQ(type_byte, kObjectStoreFreeListTypeByte);
1578 if (!DecodeVarInt(slice, &result->object_store_id_))
1579 return false;
1580 return true;
1583 std::string ObjectStoreFreeListKey::Encode(int64 database_id,
1584 int64 object_store_id) {
1585 KeyPrefix prefix(database_id);
1586 std::string ret = prefix.Encode();
1587 ret.push_back(kObjectStoreFreeListTypeByte);
1588 EncodeVarInt(object_store_id, &ret);
1589 return ret;
1592 std::string ObjectStoreFreeListKey::EncodeMaxKey(int64 database_id) {
1593 return Encode(database_id, std::numeric_limits<int64>::max());
1596 int64 ObjectStoreFreeListKey::ObjectStoreId() const {
1597 DCHECK_GE(object_store_id_, 0);
1598 return object_store_id_;
1601 int ObjectStoreFreeListKey::Compare(const ObjectStoreFreeListKey& other) {
1602 // TODO(jsbell): It may seem strange that we're not comparing database id's,
1603 // but that comparison will have been made earlier.
1604 // We should probably make this more clear, though...
1605 DCHECK_GE(object_store_id_, 0);
1606 return CompareInts(object_store_id_, other.object_store_id_);
1609 IndexFreeListKey::IndexFreeListKey() : object_store_id_(-1), index_id_(-1) {}
1611 bool IndexFreeListKey::Decode(StringPiece* slice, IndexFreeListKey* result) {
1612 KeyPrefix prefix;
1613 if (!KeyPrefix::Decode(slice, &prefix))
1614 return false;
1615 DCHECK(prefix.database_id_);
1616 DCHECK(!prefix.object_store_id_);
1617 DCHECK(!prefix.index_id_);
1618 unsigned char type_byte = 0;
1619 if (!DecodeByte(slice, &type_byte))
1620 return false;
1621 DCHECK_EQ(type_byte, kIndexFreeListTypeByte);
1622 if (!DecodeVarInt(slice, &result->object_store_id_))
1623 return false;
1624 if (!DecodeVarInt(slice, &result->index_id_))
1625 return false;
1626 return true;
1629 std::string IndexFreeListKey::Encode(int64 database_id,
1630 int64 object_store_id,
1631 int64 index_id) {
1632 KeyPrefix prefix(database_id);
1633 std::string ret = prefix.Encode();
1634 ret.push_back(kIndexFreeListTypeByte);
1635 EncodeVarInt(object_store_id, &ret);
1636 EncodeVarInt(index_id, &ret);
1637 return ret;
1640 std::string IndexFreeListKey::EncodeMaxKey(int64 database_id,
1641 int64 object_store_id) {
1642 return Encode(
1643 database_id, object_store_id, std::numeric_limits<int64>::max());
1646 int IndexFreeListKey::Compare(const IndexFreeListKey& other) {
1647 DCHECK_GE(object_store_id_, 0);
1648 DCHECK_GE(index_id_, 0);
1649 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1650 return x;
1651 return CompareInts(index_id_, other.index_id_);
1654 int64 IndexFreeListKey::ObjectStoreId() const {
1655 DCHECK_GE(object_store_id_, 0);
1656 return object_store_id_;
1659 int64 IndexFreeListKey::IndexId() const {
1660 DCHECK_GE(index_id_, 0);
1661 return index_id_;
1664 // TODO(jsbell): We never use this to look up object store ids,
1665 // because a mapping is kept in the IndexedDBDatabase. Can the
1666 // mapping become unreliable? Can we remove this?
1667 bool ObjectStoreNamesKey::Decode(StringPiece* slice,
1668 ObjectStoreNamesKey* result) {
1669 KeyPrefix prefix;
1670 if (!KeyPrefix::Decode(slice, &prefix))
1671 return false;
1672 DCHECK(prefix.database_id_);
1673 DCHECK(!prefix.object_store_id_);
1674 DCHECK(!prefix.index_id_);
1675 unsigned char type_byte = 0;
1676 if (!DecodeByte(slice, &type_byte))
1677 return false;
1678 DCHECK_EQ(type_byte, kObjectStoreNamesTypeByte);
1679 if (!DecodeStringWithLength(slice, &result->object_store_name_))
1680 return false;
1681 return true;
1684 std::string ObjectStoreNamesKey::Encode(
1685 int64 database_id,
1686 const base::string16& object_store_name) {
1687 KeyPrefix prefix(database_id);
1688 std::string ret = prefix.Encode();
1689 ret.push_back(kObjectStoreNamesTypeByte);
1690 EncodeStringWithLength(object_store_name, &ret);
1691 return ret;
1694 int ObjectStoreNamesKey::Compare(const ObjectStoreNamesKey& other) {
1695 return object_store_name_.compare(other.object_store_name_);
1698 IndexNamesKey::IndexNamesKey() : object_store_id_(-1) {}
1700 // TODO(jsbell): We never use this to look up index ids, because a mapping
1701 // is kept at a higher level.
1702 bool IndexNamesKey::Decode(StringPiece* slice, IndexNamesKey* result) {
1703 KeyPrefix prefix;
1704 if (!KeyPrefix::Decode(slice, &prefix))
1705 return false;
1706 DCHECK(prefix.database_id_);
1707 DCHECK(!prefix.object_store_id_);
1708 DCHECK(!prefix.index_id_);
1709 unsigned char type_byte = 0;
1710 if (!DecodeByte(slice, &type_byte))
1711 return false;
1712 DCHECK_EQ(type_byte, kIndexNamesKeyTypeByte);
1713 if (!DecodeVarInt(slice, &result->object_store_id_))
1714 return false;
1715 if (!DecodeStringWithLength(slice, &result->index_name_))
1716 return false;
1717 return true;
1720 std::string IndexNamesKey::Encode(int64 database_id,
1721 int64 object_store_id,
1722 const base::string16& index_name) {
1723 KeyPrefix prefix(database_id);
1724 std::string ret = prefix.Encode();
1725 ret.push_back(kIndexNamesKeyTypeByte);
1726 EncodeVarInt(object_store_id, &ret);
1727 EncodeStringWithLength(index_name, &ret);
1728 return ret;
1731 int IndexNamesKey::Compare(const IndexNamesKey& other) {
1732 DCHECK_GE(object_store_id_, 0);
1733 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1734 return x;
1735 return index_name_.compare(other.index_name_);
1738 ObjectStoreDataKey::ObjectStoreDataKey() {}
1739 ObjectStoreDataKey::~ObjectStoreDataKey() {}
1741 bool ObjectStoreDataKey::Decode(StringPiece* slice,
1742 ObjectStoreDataKey* result) {
1743 KeyPrefix prefix;
1744 if (!KeyPrefix::Decode(slice, &prefix))
1745 return false;
1746 DCHECK(prefix.database_id_);
1747 DCHECK(prefix.object_store_id_);
1748 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1749 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1750 return false;
1751 return true;
1754 std::string ObjectStoreDataKey::Encode(int64 database_id,
1755 int64 object_store_id,
1756 const std::string encoded_user_key) {
1757 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1758 database_id, object_store_id, kSpecialIndexNumber));
1759 std::string ret = prefix.Encode();
1760 ret.append(encoded_user_key);
1762 return ret;
1765 std::string ObjectStoreDataKey::Encode(int64 database_id,
1766 int64 object_store_id,
1767 const IndexedDBKey& user_key) {
1768 std::string encoded_key;
1769 EncodeIDBKey(user_key, &encoded_key);
1770 return Encode(database_id, object_store_id, encoded_key);
1773 scoped_ptr<IndexedDBKey> ObjectStoreDataKey::user_key() const {
1774 scoped_ptr<IndexedDBKey> key;
1775 StringPiece slice(encoded_user_key_);
1776 if (!DecodeIDBKey(&slice, &key)) {
1777 // TODO(jsbell): Return error.
1779 return key.Pass();
1782 const int64 ObjectStoreDataKey::kSpecialIndexNumber = kObjectStoreDataIndexId;
1784 ExistsEntryKey::ExistsEntryKey() {}
1785 ExistsEntryKey::~ExistsEntryKey() {}
1787 bool ExistsEntryKey::Decode(StringPiece* slice, ExistsEntryKey* result) {
1788 KeyPrefix prefix;
1789 if (!KeyPrefix::Decode(slice, &prefix))
1790 return false;
1791 DCHECK(prefix.database_id_);
1792 DCHECK(prefix.object_store_id_);
1793 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1794 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1795 return false;
1796 return true;
1799 std::string ExistsEntryKey::Encode(int64 database_id,
1800 int64 object_store_id,
1801 const std::string& encoded_key) {
1802 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1803 database_id, object_store_id, kSpecialIndexNumber));
1804 std::string ret = prefix.Encode();
1805 ret.append(encoded_key);
1806 return ret;
1809 std::string ExistsEntryKey::Encode(int64 database_id,
1810 int64 object_store_id,
1811 const IndexedDBKey& user_key) {
1812 std::string encoded_key;
1813 EncodeIDBKey(user_key, &encoded_key);
1814 return Encode(database_id, object_store_id, encoded_key);
1817 scoped_ptr<IndexedDBKey> ExistsEntryKey::user_key() const {
1818 scoped_ptr<IndexedDBKey> key;
1819 StringPiece slice(encoded_user_key_);
1820 if (!DecodeIDBKey(&slice, &key)) {
1821 // TODO(jsbell): Return error.
1823 return key.Pass();
1826 const int64 ExistsEntryKey::kSpecialIndexNumber = kExistsEntryIndexId;
1828 bool BlobEntryKey::Decode(StringPiece* slice, BlobEntryKey* result) {
1829 KeyPrefix prefix;
1830 if (!KeyPrefix::Decode(slice, &prefix))
1831 return false;
1832 DCHECK(prefix.database_id_);
1833 DCHECK(prefix.object_store_id_);
1834 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1836 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1837 return false;
1838 result->database_id_ = prefix.database_id_;
1839 result->object_store_id_ = prefix.object_store_id_;
1841 return true;
1844 bool BlobEntryKey::FromObjectStoreDataKey(StringPiece* slice,
1845 BlobEntryKey* result) {
1846 KeyPrefix prefix;
1847 if (!KeyPrefix::Decode(slice, &prefix))
1848 return false;
1849 DCHECK(prefix.database_id_);
1850 DCHECK(prefix.object_store_id_);
1851 DCHECK_EQ(prefix.index_id_, ObjectStoreDataKey::kSpecialIndexNumber);
1853 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1854 return false;
1855 result->database_id_ = prefix.database_id_;
1856 result->object_store_id_ = prefix.object_store_id_;
1857 return true;
1860 std::string BlobEntryKey::ReencodeToObjectStoreDataKey(StringPiece* slice) {
1861 // TODO(ericu): We could be more efficient here, since the suffix is the same.
1862 BlobEntryKey key;
1863 if (!Decode(slice, &key))
1864 return std::string();
1866 return ObjectStoreDataKey::Encode(
1867 key.database_id_, key.object_store_id_, key.encoded_user_key_);
1870 std::string BlobEntryKey::EncodeMinKeyForObjectStore(int64 database_id,
1871 int64 object_store_id) {
1872 // Our implied encoded_user_key_ here is empty, the lowest possible key.
1873 return Encode(database_id, object_store_id, std::string());
1876 std::string BlobEntryKey::EncodeStopKeyForObjectStore(int64 database_id,
1877 int64 object_store_id) {
1878 DCHECK(KeyPrefix::ValidIds(database_id, object_store_id));
1879 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1880 database_id, object_store_id, kSpecialIndexNumber + 1));
1881 return prefix.Encode();
1884 std::string BlobEntryKey::Encode() const {
1885 DCHECK(!encoded_user_key_.empty());
1886 return Encode(database_id_, object_store_id_, encoded_user_key_);
1889 std::string BlobEntryKey::Encode(int64 database_id,
1890 int64 object_store_id,
1891 const IndexedDBKey& user_key) {
1892 std::string encoded_key;
1893 EncodeIDBKey(user_key, &encoded_key);
1894 return Encode(database_id, object_store_id, encoded_key);
1897 std::string BlobEntryKey::Encode(int64 database_id,
1898 int64 object_store_id,
1899 const std::string& encoded_user_key) {
1900 DCHECK(KeyPrefix::ValidIds(database_id, object_store_id));
1901 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1902 database_id, object_store_id, kSpecialIndexNumber));
1903 return prefix.Encode() + encoded_user_key;
1906 const int64 BlobEntryKey::kSpecialIndexNumber = kBlobEntryIndexId;
1908 IndexDataKey::IndexDataKey()
1909 : database_id_(-1),
1910 object_store_id_(-1),
1911 index_id_(-1),
1912 sequence_number_(-1) {}
1914 IndexDataKey::~IndexDataKey() {}
1916 bool IndexDataKey::Decode(StringPiece* slice, IndexDataKey* result) {
1917 KeyPrefix prefix;
1918 if (!KeyPrefix::Decode(slice, &prefix))
1919 return false;
1920 DCHECK(prefix.database_id_);
1921 DCHECK(prefix.object_store_id_);
1922 DCHECK_GE(prefix.index_id_, kMinimumIndexId);
1923 result->database_id_ = prefix.database_id_;
1924 result->object_store_id_ = prefix.object_store_id_;
1925 result->index_id_ = prefix.index_id_;
1926 result->sequence_number_ = -1;
1927 result->encoded_primary_key_ = MinIDBKey();
1929 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1930 return false;
1932 // [optional] sequence number
1933 if (slice->empty())
1934 return true;
1935 if (!DecodeVarInt(slice, &result->sequence_number_))
1936 return false;
1938 // [optional] primary key
1939 if (slice->empty())
1940 return true;
1941 if (!ExtractEncodedIDBKey(slice, &result->encoded_primary_key_))
1942 return false;
1943 return true;
1946 std::string IndexDataKey::Encode(int64 database_id,
1947 int64 object_store_id,
1948 int64 index_id,
1949 const std::string& encoded_user_key,
1950 const std::string& encoded_primary_key,
1951 int64 sequence_number) {
1952 KeyPrefix prefix(database_id, object_store_id, index_id);
1953 std::string ret = prefix.Encode();
1954 ret.append(encoded_user_key);
1955 EncodeVarInt(sequence_number, &ret);
1956 ret.append(encoded_primary_key);
1957 return ret;
1960 std::string IndexDataKey::Encode(int64 database_id,
1961 int64 object_store_id,
1962 int64 index_id,
1963 const IndexedDBKey& user_key) {
1964 std::string encoded_key;
1965 EncodeIDBKey(user_key, &encoded_key);
1966 return Encode(
1967 database_id, object_store_id, index_id, encoded_key, MinIDBKey(), 0);
1970 std::string IndexDataKey::Encode(int64 database_id,
1971 int64 object_store_id,
1972 int64 index_id,
1973 const IndexedDBKey& user_key,
1974 const IndexedDBKey& user_primary_key) {
1975 std::string encoded_key;
1976 EncodeIDBKey(user_key, &encoded_key);
1977 std::string encoded_primary_key;
1978 EncodeIDBKey(user_primary_key, &encoded_primary_key);
1979 return Encode(database_id,
1980 object_store_id,
1981 index_id,
1982 encoded_key,
1983 encoded_primary_key,
1987 std::string IndexDataKey::EncodeMinKey(int64 database_id,
1988 int64 object_store_id,
1989 int64 index_id) {
1990 return Encode(
1991 database_id, object_store_id, index_id, MinIDBKey(), MinIDBKey(), 0);
1994 std::string IndexDataKey::EncodeMaxKey(int64 database_id,
1995 int64 object_store_id,
1996 int64 index_id) {
1997 return Encode(database_id,
1998 object_store_id,
1999 index_id,
2000 MaxIDBKey(),
2001 MaxIDBKey(),
2002 std::numeric_limits<int64>::max());
2005 int64 IndexDataKey::DatabaseId() const {
2006 DCHECK_GE(database_id_, 0);
2007 return database_id_;
2010 int64 IndexDataKey::ObjectStoreId() const {
2011 DCHECK_GE(object_store_id_, 0);
2012 return object_store_id_;
2015 int64 IndexDataKey::IndexId() const {
2016 DCHECK_GE(index_id_, 0);
2017 return index_id_;
2020 scoped_ptr<IndexedDBKey> IndexDataKey::user_key() const {
2021 scoped_ptr<IndexedDBKey> key;
2022 StringPiece slice(encoded_user_key_);
2023 if (!DecodeIDBKey(&slice, &key)) {
2024 // TODO(jsbell): Return error.
2026 return key.Pass();
2029 scoped_ptr<IndexedDBKey> IndexDataKey::primary_key() const {
2030 scoped_ptr<IndexedDBKey> key;
2031 StringPiece slice(encoded_primary_key_);
2032 if (!DecodeIDBKey(&slice, &key)) {
2033 // TODO(jsbell): Return error.
2035 return key.Pass();
2038 } // namespace content