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

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

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

Powered by Google App Engine
This is Rietveld 408576698