Roll DEPS for PDFium to 19ae17578f99621100a26dac3e2c7c3dbf7c7cd1
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_leveldb_coding.cc
blob45656a860381510f7277bbfabb0fd687ab9cc4c8
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:
50 // {database_id (var int), blobKey (var int)}*.
51 // If the blobKey is kAllBlobsKey, the whole database should be deleted.
52 // [BlobJournalKey]
53 // <0, 0, 0, 4> => Live blob journal; same format. [LiveBlobJournalKey]
54 // <0, 0, 0, 100, database id>
55 // => Existence implies the database id is in the free list
56 // [DatabaseFreeListKey]
57 // <0, 0, 0, 201, origin, database name> => Database id (int) [DatabaseNameKey]
60 // Database metadata: [DatabaseMetaDataKey]
61 // ----------------------------------------
62 // The prefix is <database id, 0, 0> followed by a metadata type byte:
64 // <database id, 0, 0, 0> => origin name
65 // <database id, 0, 0, 1> => database name
66 // <database id, 0, 0, 2> => IDB string version data (obsolete)
67 // <database id, 0, 0, 3> => maximum allocated object store id
68 // <database id, 0, 0, 4> => IDB integer version (var int)
69 // <database id, 0, 0, 5> => blob key generator current number
72 // Object store metadata: [ObjectStoreMetaDataKey]
73 // -----------------------------------------------
74 // The prefix is <database id, 0, 0>, followed by a type byte (50), then the
75 // object store id (var int), then a metadata type byte.
77 // <database id, 0, 0, 50, object store id, 0> => object store name
78 // <database id, 0, 0, 50, object store id, 1> => key path
79 // <database id, 0, 0, 50, object store id, 2> => auto increment flag
80 // <database id, 0, 0, 50, object store id, 3> => is evictable
81 // <database id, 0, 0, 50, object store id, 4> => last "version" number
82 // <database id, 0, 0, 50, object store id, 5> => maximum allocated index id
83 // <database id, 0, 0, 50, object store id, 6> => has key path flag (obsolete)
84 // <database id, 0, 0, 50, object store id, 7> => key generator current number
86 // The key path was originally just a string (#1) or null (identified by flag,
87 // #6). To support null, string, or array the coding is now identified by the
88 // leading bytes in #1 - see EncodeIDBKeyPath.
90 // The "version" field is used to weed out stale index data. Whenever new
91 // object store data is inserted, it gets a new "version" number, and new
92 // index data is written with this number. When the index is used for
93 // look-ups, entries are validated against the "exists" entries, and records
94 // with old "version" numbers are deleted when they are encountered in
95 // GetPrimaryKeyViaIndex, IndexCursorImpl::LoadCurrentRow and
96 // IndexKeyCursorImpl::LoadCurrentRow.
99 // Index metadata: [IndexMetaDataKey]
100 // ----------------------------------
101 // The prefix is <database id, 0, 0>, followed by a type byte (100), then the
102 // object store id (var int), then the index id (var int), then a metadata
103 // type byte.
105 // <database id, 0, 0, 100, object store id, index id, 0> => index name
106 // <database id, 0, 0, 100, object store id, index id, 1> => unique flag
107 // <database id, 0, 0, 100, object store id, index id, 2> => key path
108 // <database id, 0, 0, 100, object store id, index id, 3> => multi-entry flag
111 // Other object store and index metadata
112 // -------------------------------------
113 // The prefix is <database id, 0, 0> followed by a type byte. The object
114 // store and index id are variable length integers, the names are variable
115 // length strings.
117 // <database id, 0, 0, 150, object store id>
118 // => existence implies the object store id is in the free list
119 // [ObjectStoreFreeListKey]
120 // <database id, 0, 0, 151, object store id, index id>
121 // => existence implies the index id is in the free list [IndexFreeListKey]
122 // <database id, 0, 0, 200, object store name>
123 // => object store id [ObjectStoreNamesKey]
124 // <database id, 0, 0, 201, object store id, index name>
125 // => index id [IndexNamesKey]
128 // Object store data: [ObjectStoreDataKey]
129 // ---------------------------------------
130 // The prefix is followed by a type byte and the encoded IDB primary key. The
131 // data has a "version" prefix followed by the serialized script value.
133 // <database id, object store id, 1, user key>
134 // => "version", serialized script value
137 // "Exists" entry: [ExistsEntryKey]
138 // --------------------------------
139 // The prefix is followed by a type byte and the encoded IDB primary key.
141 // <database id, object store id, 2, user key> => "version"
144 // Blob entry table: [BlobEntryKey]
145 // --------------------------------
147 // The prefix is followed by a type byte and the encoded IDB primary key.
149 // <database id, object store id, 3, user key> => array of IndexedDBBlobInfo
152 // Index data
153 // ----------
154 // The prefix is followed by a type byte, the encoded IDB index key, a
155 // "sequence" number (obsolete; var int), and the encoded IDB primary key.
157 // <database id, object store id, index id, index key, sequence number,
158 // primary key> => "version", primary key [IndexDataKey]
160 // The sequence number is obsolete; it was used to allow two entries with the
161 // same user (index) key in non-unique indexes prior to the inclusion of the
162 // primary key in the data.
164 // Note: In order to be compatible with LevelDB's Bloom filter each bit of the
165 // encoded key needs to used and "not ignored" by the comparator.
167 using base::StringPiece;
168 using blink::WebIDBKeyType;
169 using blink::WebIDBKeyTypeArray;
170 using blink::WebIDBKeyTypeBinary;
171 using blink::WebIDBKeyTypeDate;
172 using blink::WebIDBKeyTypeInvalid;
173 using blink::WebIDBKeyTypeMin;
174 using blink::WebIDBKeyTypeNull;
175 using blink::WebIDBKeyTypeNumber;
176 using blink::WebIDBKeyTypeString;
177 using blink::WebIDBKeyPathType;
178 using blink::WebIDBKeyPathTypeArray;
179 using blink::WebIDBKeyPathTypeNull;
180 using blink::WebIDBKeyPathTypeString;
182 namespace content {
184 // As most of the IndexedDBKeys and encoded values are short, we
185 // initialize some std::vectors with a default inline buffer size to reduce
186 // the memory re-allocations when the std::vectors are appended.
187 static const size_t kDefaultInlineBufferSize = 32;
189 static const unsigned char kIndexedDBKeyNullTypeByte = 0;
190 static const unsigned char kIndexedDBKeyStringTypeByte = 1;
191 static const unsigned char kIndexedDBKeyDateTypeByte = 2;
192 static const unsigned char kIndexedDBKeyNumberTypeByte = 3;
193 static const unsigned char kIndexedDBKeyArrayTypeByte = 4;
194 static const unsigned char kIndexedDBKeyMinKeyTypeByte = 5;
195 static const unsigned char kIndexedDBKeyBinaryTypeByte = 6;
197 static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0;
198 static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0;
200 static const unsigned char kObjectStoreDataIndexId = 1;
201 static const unsigned char kExistsEntryIndexId = 2;
202 static const unsigned char kBlobEntryIndexId = 3;
204 static const unsigned char kSchemaVersionTypeByte = 0;
205 static const unsigned char kMaxDatabaseIdTypeByte = 1;
206 static const unsigned char kDataVersionTypeByte = 2;
207 static const unsigned char kBlobJournalTypeByte = 3;
208 static const unsigned char kLiveBlobJournalTypeByte = 4;
209 static const unsigned char kMaxSimpleGlobalMetaDataTypeByte =
210 5; // Insert before this and increment.
211 static const unsigned char kDatabaseFreeListTypeByte = 100;
212 static const unsigned char kDatabaseNameTypeByte = 201;
214 static const unsigned char kObjectStoreMetaDataTypeByte = 50;
215 static const unsigned char kIndexMetaDataTypeByte = 100;
216 static const unsigned char kObjectStoreFreeListTypeByte = 150;
217 static const unsigned char kIndexFreeListTypeByte = 151;
218 static const unsigned char kObjectStoreNamesTypeByte = 200;
219 static const unsigned char kIndexNamesKeyTypeByte = 201;
221 static const unsigned char kObjectMetaDataTypeMaximum = 255;
222 static const unsigned char kIndexMetaDataTypeMaximum = 255;
224 const unsigned char kMinimumIndexId = 30;
226 inline void EncodeIntSafely(int64 value, int64 max, std::string* into) {
227 DCHECK_LE(value, max);
228 return EncodeInt(value, into);
231 std::string MaxIDBKey() {
232 std::string ret;
233 EncodeByte(kIndexedDBKeyNullTypeByte, &ret);
234 return ret;
237 std::string MinIDBKey() {
238 std::string ret;
239 EncodeByte(kIndexedDBKeyMinKeyTypeByte, &ret);
240 return ret;
243 void EncodeByte(unsigned char value, std::string* into) {
244 into->push_back(value);
247 void EncodeBool(bool value, std::string* into) {
248 into->push_back(value ? 1 : 0);
251 void EncodeInt(int64 value, std::string* into) {
252 #ifndef NDEBUG
253 // Exercised by unit tests in debug only.
254 DCHECK_GE(value, 0);
255 #endif
256 uint64 n = static_cast<uint64>(value);
258 do {
259 unsigned char c = n;
260 into->push_back(c);
261 n >>= 8;
262 } while (n);
265 void EncodeVarInt(int64 value, std::string* into) {
266 #ifndef NDEBUG
267 // Exercised by unit tests in debug only.
268 DCHECK_GE(value, 0);
269 #endif
270 uint64 n = static_cast<uint64>(value);
272 do {
273 unsigned char c = n & 0x7f;
274 n >>= 7;
275 if (n)
276 c |= 0x80;
277 into->push_back(c);
278 } while (n);
281 void EncodeString(const base::string16& value, std::string* into) {
282 if (value.empty())
283 return;
284 // Backing store is UTF-16BE, convert from host endianness.
285 size_t length = value.length();
286 size_t current = into->size();
287 into->resize(into->size() + length * sizeof(base::char16));
289 const base::char16* src = value.c_str();
290 base::char16* dst =
291 reinterpret_cast<base::char16*>(&*into->begin() + current);
292 for (unsigned i = 0; i < length; ++i)
293 *dst++ = htons(*src++);
296 void EncodeBinary(const std::string& value, std::string* into) {
297 EncodeVarInt(value.length(), into);
298 into->append(value.begin(), value.end());
299 DCHECK(into->size() >= value.size());
302 void EncodeStringWithLength(const base::string16& value, std::string* into) {
303 EncodeVarInt(value.length(), into);
304 EncodeString(value, into);
307 void EncodeDouble(double value, std::string* into) {
308 // This always has host endianness.
309 const char* p = reinterpret_cast<char*>(&value);
310 into->insert(into->end(), p, p + sizeof(value));
313 void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
314 size_t previous_size = into->size();
315 DCHECK(value.IsValid());
316 switch (value.type()) {
317 case WebIDBKeyTypeArray: {
318 EncodeByte(kIndexedDBKeyArrayTypeByte, into);
319 size_t length = value.array().size();
320 EncodeVarInt(length, into);
321 for (size_t i = 0; i < length; ++i)
322 EncodeIDBKey(value.array()[i], into);
323 DCHECK_GT(into->size(), previous_size);
324 return;
326 case WebIDBKeyTypeBinary:
327 EncodeByte(kIndexedDBKeyBinaryTypeByte, into);
328 EncodeBinary(value.binary(), into);
329 DCHECK_GT(into->size(), previous_size);
330 return;
331 case WebIDBKeyTypeString:
332 EncodeByte(kIndexedDBKeyStringTypeByte, into);
333 EncodeStringWithLength(value.string(), into);
334 DCHECK_GT(into->size(), previous_size);
335 return;
336 case WebIDBKeyTypeDate:
337 EncodeByte(kIndexedDBKeyDateTypeByte, into);
338 EncodeDouble(value.date(), into);
339 DCHECK_EQ(9u, static_cast<size_t>(into->size() - previous_size));
340 return;
341 case WebIDBKeyTypeNumber:
342 EncodeByte(kIndexedDBKeyNumberTypeByte, into);
343 EncodeDouble(value.number(), into);
344 DCHECK_EQ(9u, static_cast<size_t>(into->size() - previous_size));
345 return;
346 case WebIDBKeyTypeNull:
347 case WebIDBKeyTypeInvalid:
348 case WebIDBKeyTypeMin:
349 default:
350 NOTREACHED();
351 EncodeByte(kIndexedDBKeyNullTypeByte, into);
352 return;
356 void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) {
357 // May be typed, or may be a raw string. An invalid leading
358 // byte is used to identify typed coding. New records are
359 // always written as typed.
360 EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into);
361 EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into);
362 EncodeByte(static_cast<char>(value.type()), into);
363 switch (value.type()) {
364 case WebIDBKeyPathTypeNull:
365 break;
366 case WebIDBKeyPathTypeString: {
367 EncodeStringWithLength(value.string(), into);
368 break;
370 case WebIDBKeyPathTypeArray: {
371 const std::vector<base::string16>& array = value.array();
372 size_t count = array.size();
373 EncodeVarInt(count, into);
374 for (size_t i = 0; i < count; ++i) {
375 EncodeStringWithLength(array[i], into);
377 break;
382 void EncodeBlobJournal(const BlobJournalType& journal, std::string* into) {
383 for (const auto& iter : journal) {
384 EncodeVarInt(iter.first, into);
385 EncodeVarInt(iter.second, into);
389 bool DecodeByte(StringPiece* slice, unsigned char* value) {
390 if (slice->empty())
391 return false;
393 *value = (*slice)[0];
394 slice->remove_prefix(1);
395 return true;
398 bool DecodeBool(StringPiece* slice, bool* value) {
399 if (slice->empty())
400 return false;
402 *value = !!(*slice)[0];
403 slice->remove_prefix(1);
404 return true;
407 bool DecodeInt(StringPiece* slice, int64* value) {
408 if (slice->empty())
409 return false;
411 StringPiece::const_iterator it = slice->begin();
412 int shift = 0;
413 int64 ret = 0;
414 while (it != slice->end()) {
415 unsigned char c = *it++;
416 ret |= static_cast<int64>(c) << shift;
417 shift += 8;
419 *value = ret;
420 slice->remove_prefix(it - slice->begin());
421 return true;
424 bool DecodeVarInt(StringPiece* slice, int64* value) {
425 if (slice->empty())
426 return false;
428 StringPiece::const_iterator it = slice->begin();
429 int shift = 0;
430 int64 ret = 0;
431 do {
432 if (it == slice->end())
433 return false;
435 unsigned char c = *it;
436 ret |= static_cast<int64>(c & 0x7f) << shift;
437 shift += 7;
438 } while (*it++ & 0x80);
439 *value = ret;
440 slice->remove_prefix(it - slice->begin());
441 return true;
444 bool DecodeString(StringPiece* slice, base::string16* value) {
445 if (slice->empty()) {
446 value->clear();
447 return true;
450 // Backing store is UTF-16BE, convert to host endianness.
451 DCHECK(!(slice->size() % sizeof(base::char16)));
452 size_t length = slice->size() / sizeof(base::char16);
453 base::string16 decoded;
454 decoded.reserve(length);
455 const base::char16* encoded =
456 reinterpret_cast<const base::char16*>(slice->begin());
457 for (unsigned i = 0; i < length; ++i)
458 decoded.push_back(ntohs(*encoded++));
460 *value = decoded;
461 slice->remove_prefix(length * sizeof(base::char16));
462 return true;
465 bool DecodeStringWithLength(StringPiece* slice, base::string16* value) {
466 if (slice->empty())
467 return false;
469 int64 length = 0;
470 if (!DecodeVarInt(slice, &length) || length < 0)
471 return false;
472 size_t bytes = length * sizeof(base::char16);
473 if (slice->size() < bytes)
474 return false;
476 StringPiece subpiece(slice->begin(), bytes);
477 slice->remove_prefix(bytes);
478 if (!DecodeString(&subpiece, value))
479 return false;
481 return true;
484 bool DecodeBinary(StringPiece* slice, std::string* value) {
485 if (slice->empty())
486 return false;
488 int64 length = 0;
489 if (!DecodeVarInt(slice, &length) || length < 0)
490 return false;
491 size_t size = length;
492 if (slice->size() < size)
493 return false;
495 value->assign(slice->begin(), size);
496 slice->remove_prefix(size);
497 return true;
500 bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) {
501 if (slice->empty())
502 return false;
504 unsigned char type = (*slice)[0];
505 slice->remove_prefix(1);
507 switch (type) {
508 case kIndexedDBKeyNullTypeByte:
509 *value = make_scoped_ptr(new IndexedDBKey());
510 return true;
512 case kIndexedDBKeyArrayTypeByte: {
513 int64 length = 0;
514 if (!DecodeVarInt(slice, &length) || length < 0)
515 return false;
516 IndexedDBKey::KeyArray array;
517 while (length--) {
518 scoped_ptr<IndexedDBKey> key;
519 if (!DecodeIDBKey(slice, &key))
520 return false;
521 array.push_back(*key);
523 *value = make_scoped_ptr(new IndexedDBKey(array));
524 return true;
526 case kIndexedDBKeyBinaryTypeByte: {
527 std::string binary;
528 if (!DecodeBinary(slice, &binary))
529 return false;
530 *value = make_scoped_ptr(new IndexedDBKey(binary));
531 return true;
533 case kIndexedDBKeyStringTypeByte: {
534 base::string16 s;
535 if (!DecodeStringWithLength(slice, &s))
536 return false;
537 *value = make_scoped_ptr(new IndexedDBKey(s));
538 return true;
540 case kIndexedDBKeyDateTypeByte: {
541 double d;
542 if (!DecodeDouble(slice, &d))
543 return false;
544 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKeyTypeDate));
545 return true;
547 case kIndexedDBKeyNumberTypeByte: {
548 double d;
549 if (!DecodeDouble(slice, &d))
550 return false;
551 *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKeyTypeNumber));
552 return true;
556 NOTREACHED();
557 return false;
560 bool DecodeDouble(StringPiece* slice, double* value) {
561 if (slice->size() < sizeof(*value))
562 return false;
564 memcpy(value, slice->begin(), sizeof(*value));
565 slice->remove_prefix(sizeof(*value));
566 return true;
569 bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) {
570 // May be typed, or may be a raw string. An invalid leading
571 // byte sequence is used to identify typed coding. New records are
572 // always written as typed.
573 if (slice->size() < 3 || (*slice)[0] != kIndexedDBKeyPathTypeCodedByte1 ||
574 (*slice)[1] != kIndexedDBKeyPathTypeCodedByte2) {
575 base::string16 s;
576 if (!DecodeString(slice, &s))
577 return false;
578 *value = IndexedDBKeyPath(s);
579 return true;
582 slice->remove_prefix(2);
583 DCHECK(!slice->empty());
584 WebIDBKeyPathType type = static_cast<WebIDBKeyPathType>((*slice)[0]);
585 slice->remove_prefix(1);
587 switch (type) {
588 case WebIDBKeyPathTypeNull:
589 DCHECK(slice->empty());
590 *value = IndexedDBKeyPath();
591 return true;
592 case WebIDBKeyPathTypeString: {
593 base::string16 string;
594 if (!DecodeStringWithLength(slice, &string))
595 return false;
596 DCHECK(slice->empty());
597 *value = IndexedDBKeyPath(string);
598 return true;
600 case WebIDBKeyPathTypeArray: {
601 std::vector<base::string16> array;
602 int64 count;
603 if (!DecodeVarInt(slice, &count))
604 return false;
605 DCHECK_GE(count, 0);
606 while (count--) {
607 base::string16 string;
608 if (!DecodeStringWithLength(slice, &string))
609 return false;
610 array.push_back(string);
612 DCHECK(slice->empty());
613 *value = IndexedDBKeyPath(array);
614 return true;
617 NOTREACHED();
618 return false;
621 bool DecodeBlobJournal(StringPiece* slice, BlobJournalType* journal) {
622 BlobJournalType output;
623 while (!slice->empty()) {
624 int64 database_id = -1;
625 int64 blob_key = -1;
626 if (!DecodeVarInt(slice, &database_id))
627 return false;
628 if (!KeyPrefix::IsValidDatabaseId(database_id))
629 return false;
630 if (!DecodeVarInt(slice, &blob_key))
631 return false;
632 if (!DatabaseMetaDataKey::IsValidBlobKey(blob_key) &&
633 (blob_key != DatabaseMetaDataKey::kAllBlobsKey)) {
634 return false;
636 output.push_back(std::make_pair(database_id, blob_key));
638 journal->swap(output);
639 return true;
642 bool ConsumeEncodedIDBKey(StringPiece* slice) {
643 unsigned char type = (*slice)[0];
644 slice->remove_prefix(1);
646 switch (type) {
647 case kIndexedDBKeyNullTypeByte:
648 case kIndexedDBKeyMinKeyTypeByte:
649 return true;
650 case kIndexedDBKeyArrayTypeByte: {
651 int64 length;
652 if (!DecodeVarInt(slice, &length))
653 return false;
654 while (length--) {
655 if (!ConsumeEncodedIDBKey(slice))
656 return false;
658 return true;
660 case kIndexedDBKeyBinaryTypeByte: {
661 int64 length = 0;
662 if (!DecodeVarInt(slice, &length) || length < 0)
663 return false;
664 if (slice->size() < static_cast<size_t>(length))
665 return false;
666 slice->remove_prefix(length);
667 return true;
669 case kIndexedDBKeyStringTypeByte: {
670 int64 length = 0;
671 if (!DecodeVarInt(slice, &length) || length < 0)
672 return false;
673 if (slice->size() < static_cast<size_t>(length) * sizeof(base::char16))
674 return false;
675 slice->remove_prefix(length * sizeof(base::char16));
676 return true;
678 case kIndexedDBKeyDateTypeByte:
679 case kIndexedDBKeyNumberTypeByte:
680 if (slice->size() < sizeof(double))
681 return false;
682 slice->remove_prefix(sizeof(double));
683 return true;
685 NOTREACHED();
686 return false;
689 bool ExtractEncodedIDBKey(StringPiece* slice, std::string* result) {
690 const char* start = slice->begin();
691 if (!ConsumeEncodedIDBKey(slice))
692 return false;
694 if (result)
695 result->assign(start, slice->begin());
696 return true;
699 static WebIDBKeyType KeyTypeByteToKeyType(unsigned char type) {
700 switch (type) {
701 case kIndexedDBKeyNullTypeByte:
702 return WebIDBKeyTypeInvalid;
703 case kIndexedDBKeyArrayTypeByte:
704 return WebIDBKeyTypeArray;
705 case kIndexedDBKeyBinaryTypeByte:
706 return WebIDBKeyTypeBinary;
707 case kIndexedDBKeyStringTypeByte:
708 return WebIDBKeyTypeString;
709 case kIndexedDBKeyDateTypeByte:
710 return WebIDBKeyTypeDate;
711 case kIndexedDBKeyNumberTypeByte:
712 return WebIDBKeyTypeNumber;
713 case kIndexedDBKeyMinKeyTypeByte:
714 return WebIDBKeyTypeMin;
717 NOTREACHED();
718 return WebIDBKeyTypeInvalid;
721 int CompareEncodedStringsWithLength(StringPiece* slice1,
722 StringPiece* slice2,
723 bool* ok) {
724 int64 len1, len2;
725 if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
726 *ok = false;
727 return 0;
729 DCHECK_GE(len1, 0);
730 DCHECK_GE(len2, 0);
731 if (len1 < 0 || len2 < 0) {
732 *ok = false;
733 return 0;
735 DCHECK_GE(slice1->size(), len1 * sizeof(base::char16));
736 DCHECK_GE(slice2->size(), len2 * sizeof(base::char16));
737 if (slice1->size() < len1 * sizeof(base::char16) ||
738 slice2->size() < len2 * sizeof(base::char16)) {
739 *ok = false;
740 return 0;
743 // Extract the string data, and advance the passed slices.
744 StringPiece string1(slice1->begin(), len1 * sizeof(base::char16));
745 StringPiece string2(slice2->begin(), len2 * sizeof(base::char16));
746 slice1->remove_prefix(len1 * sizeof(base::char16));
747 slice2->remove_prefix(len2 * sizeof(base::char16));
749 *ok = true;
750 // Strings are UTF-16BE encoded, so a simple memcmp is sufficient.
751 return string1.compare(string2);
754 int CompareEncodedBinary(StringPiece* slice1,
755 StringPiece* slice2,
756 bool* ok) {
757 int64 len1, len2;
758 if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
759 *ok = false;
760 return 0;
762 DCHECK_GE(len1, 0);
763 DCHECK_GE(len2, 0);
764 if (len1 < 0 || len2 < 0) {
765 *ok = false;
766 return 0;
768 size_t size1 = len1;
769 size_t size2 = len2;
771 DCHECK_GE(slice1->size(), size1);
772 DCHECK_GE(slice2->size(), size2);
773 if (slice1->size() < size1 || slice2->size() < size2) {
774 *ok = false;
775 return 0;
778 // Extract the binary data, and advance the passed slices.
779 StringPiece binary1(slice1->begin(), size1);
780 StringPiece binary2(slice2->begin(), size2);
781 slice1->remove_prefix(size1);
782 slice2->remove_prefix(size2);
784 *ok = true;
785 // This is the same as a memcmp()
786 return binary1.compare(binary2);
789 static int CompareInts(int64 a, int64 b) {
790 #ifndef NDEBUG
791 // Exercised by unit tests in debug only.
792 DCHECK_GE(a, 0);
793 DCHECK_GE(b, 0);
794 #endif
795 int64 diff = a - b;
796 if (diff < 0)
797 return -1;
798 if (diff > 0)
799 return 1;
800 return 0;
803 static inline int CompareSizes(size_t a, size_t b) {
804 if (a > b)
805 return 1;
806 if (b > a)
807 return -1;
808 return 0;
811 static int CompareTypes(WebIDBKeyType a, WebIDBKeyType b) { return b - a; }
813 int CompareEncodedIDBKeys(StringPiece* slice_a,
814 StringPiece* slice_b,
815 bool* ok) {
816 DCHECK(!slice_a->empty());
817 DCHECK(!slice_b->empty());
818 *ok = true;
819 unsigned char type_a = (*slice_a)[0];
820 unsigned char type_b = (*slice_b)[0];
821 slice_a->remove_prefix(1);
822 slice_b->remove_prefix(1);
824 if (int x = CompareTypes(KeyTypeByteToKeyType(type_a),
825 KeyTypeByteToKeyType(type_b)))
826 return x;
828 switch (type_a) {
829 case kIndexedDBKeyNullTypeByte:
830 case kIndexedDBKeyMinKeyTypeByte:
831 // Null type or max type; no payload to compare.
832 return 0;
833 case kIndexedDBKeyArrayTypeByte: {
834 int64 length_a, length_b;
835 if (!DecodeVarInt(slice_a, &length_a) ||
836 !DecodeVarInt(slice_b, &length_b)) {
837 *ok = false;
838 return 0;
840 for (int64 i = 0; i < length_a && i < length_b; ++i) {
841 int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
842 if (!*ok || result)
843 return result;
845 return length_a - length_b;
847 case kIndexedDBKeyBinaryTypeByte:
848 return CompareEncodedBinary(slice_a, slice_b, ok);
849 case kIndexedDBKeyStringTypeByte:
850 return CompareEncodedStringsWithLength(slice_a, slice_b, ok);
851 case kIndexedDBKeyDateTypeByte:
852 case kIndexedDBKeyNumberTypeByte: {
853 double d, e;
854 if (!DecodeDouble(slice_a, &d) || !DecodeDouble(slice_b, &e)) {
855 *ok = false;
856 return 0;
858 if (d < e)
859 return -1;
860 if (d > e)
861 return 1;
862 return 0;
866 NOTREACHED();
867 return 0;
870 namespace {
872 template <typename KeyType>
873 int Compare(const StringPiece& a,
874 const StringPiece& b,
875 bool only_compare_index_keys,
876 bool* ok) {
877 KeyType key_a;
878 KeyType key_b;
880 StringPiece slice_a(a);
881 if (!KeyType::Decode(&slice_a, &key_a)) {
882 *ok = false;
883 return 0;
885 StringPiece slice_b(b);
886 if (!KeyType::Decode(&slice_b, &key_b)) {
887 *ok = false;
888 return 0;
891 *ok = true;
892 return key_a.Compare(key_b);
895 template <typename KeyType>
896 int CompareSuffix(StringPiece* a,
897 StringPiece* b,
898 bool only_compare_index_keys,
899 bool* ok) {
900 NOTREACHED();
901 return 0;
904 template <>
905 int CompareSuffix<ExistsEntryKey>(StringPiece* slice_a,
906 StringPiece* slice_b,
907 bool only_compare_index_keys,
908 bool* ok) {
909 DCHECK(!slice_a->empty());
910 DCHECK(!slice_b->empty());
911 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
914 template <>
915 int CompareSuffix<ObjectStoreDataKey>(StringPiece* slice_a,
916 StringPiece* slice_b,
917 bool only_compare_index_keys,
918 bool* ok) {
919 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
922 template <>
923 int CompareSuffix<BlobEntryKey>(StringPiece* slice_a,
924 StringPiece* slice_b,
925 bool only_compare_index_keys,
926 bool* ok) {
927 return CompareEncodedIDBKeys(slice_a, slice_b, ok);
930 template <>
931 int CompareSuffix<IndexDataKey>(StringPiece* slice_a,
932 StringPiece* slice_b,
933 bool only_compare_index_keys,
934 bool* ok) {
935 // index key
936 int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
937 if (!*ok || result)
938 return result;
939 if (only_compare_index_keys)
940 return 0;
942 // sequence number [optional]
943 int64 sequence_number_a = -1;
944 int64 sequence_number_b = -1;
945 if (!slice_a->empty() && !DecodeVarInt(slice_a, &sequence_number_a))
946 return 0;
947 if (!slice_b->empty() && !DecodeVarInt(slice_b, &sequence_number_b))
948 return 0;
950 if (slice_a->empty() || slice_b->empty())
951 return CompareSizes(slice_a->size(), slice_b->size());
953 // primary key [optional]
954 result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
955 if (!*ok || result)
956 return result;
958 return CompareInts(sequence_number_a, sequence_number_b);
961 int Compare(const StringPiece& a,
962 const StringPiece& b,
963 bool only_compare_index_keys,
964 bool* ok) {
965 StringPiece slice_a(a);
966 StringPiece slice_b(b);
967 KeyPrefix prefix_a;
968 KeyPrefix prefix_b;
969 bool ok_a = KeyPrefix::Decode(&slice_a, &prefix_a);
970 bool ok_b = KeyPrefix::Decode(&slice_b, &prefix_b);
971 DCHECK(ok_a);
972 DCHECK(ok_b);
973 if (!ok_a || !ok_b) {
974 *ok = false;
975 return 0;
978 *ok = true;
979 if (int x = prefix_a.Compare(prefix_b))
980 return x;
982 switch (prefix_a.type()) {
983 case KeyPrefix::GLOBAL_METADATA: {
984 DCHECK(!slice_a.empty());
985 DCHECK(!slice_b.empty());
987 unsigned char type_byte_a;
988 if (!DecodeByte(&slice_a, &type_byte_a)) {
989 *ok = false;
990 return 0;
993 unsigned char type_byte_b;
994 if (!DecodeByte(&slice_b, &type_byte_b)) {
995 *ok = false;
996 return 0;
999 if (int x = type_byte_a - type_byte_b)
1000 return x;
1001 if (type_byte_a < kMaxSimpleGlobalMetaDataTypeByte)
1002 return 0;
1004 // Compare<> is used (which re-decodes the prefix) rather than an
1005 // specialized CompareSuffix<> because metadata is relatively uncommon
1006 // in the database.
1008 if (type_byte_a == kDatabaseFreeListTypeByte) {
1009 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1010 return Compare<DatabaseFreeListKey>(a, b, only_compare_index_keys, ok);
1012 if (type_byte_a == kDatabaseNameTypeByte) {
1013 return Compare<DatabaseNameKey>(
1014 a, b, /*only_compare_index_keys*/ false, ok);
1016 break;
1019 case KeyPrefix::DATABASE_METADATA: {
1020 DCHECK(!slice_a.empty());
1021 DCHECK(!slice_b.empty());
1023 unsigned char type_byte_a;
1024 if (!DecodeByte(&slice_a, &type_byte_a)) {
1025 *ok = false;
1026 return 0;
1029 unsigned char type_byte_b;
1030 if (!DecodeByte(&slice_b, &type_byte_b)) {
1031 *ok = false;
1032 return 0;
1035 if (int x = type_byte_a - type_byte_b)
1036 return x;
1037 if (type_byte_a < DatabaseMetaDataKey::MAX_SIMPLE_METADATA_TYPE)
1038 return 0;
1040 // Compare<> is used (which re-decodes the prefix) rather than an
1041 // specialized CompareSuffix<> because metadata is relatively uncommon
1042 // in the database.
1044 if (type_byte_a == kObjectStoreMetaDataTypeByte) {
1045 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1046 return Compare<ObjectStoreMetaDataKey>(
1047 a, b, only_compare_index_keys, ok);
1049 if (type_byte_a == kIndexMetaDataTypeByte) {
1050 return Compare<IndexMetaDataKey>(
1051 a, b, /*only_compare_index_keys*/ false, ok);
1053 if (type_byte_a == kObjectStoreFreeListTypeByte) {
1054 return Compare<ObjectStoreFreeListKey>(
1055 a, b, only_compare_index_keys, ok);
1057 if (type_byte_a == kIndexFreeListTypeByte) {
1058 return Compare<IndexFreeListKey>(
1059 a, b, /*only_compare_index_keys*/ false, ok);
1061 if (type_byte_a == kObjectStoreNamesTypeByte) {
1062 // TODO(jsbell): No need to pass only_compare_index_keys through here.
1063 return Compare<ObjectStoreNamesKey>(
1064 a, b, only_compare_index_keys, ok);
1066 if (type_byte_a == kIndexNamesKeyTypeByte) {
1067 return Compare<IndexNamesKey>(
1068 a, b, /*only_compare_index_keys*/ false, ok);
1070 break;
1073 case KeyPrefix::OBJECT_STORE_DATA: {
1074 // Provide a stable ordering for invalid data.
1075 if (slice_a.empty() || slice_b.empty())
1076 return CompareSizes(slice_a.size(), slice_b.size());
1078 return CompareSuffix<ObjectStoreDataKey>(
1079 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1082 case KeyPrefix::EXISTS_ENTRY: {
1083 // Provide a stable ordering for invalid data.
1084 if (slice_a.empty() || slice_b.empty())
1085 return CompareSizes(slice_a.size(), slice_b.size());
1087 return CompareSuffix<ExistsEntryKey>(
1088 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1091 case KeyPrefix::BLOB_ENTRY: {
1092 // Provide a stable ordering for invalid data.
1093 if (slice_a.empty() || slice_b.empty())
1094 return CompareSizes(slice_a.size(), slice_b.size());
1096 return CompareSuffix<BlobEntryKey>(
1097 &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok);
1100 case KeyPrefix::INDEX_DATA: {
1101 // Provide a stable ordering for invalid data.
1102 if (slice_a.empty() || slice_b.empty())
1103 return CompareSizes(slice_a.size(), slice_b.size());
1105 return CompareSuffix<IndexDataKey>(
1106 &slice_a, &slice_b, only_compare_index_keys, ok);
1109 case KeyPrefix::INVALID_TYPE:
1110 break;
1113 NOTREACHED();
1114 *ok = false;
1115 return 0;
1118 } // namespace
1120 int Compare(const StringPiece& a,
1121 const StringPiece& b,
1122 bool only_compare_index_keys) {
1123 bool ok;
1124 int result = Compare(a, b, only_compare_index_keys, &ok);
1125 DCHECK(ok);
1126 if (!ok)
1127 return 0;
1128 return result;
1131 KeyPrefix::KeyPrefix()
1132 : database_id_(INVALID_TYPE),
1133 object_store_id_(INVALID_TYPE),
1134 index_id_(INVALID_TYPE) {}
1136 KeyPrefix::KeyPrefix(int64 database_id)
1137 : database_id_(database_id), object_store_id_(0), index_id_(0) {
1138 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1141 KeyPrefix::KeyPrefix(int64 database_id, int64 object_store_id)
1142 : database_id_(database_id),
1143 object_store_id_(object_store_id),
1144 index_id_(0) {
1145 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1146 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1149 KeyPrefix::KeyPrefix(int64 database_id, int64 object_store_id, int64 index_id)
1150 : database_id_(database_id),
1151 object_store_id_(object_store_id),
1152 index_id_(index_id) {
1153 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1154 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1155 DCHECK(KeyPrefix::IsValidIndexId(index_id));
1158 KeyPrefix::KeyPrefix(enum Type type,
1159 int64 database_id,
1160 int64 object_store_id,
1161 int64 index_id)
1162 : database_id_(database_id),
1163 object_store_id_(object_store_id),
1164 index_id_(index_id) {
1165 DCHECK_EQ(type, INVALID_TYPE);
1166 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1167 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1170 KeyPrefix KeyPrefix::CreateWithSpecialIndex(int64 database_id,
1171 int64 object_store_id,
1172 int64 index_id) {
1173 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
1174 DCHECK(KeyPrefix::IsValidObjectStoreId(object_store_id));
1175 DCHECK(index_id);
1176 return KeyPrefix(INVALID_TYPE, database_id, object_store_id, index_id);
1179 bool KeyPrefix::IsValidDatabaseId(int64 database_id) {
1180 return (database_id > 0) && (database_id < KeyPrefix::kMaxDatabaseId);
1183 bool KeyPrefix::IsValidObjectStoreId(int64 object_store_id) {
1184 return (object_store_id > 0) &&
1185 (object_store_id < KeyPrefix::kMaxObjectStoreId);
1188 bool KeyPrefix::IsValidIndexId(int64 index_id) {
1189 return (index_id >= kMinimumIndexId) && (index_id < KeyPrefix::kMaxIndexId);
1192 bool KeyPrefix::Decode(StringPiece* slice, KeyPrefix* result) {
1193 unsigned char first_byte;
1194 if (!DecodeByte(slice, &first_byte))
1195 return false;
1197 size_t database_id_bytes = ((first_byte >> 5) & 0x7) + 1;
1198 size_t object_store_id_bytes = ((first_byte >> 2) & 0x7) + 1;
1199 size_t index_id_bytes = (first_byte & 0x3) + 1;
1201 if (database_id_bytes + object_store_id_bytes + index_id_bytes >
1202 slice->size())
1203 return false;
1206 StringPiece tmp(slice->begin(), database_id_bytes);
1207 if (!DecodeInt(&tmp, &result->database_id_))
1208 return false;
1210 slice->remove_prefix(database_id_bytes);
1212 StringPiece tmp(slice->begin(), object_store_id_bytes);
1213 if (!DecodeInt(&tmp, &result->object_store_id_))
1214 return false;
1216 slice->remove_prefix(object_store_id_bytes);
1218 StringPiece tmp(slice->begin(), index_id_bytes);
1219 if (!DecodeInt(&tmp, &result->index_id_))
1220 return false;
1222 slice->remove_prefix(index_id_bytes);
1223 return true;
1226 std::string KeyPrefix::EncodeEmpty() {
1227 const std::string result(4, 0);
1228 DCHECK(EncodeInternal(0, 0, 0) == std::string(4, 0));
1229 return result;
1232 std::string KeyPrefix::Encode() const {
1233 DCHECK(database_id_ != kInvalidId);
1234 DCHECK(object_store_id_ != kInvalidId);
1235 DCHECK(index_id_ != kInvalidId);
1236 return EncodeInternal(database_id_, object_store_id_, index_id_);
1239 std::string KeyPrefix::EncodeInternal(int64 database_id,
1240 int64 object_store_id,
1241 int64 index_id) {
1242 std::string database_id_string;
1243 std::string object_store_id_string;
1244 std::string index_id_string;
1246 EncodeIntSafely(database_id, kMaxDatabaseId, &database_id_string);
1247 EncodeIntSafely(object_store_id, kMaxObjectStoreId, &object_store_id_string);
1248 EncodeIntSafely(index_id, kMaxIndexId, &index_id_string);
1250 DCHECK(database_id_string.size() <= kMaxDatabaseIdSizeBytes);
1251 DCHECK(object_store_id_string.size() <= kMaxObjectStoreIdSizeBytes);
1252 DCHECK(index_id_string.size() <= kMaxIndexIdSizeBytes);
1254 unsigned char first_byte =
1255 (database_id_string.size() - 1) << (kMaxObjectStoreIdSizeBits +
1256 kMaxIndexIdSizeBits) |
1257 (object_store_id_string.size() - 1) << kMaxIndexIdSizeBits |
1258 (index_id_string.size() - 1);
1259 static_assert(kMaxDatabaseIdSizeBits + kMaxObjectStoreIdSizeBits +
1260 kMaxIndexIdSizeBits ==
1261 sizeof(first_byte) * 8,
1262 "cannot encode ids");
1263 std::string ret;
1264 ret.reserve(kDefaultInlineBufferSize);
1265 ret.push_back(first_byte);
1266 ret.append(database_id_string);
1267 ret.append(object_store_id_string);
1268 ret.append(index_id_string);
1270 DCHECK_LE(ret.size(), kDefaultInlineBufferSize);
1271 return ret;
1274 int KeyPrefix::Compare(const KeyPrefix& other) const {
1275 DCHECK(database_id_ != kInvalidId);
1276 DCHECK(object_store_id_ != kInvalidId);
1277 DCHECK(index_id_ != kInvalidId);
1279 if (database_id_ != other.database_id_)
1280 return CompareInts(database_id_, other.database_id_);
1281 if (object_store_id_ != other.object_store_id_)
1282 return CompareInts(object_store_id_, other.object_store_id_);
1283 if (index_id_ != other.index_id_)
1284 return CompareInts(index_id_, other.index_id_);
1285 return 0;
1288 KeyPrefix::Type KeyPrefix::type() const {
1289 DCHECK(database_id_ != kInvalidId);
1290 DCHECK(object_store_id_ != kInvalidId);
1291 DCHECK(index_id_ != kInvalidId);
1293 if (!database_id_)
1294 return GLOBAL_METADATA;
1295 if (!object_store_id_)
1296 return DATABASE_METADATA;
1297 if (index_id_ == kObjectStoreDataIndexId)
1298 return OBJECT_STORE_DATA;
1299 if (index_id_ == kExistsEntryIndexId)
1300 return EXISTS_ENTRY;
1301 if (index_id_ == kBlobEntryIndexId)
1302 return BLOB_ENTRY;
1303 if (index_id_ >= kMinimumIndexId)
1304 return INDEX_DATA;
1306 NOTREACHED();
1307 return INVALID_TYPE;
1310 std::string SchemaVersionKey::Encode() {
1311 std::string ret = KeyPrefix::EncodeEmpty();
1312 ret.push_back(kSchemaVersionTypeByte);
1313 return ret;
1316 std::string MaxDatabaseIdKey::Encode() {
1317 std::string ret = KeyPrefix::EncodeEmpty();
1318 ret.push_back(kMaxDatabaseIdTypeByte);
1319 return ret;
1322 std::string DataVersionKey::Encode() {
1323 std::string ret = KeyPrefix::EncodeEmpty();
1324 ret.push_back(kDataVersionTypeByte);
1325 return ret;
1328 std::string BlobJournalKey::Encode() {
1329 std::string ret = KeyPrefix::EncodeEmpty();
1330 ret.push_back(kBlobJournalTypeByte);
1331 return ret;
1334 std::string LiveBlobJournalKey::Encode() {
1335 std::string ret = KeyPrefix::EncodeEmpty();
1336 ret.push_back(kLiveBlobJournalTypeByte);
1337 return ret;
1340 DatabaseFreeListKey::DatabaseFreeListKey() : database_id_(-1) {}
1342 bool DatabaseFreeListKey::Decode(StringPiece* slice,
1343 DatabaseFreeListKey* result) {
1344 KeyPrefix prefix;
1345 if (!KeyPrefix::Decode(slice, &prefix))
1346 return false;
1347 DCHECK(!prefix.database_id_);
1348 DCHECK(!prefix.object_store_id_);
1349 DCHECK(!prefix.index_id_);
1350 unsigned char type_byte = 0;
1351 if (!DecodeByte(slice, &type_byte))
1352 return false;
1353 DCHECK_EQ(type_byte, kDatabaseFreeListTypeByte);
1354 if (!DecodeVarInt(slice, &result->database_id_))
1355 return false;
1356 return true;
1359 std::string DatabaseFreeListKey::Encode(int64 database_id) {
1360 std::string ret = KeyPrefix::EncodeEmpty();
1361 ret.push_back(kDatabaseFreeListTypeByte);
1362 EncodeVarInt(database_id, &ret);
1363 return ret;
1366 std::string DatabaseFreeListKey::EncodeMaxKey() {
1367 return Encode(std::numeric_limits<int64>::max());
1370 int64 DatabaseFreeListKey::DatabaseId() const {
1371 DCHECK_GE(database_id_, 0);
1372 return database_id_;
1375 int DatabaseFreeListKey::Compare(const DatabaseFreeListKey& other) const {
1376 DCHECK_GE(database_id_, 0);
1377 return CompareInts(database_id_, other.database_id_);
1380 bool DatabaseNameKey::Decode(StringPiece* slice, DatabaseNameKey* result) {
1381 KeyPrefix prefix;
1382 if (!KeyPrefix::Decode(slice, &prefix))
1383 return false;
1384 DCHECK(!prefix.database_id_);
1385 DCHECK(!prefix.object_store_id_);
1386 DCHECK(!prefix.index_id_);
1387 unsigned char type_byte = 0;
1388 if (!DecodeByte(slice, &type_byte))
1389 return false;
1390 DCHECK_EQ(type_byte, kDatabaseNameTypeByte);
1391 if (!DecodeStringWithLength(slice, &result->origin_))
1392 return false;
1393 if (!DecodeStringWithLength(slice, &result->database_name_))
1394 return false;
1395 return true;
1398 std::string DatabaseNameKey::Encode(const std::string& origin_identifier,
1399 const base::string16& database_name) {
1400 std::string ret = KeyPrefix::EncodeEmpty();
1401 ret.push_back(kDatabaseNameTypeByte);
1402 EncodeStringWithLength(base::ASCIIToUTF16(origin_identifier), &ret);
1403 EncodeStringWithLength(database_name, &ret);
1404 return ret;
1407 std::string DatabaseNameKey::EncodeMinKeyForOrigin(
1408 const std::string& origin_identifier) {
1409 return Encode(origin_identifier, base::string16());
1412 std::string DatabaseNameKey::EncodeStopKeyForOrigin(
1413 const std::string& origin_identifier) {
1414 // just after origin in collation order
1415 return EncodeMinKeyForOrigin(origin_identifier + '\x01');
1418 int DatabaseNameKey::Compare(const DatabaseNameKey& other) {
1419 if (int x = origin_.compare(other.origin_))
1420 return x;
1421 return database_name_.compare(other.database_name_);
1424 bool DatabaseMetaDataKey::IsValidBlobKey(int64 blob_key) {
1425 return blob_key >= kBlobKeyGeneratorInitialNumber;
1428 const int64 DatabaseMetaDataKey::kAllBlobsKey = 1;
1429 const int64 DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber = 2;
1430 const int64 DatabaseMetaDataKey::kInvalidBlobKey = -1;
1432 std::string DatabaseMetaDataKey::Encode(int64 database_id,
1433 MetaDataType meta_data_type) {
1434 KeyPrefix prefix(database_id);
1435 std::string ret = prefix.Encode();
1436 ret.push_back(meta_data_type);
1437 return ret;
1440 ObjectStoreMetaDataKey::ObjectStoreMetaDataKey()
1441 : object_store_id_(-1), meta_data_type_(0xFF) {}
1443 bool ObjectStoreMetaDataKey::Decode(StringPiece* slice,
1444 ObjectStoreMetaDataKey* result) {
1445 KeyPrefix prefix;
1446 if (!KeyPrefix::Decode(slice, &prefix))
1447 return false;
1448 DCHECK(prefix.database_id_);
1449 DCHECK(!prefix.object_store_id_);
1450 DCHECK(!prefix.index_id_);
1451 unsigned char type_byte = 0;
1452 if (!DecodeByte(slice, &type_byte))
1453 return false;
1454 DCHECK_EQ(type_byte, kObjectStoreMetaDataTypeByte);
1455 if (!DecodeVarInt(slice, &result->object_store_id_))
1456 return false;
1457 DCHECK(result->object_store_id_);
1458 if (!DecodeByte(slice, &result->meta_data_type_))
1459 return false;
1460 return true;
1463 std::string ObjectStoreMetaDataKey::Encode(int64 database_id,
1464 int64 object_store_id,
1465 unsigned char meta_data_type) {
1466 KeyPrefix prefix(database_id);
1467 std::string ret = prefix.Encode();
1468 ret.push_back(kObjectStoreMetaDataTypeByte);
1469 EncodeVarInt(object_store_id, &ret);
1470 ret.push_back(meta_data_type);
1471 return ret;
1474 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id) {
1475 return Encode(database_id,
1476 std::numeric_limits<int64>::max(),
1477 kObjectMetaDataTypeMaximum);
1480 std::string ObjectStoreMetaDataKey::EncodeMaxKey(int64 database_id,
1481 int64 object_store_id) {
1482 return Encode(database_id, object_store_id, kObjectMetaDataTypeMaximum);
1485 int64 ObjectStoreMetaDataKey::ObjectStoreId() const {
1486 DCHECK_GE(object_store_id_, 0);
1487 return object_store_id_;
1489 unsigned char ObjectStoreMetaDataKey::MetaDataType() const {
1490 return meta_data_type_;
1493 int ObjectStoreMetaDataKey::Compare(const ObjectStoreMetaDataKey& other) {
1494 DCHECK_GE(object_store_id_, 0);
1495 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1496 return x;
1497 return meta_data_type_ - other.meta_data_type_;
1500 IndexMetaDataKey::IndexMetaDataKey()
1501 : object_store_id_(-1), index_id_(-1), meta_data_type_(0) {}
1503 bool IndexMetaDataKey::Decode(StringPiece* slice, IndexMetaDataKey* result) {
1504 KeyPrefix prefix;
1505 if (!KeyPrefix::Decode(slice, &prefix))
1506 return false;
1507 DCHECK(prefix.database_id_);
1508 DCHECK(!prefix.object_store_id_);
1509 DCHECK(!prefix.index_id_);
1510 unsigned char type_byte = 0;
1511 if (!DecodeByte(slice, &type_byte))
1512 return false;
1513 DCHECK_EQ(type_byte, kIndexMetaDataTypeByte);
1514 if (!DecodeVarInt(slice, &result->object_store_id_))
1515 return false;
1516 if (!DecodeVarInt(slice, &result->index_id_))
1517 return false;
1518 if (!DecodeByte(slice, &result->meta_data_type_))
1519 return false;
1520 return true;
1523 std::string IndexMetaDataKey::Encode(int64 database_id,
1524 int64 object_store_id,
1525 int64 index_id,
1526 unsigned char meta_data_type) {
1527 KeyPrefix prefix(database_id);
1528 std::string ret = prefix.Encode();
1529 ret.push_back(kIndexMetaDataTypeByte);
1530 EncodeVarInt(object_store_id, &ret);
1531 EncodeVarInt(index_id, &ret);
1532 EncodeByte(meta_data_type, &ret);
1533 return ret;
1536 std::string IndexMetaDataKey::EncodeMaxKey(int64 database_id,
1537 int64 object_store_id) {
1538 return Encode(database_id,
1539 object_store_id,
1540 std::numeric_limits<int64>::max(),
1541 kIndexMetaDataTypeMaximum);
1544 std::string IndexMetaDataKey::EncodeMaxKey(int64 database_id,
1545 int64 object_store_id,
1546 int64 index_id) {
1547 return Encode(
1548 database_id, object_store_id, index_id, kIndexMetaDataTypeMaximum);
1551 int IndexMetaDataKey::Compare(const IndexMetaDataKey& other) {
1552 DCHECK_GE(object_store_id_, 0);
1553 DCHECK_GE(index_id_, 0);
1555 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1556 return x;
1557 if (int x = CompareInts(index_id_, other.index_id_))
1558 return x;
1559 return meta_data_type_ - other.meta_data_type_;
1562 int64 IndexMetaDataKey::IndexId() const {
1563 DCHECK_GE(index_id_, 0);
1564 return index_id_;
1567 ObjectStoreFreeListKey::ObjectStoreFreeListKey() : object_store_id_(-1) {}
1569 bool ObjectStoreFreeListKey::Decode(StringPiece* slice,
1570 ObjectStoreFreeListKey* result) {
1571 KeyPrefix prefix;
1572 if (!KeyPrefix::Decode(slice, &prefix))
1573 return false;
1574 DCHECK(prefix.database_id_);
1575 DCHECK(!prefix.object_store_id_);
1576 DCHECK(!prefix.index_id_);
1577 unsigned char type_byte = 0;
1578 if (!DecodeByte(slice, &type_byte))
1579 return false;
1580 DCHECK_EQ(type_byte, kObjectStoreFreeListTypeByte);
1581 if (!DecodeVarInt(slice, &result->object_store_id_))
1582 return false;
1583 return true;
1586 std::string ObjectStoreFreeListKey::Encode(int64 database_id,
1587 int64 object_store_id) {
1588 KeyPrefix prefix(database_id);
1589 std::string ret = prefix.Encode();
1590 ret.push_back(kObjectStoreFreeListTypeByte);
1591 EncodeVarInt(object_store_id, &ret);
1592 return ret;
1595 std::string ObjectStoreFreeListKey::EncodeMaxKey(int64 database_id) {
1596 return Encode(database_id, std::numeric_limits<int64>::max());
1599 int64 ObjectStoreFreeListKey::ObjectStoreId() const {
1600 DCHECK_GE(object_store_id_, 0);
1601 return object_store_id_;
1604 int ObjectStoreFreeListKey::Compare(const ObjectStoreFreeListKey& other) {
1605 // TODO(jsbell): It may seem strange that we're not comparing database id's,
1606 // but that comparison will have been made earlier.
1607 // We should probably make this more clear, though...
1608 DCHECK_GE(object_store_id_, 0);
1609 return CompareInts(object_store_id_, other.object_store_id_);
1612 IndexFreeListKey::IndexFreeListKey() : object_store_id_(-1), index_id_(-1) {}
1614 bool IndexFreeListKey::Decode(StringPiece* slice, IndexFreeListKey* result) {
1615 KeyPrefix prefix;
1616 if (!KeyPrefix::Decode(slice, &prefix))
1617 return false;
1618 DCHECK(prefix.database_id_);
1619 DCHECK(!prefix.object_store_id_);
1620 DCHECK(!prefix.index_id_);
1621 unsigned char type_byte = 0;
1622 if (!DecodeByte(slice, &type_byte))
1623 return false;
1624 DCHECK_EQ(type_byte, kIndexFreeListTypeByte);
1625 if (!DecodeVarInt(slice, &result->object_store_id_))
1626 return false;
1627 if (!DecodeVarInt(slice, &result->index_id_))
1628 return false;
1629 return true;
1632 std::string IndexFreeListKey::Encode(int64 database_id,
1633 int64 object_store_id,
1634 int64 index_id) {
1635 KeyPrefix prefix(database_id);
1636 std::string ret = prefix.Encode();
1637 ret.push_back(kIndexFreeListTypeByte);
1638 EncodeVarInt(object_store_id, &ret);
1639 EncodeVarInt(index_id, &ret);
1640 return ret;
1643 std::string IndexFreeListKey::EncodeMaxKey(int64 database_id,
1644 int64 object_store_id) {
1645 return Encode(
1646 database_id, object_store_id, std::numeric_limits<int64>::max());
1649 int IndexFreeListKey::Compare(const IndexFreeListKey& other) {
1650 DCHECK_GE(object_store_id_, 0);
1651 DCHECK_GE(index_id_, 0);
1652 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1653 return x;
1654 return CompareInts(index_id_, other.index_id_);
1657 int64 IndexFreeListKey::ObjectStoreId() const {
1658 DCHECK_GE(object_store_id_, 0);
1659 return object_store_id_;
1662 int64 IndexFreeListKey::IndexId() const {
1663 DCHECK_GE(index_id_, 0);
1664 return index_id_;
1667 // TODO(jsbell): We never use this to look up object store ids,
1668 // because a mapping is kept in the IndexedDBDatabase. Can the
1669 // mapping become unreliable? Can we remove this?
1670 bool ObjectStoreNamesKey::Decode(StringPiece* slice,
1671 ObjectStoreNamesKey* result) {
1672 KeyPrefix prefix;
1673 if (!KeyPrefix::Decode(slice, &prefix))
1674 return false;
1675 DCHECK(prefix.database_id_);
1676 DCHECK(!prefix.object_store_id_);
1677 DCHECK(!prefix.index_id_);
1678 unsigned char type_byte = 0;
1679 if (!DecodeByte(slice, &type_byte))
1680 return false;
1681 DCHECK_EQ(type_byte, kObjectStoreNamesTypeByte);
1682 if (!DecodeStringWithLength(slice, &result->object_store_name_))
1683 return false;
1684 return true;
1687 std::string ObjectStoreNamesKey::Encode(
1688 int64 database_id,
1689 const base::string16& object_store_name) {
1690 KeyPrefix prefix(database_id);
1691 std::string ret = prefix.Encode();
1692 ret.push_back(kObjectStoreNamesTypeByte);
1693 EncodeStringWithLength(object_store_name, &ret);
1694 return ret;
1697 int ObjectStoreNamesKey::Compare(const ObjectStoreNamesKey& other) {
1698 return object_store_name_.compare(other.object_store_name_);
1701 IndexNamesKey::IndexNamesKey() : object_store_id_(-1) {}
1703 // TODO(jsbell): We never use this to look up index ids, because a mapping
1704 // is kept at a higher level.
1705 bool IndexNamesKey::Decode(StringPiece* slice, IndexNamesKey* result) {
1706 KeyPrefix prefix;
1707 if (!KeyPrefix::Decode(slice, &prefix))
1708 return false;
1709 DCHECK(prefix.database_id_);
1710 DCHECK(!prefix.object_store_id_);
1711 DCHECK(!prefix.index_id_);
1712 unsigned char type_byte = 0;
1713 if (!DecodeByte(slice, &type_byte))
1714 return false;
1715 DCHECK_EQ(type_byte, kIndexNamesKeyTypeByte);
1716 if (!DecodeVarInt(slice, &result->object_store_id_))
1717 return false;
1718 if (!DecodeStringWithLength(slice, &result->index_name_))
1719 return false;
1720 return true;
1723 std::string IndexNamesKey::Encode(int64 database_id,
1724 int64 object_store_id,
1725 const base::string16& index_name) {
1726 KeyPrefix prefix(database_id);
1727 std::string ret = prefix.Encode();
1728 ret.push_back(kIndexNamesKeyTypeByte);
1729 EncodeVarInt(object_store_id, &ret);
1730 EncodeStringWithLength(index_name, &ret);
1731 return ret;
1734 int IndexNamesKey::Compare(const IndexNamesKey& other) {
1735 DCHECK_GE(object_store_id_, 0);
1736 if (int x = CompareInts(object_store_id_, other.object_store_id_))
1737 return x;
1738 return index_name_.compare(other.index_name_);
1741 ObjectStoreDataKey::ObjectStoreDataKey() {}
1742 ObjectStoreDataKey::~ObjectStoreDataKey() {}
1744 bool ObjectStoreDataKey::Decode(StringPiece* slice,
1745 ObjectStoreDataKey* result) {
1746 KeyPrefix prefix;
1747 if (!KeyPrefix::Decode(slice, &prefix))
1748 return false;
1749 DCHECK(prefix.database_id_);
1750 DCHECK(prefix.object_store_id_);
1751 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1752 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1753 return false;
1754 return true;
1757 std::string ObjectStoreDataKey::Encode(int64 database_id,
1758 int64 object_store_id,
1759 const std::string encoded_user_key) {
1760 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1761 database_id, object_store_id, kSpecialIndexNumber));
1762 std::string ret = prefix.Encode();
1763 ret.append(encoded_user_key);
1765 return ret;
1768 std::string ObjectStoreDataKey::Encode(int64 database_id,
1769 int64 object_store_id,
1770 const IndexedDBKey& user_key) {
1771 std::string encoded_key;
1772 EncodeIDBKey(user_key, &encoded_key);
1773 return Encode(database_id, object_store_id, encoded_key);
1776 scoped_ptr<IndexedDBKey> ObjectStoreDataKey::user_key() const {
1777 scoped_ptr<IndexedDBKey> key;
1778 StringPiece slice(encoded_user_key_);
1779 if (!DecodeIDBKey(&slice, &key)) {
1780 // TODO(jsbell): Return error.
1782 return key.Pass();
1785 const int64 ObjectStoreDataKey::kSpecialIndexNumber = kObjectStoreDataIndexId;
1787 ExistsEntryKey::ExistsEntryKey() {}
1788 ExistsEntryKey::~ExistsEntryKey() {}
1790 bool ExistsEntryKey::Decode(StringPiece* slice, ExistsEntryKey* result) {
1791 KeyPrefix prefix;
1792 if (!KeyPrefix::Decode(slice, &prefix))
1793 return false;
1794 DCHECK(prefix.database_id_);
1795 DCHECK(prefix.object_store_id_);
1796 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1797 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1798 return false;
1799 return true;
1802 std::string ExistsEntryKey::Encode(int64 database_id,
1803 int64 object_store_id,
1804 const std::string& encoded_key) {
1805 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1806 database_id, object_store_id, kSpecialIndexNumber));
1807 std::string ret = prefix.Encode();
1808 ret.append(encoded_key);
1809 return ret;
1812 std::string ExistsEntryKey::Encode(int64 database_id,
1813 int64 object_store_id,
1814 const IndexedDBKey& user_key) {
1815 std::string encoded_key;
1816 EncodeIDBKey(user_key, &encoded_key);
1817 return Encode(database_id, object_store_id, encoded_key);
1820 scoped_ptr<IndexedDBKey> ExistsEntryKey::user_key() const {
1821 scoped_ptr<IndexedDBKey> key;
1822 StringPiece slice(encoded_user_key_);
1823 if (!DecodeIDBKey(&slice, &key)) {
1824 // TODO(jsbell): Return error.
1826 return key.Pass();
1829 const int64 ExistsEntryKey::kSpecialIndexNumber = kExistsEntryIndexId;
1831 bool BlobEntryKey::Decode(StringPiece* slice, BlobEntryKey* result) {
1832 KeyPrefix prefix;
1833 if (!KeyPrefix::Decode(slice, &prefix))
1834 return false;
1835 DCHECK(prefix.database_id_);
1836 DCHECK(prefix.object_store_id_);
1837 DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
1839 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1840 return false;
1841 result->database_id_ = prefix.database_id_;
1842 result->object_store_id_ = prefix.object_store_id_;
1844 return true;
1847 bool BlobEntryKey::FromObjectStoreDataKey(StringPiece* slice,
1848 BlobEntryKey* result) {
1849 KeyPrefix prefix;
1850 if (!KeyPrefix::Decode(slice, &prefix))
1851 return false;
1852 DCHECK(prefix.database_id_);
1853 DCHECK(prefix.object_store_id_);
1854 DCHECK_EQ(prefix.index_id_, ObjectStoreDataKey::kSpecialIndexNumber);
1856 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1857 return false;
1858 result->database_id_ = prefix.database_id_;
1859 result->object_store_id_ = prefix.object_store_id_;
1860 return true;
1863 std::string BlobEntryKey::ReencodeToObjectStoreDataKey(StringPiece* slice) {
1864 // TODO(ericu): We could be more efficient here, since the suffix is the same.
1865 BlobEntryKey key;
1866 if (!Decode(slice, &key))
1867 return std::string();
1869 return ObjectStoreDataKey::Encode(
1870 key.database_id_, key.object_store_id_, key.encoded_user_key_);
1873 std::string BlobEntryKey::EncodeMinKeyForObjectStore(int64 database_id,
1874 int64 object_store_id) {
1875 // Our implied encoded_user_key_ here is empty, the lowest possible key.
1876 return Encode(database_id, object_store_id, std::string());
1879 std::string BlobEntryKey::EncodeStopKeyForObjectStore(int64 database_id,
1880 int64 object_store_id) {
1881 DCHECK(KeyPrefix::ValidIds(database_id, object_store_id));
1882 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1883 database_id, object_store_id, kSpecialIndexNumber + 1));
1884 return prefix.Encode();
1887 std::string BlobEntryKey::Encode() const {
1888 DCHECK(!encoded_user_key_.empty());
1889 return Encode(database_id_, object_store_id_, encoded_user_key_);
1892 std::string BlobEntryKey::Encode(int64 database_id,
1893 int64 object_store_id,
1894 const IndexedDBKey& user_key) {
1895 std::string encoded_key;
1896 EncodeIDBKey(user_key, &encoded_key);
1897 return Encode(database_id, object_store_id, encoded_key);
1900 std::string BlobEntryKey::Encode(int64 database_id,
1901 int64 object_store_id,
1902 const std::string& encoded_user_key) {
1903 DCHECK(KeyPrefix::ValidIds(database_id, object_store_id));
1904 KeyPrefix prefix(KeyPrefix::CreateWithSpecialIndex(
1905 database_id, object_store_id, kSpecialIndexNumber));
1906 return prefix.Encode() + encoded_user_key;
1909 const int64 BlobEntryKey::kSpecialIndexNumber = kBlobEntryIndexId;
1911 IndexDataKey::IndexDataKey()
1912 : database_id_(-1),
1913 object_store_id_(-1),
1914 index_id_(-1),
1915 sequence_number_(-1) {}
1917 IndexDataKey::~IndexDataKey() {}
1919 bool IndexDataKey::Decode(StringPiece* slice, IndexDataKey* result) {
1920 KeyPrefix prefix;
1921 if (!KeyPrefix::Decode(slice, &prefix))
1922 return false;
1923 DCHECK(prefix.database_id_);
1924 DCHECK(prefix.object_store_id_);
1925 DCHECK_GE(prefix.index_id_, kMinimumIndexId);
1926 result->database_id_ = prefix.database_id_;
1927 result->object_store_id_ = prefix.object_store_id_;
1928 result->index_id_ = prefix.index_id_;
1929 result->sequence_number_ = -1;
1930 result->encoded_primary_key_ = MinIDBKey();
1932 if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_))
1933 return false;
1935 // [optional] sequence number
1936 if (slice->empty())
1937 return true;
1938 if (!DecodeVarInt(slice, &result->sequence_number_))
1939 return false;
1941 // [optional] primary key
1942 if (slice->empty())
1943 return true;
1944 if (!ExtractEncodedIDBKey(slice, &result->encoded_primary_key_))
1945 return false;
1946 return true;
1949 std::string IndexDataKey::Encode(int64 database_id,
1950 int64 object_store_id,
1951 int64 index_id,
1952 const std::string& encoded_user_key,
1953 const std::string& encoded_primary_key,
1954 int64 sequence_number) {
1955 KeyPrefix prefix(database_id, object_store_id, index_id);
1956 std::string ret = prefix.Encode();
1957 ret.append(encoded_user_key);
1958 EncodeVarInt(sequence_number, &ret);
1959 ret.append(encoded_primary_key);
1960 return ret;
1963 std::string IndexDataKey::Encode(int64 database_id,
1964 int64 object_store_id,
1965 int64 index_id,
1966 const IndexedDBKey& user_key) {
1967 std::string encoded_key;
1968 EncodeIDBKey(user_key, &encoded_key);
1969 return Encode(
1970 database_id, object_store_id, index_id, encoded_key, MinIDBKey(), 0);
1973 std::string IndexDataKey::Encode(int64 database_id,
1974 int64 object_store_id,
1975 int64 index_id,
1976 const IndexedDBKey& user_key,
1977 const IndexedDBKey& user_primary_key) {
1978 std::string encoded_key;
1979 EncodeIDBKey(user_key, &encoded_key);
1980 std::string encoded_primary_key;
1981 EncodeIDBKey(user_primary_key, &encoded_primary_key);
1982 return Encode(database_id,
1983 object_store_id,
1984 index_id,
1985 encoded_key,
1986 encoded_primary_key,
1990 std::string IndexDataKey::EncodeMinKey(int64 database_id,
1991 int64 object_store_id,
1992 int64 index_id) {
1993 return Encode(
1994 database_id, object_store_id, index_id, MinIDBKey(), MinIDBKey(), 0);
1997 std::string IndexDataKey::EncodeMaxKey(int64 database_id,
1998 int64 object_store_id,
1999 int64 index_id) {
2000 return Encode(database_id,
2001 object_store_id,
2002 index_id,
2003 MaxIDBKey(),
2004 MaxIDBKey(),
2005 std::numeric_limits<int64>::max());
2008 int64 IndexDataKey::DatabaseId() const {
2009 DCHECK_GE(database_id_, 0);
2010 return database_id_;
2013 int64 IndexDataKey::ObjectStoreId() const {
2014 DCHECK_GE(object_store_id_, 0);
2015 return object_store_id_;
2018 int64 IndexDataKey::IndexId() const {
2019 DCHECK_GE(index_id_, 0);
2020 return index_id_;
2023 scoped_ptr<IndexedDBKey> IndexDataKey::user_key() const {
2024 scoped_ptr<IndexedDBKey> key;
2025 StringPiece slice(encoded_user_key_);
2026 if (!DecodeIDBKey(&slice, &key)) {
2027 // TODO(jsbell): Return error.
2029 return key.Pass();
2032 scoped_ptr<IndexedDBKey> IndexDataKey::primary_key() const {
2033 scoped_ptr<IndexedDBKey> key;
2034 StringPiece slice(encoded_primary_key_);
2035 if (!DecodeIDBKey(&slice, &key)) {
2036 // TODO(jsbell): Return error.
2038 return key.Pass();
2041 } // namespace content