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