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