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

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

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

Powered by Google App Engine
This is Rietveld 408576698