Chromium Code Reviews| 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 <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 | |
| OLD | NEW |