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

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

Powered by Google App Engine
This is Rietveld 408576698