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

Unified Diff: content/browser/indexed_db/indexed_db_leveldb_coding.cc

Issue 16256014: IndexedDB: Convert decoding functions to pass StringPieces vs. pointers (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Correct bogus iterator dereference in unit test Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/indexed_db/indexed_db_leveldb_coding.cc
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index 29ca0717d406eca46b580f88089568e98de7e074..c222c01f93fd8c85f78f9d166177a3506c136251 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -150,6 +150,7 @@
// IndexCursorImpl::load_current_row, and
// IndexKeyCursorImpl::load_current_row).
+using base::StringPiece;
using WebKit::WebIDBKey;
using WebKit::WebIDBKeyPath;
@@ -193,19 +194,9 @@ static const unsigned char kIndexMetaDataTypeMaximum = 255;
const unsigned char kMinimumIndexId = 30;
-void EncodeByte(unsigned char c, std::vector<char>* into) {
- into->push_back(c);
-}
-
-const char* DecodeByte(const char* p,
- const char* limit,
- unsigned char& found_char) {
- DCHECK_GE(limit, p);
- if (p >= limit)
- return 0;
-
- found_char = *p++;
- return p;
+inline void EncodeIntSafely(int64 nParam, int64 max, std::vector<char>* into) {
+ DCHECK_LE(nParam, max);
+ return EncodeInt(nParam, into);
}
std::vector<char> MaxIDBKey() {
@@ -220,19 +211,20 @@ std::vector<char> MinIDBKey() {
return ret;
}
-bool DecodeBool(const char* p, const char* limit) {
- DCHECK_GT(limit, p);
- return !!*p;
+void EncodeByte(unsigned char value, std::vector<char>* into) {
+ into->push_back(value);
}
-void EncodeBool(bool b, std::vector<char>* into) { into->push_back(b ? 1 : 0); }
+void EncodeBool(bool value, std::vector<char>* into) {
+ into->push_back(value ? 1 : 0);
+}
-void EncodeInt(int64 nParam, std::vector<char>* into) {
+void EncodeInt(int64 value, std::vector<char>* into) {
#ifndef NDEBUG
// Exercised by unit tests in debug only.
- DCHECK_GE(nParam, 0);
+ DCHECK_GE(value, 0);
#endif
- uint64 n = static_cast<uint64>(nParam);
+ uint64 n = static_cast<uint64>(value);
do {
unsigned char c = n;
@@ -241,26 +233,12 @@ void EncodeInt(int64 nParam, std::vector<char>* into) {
} while (n);
}
-static int CompareInts(int64 a, int64 b) {
-#ifndef NDEBUG
- // Exercised by unit tests in debug only.
- DCHECK_GE(a, 0);
- DCHECK_GE(b, 0);
-#endif
- int64 diff = a - b;
- if (diff < 0)
- return -1;
- if (diff > 0)
- return 1;
- return 0;
-}
-
-void EncodeVarInt(int64 nParam, std::vector<char>* into) {
+void EncodeVarInt(int64 value, std::vector<char>* into) {
#ifndef NDEBUG
// Exercised by unit tests in debug only.
- DCHECK_GE(nParam, 0);
+ DCHECK_GE(value, 0);
#endif
- uint64 n = static_cast<uint64>(nParam);
+ uint64 n = static_cast<uint64>(value);
do {
unsigned char c = n & 0x7f;
@@ -271,138 +249,35 @@ void EncodeVarInt(int64 nParam, std::vector<char>* into) {
} while (n);
}
-const char* DecodeVarInt(const char* p, const char* limit, int64& found_int) {
- DCHECK_GE(limit, p);
- found_int = 0;
- int shift = 0;
-
- do {
- if (p >= limit)
- return 0;
-
- unsigned char c = *p;
- found_int |= static_cast<int64>(c & 0x7f) << shift;
- shift += 7;
- } while (*p++ & 0x80);
- return p;
-}
-
-void EncodeString(const string16& s, std::vector<char>* into) {
- if (s.empty())
+void EncodeString(const string16& value, std::vector<char>* into) {
+ if (value.empty())
return;
// Backing store is UTF-16BE, convert from host endianness.
- size_t length = s.length();
+ size_t length = value.length();
size_t current = into->size();
into->resize(into->size() + length * sizeof(char16));
- const char16* src = s.c_str();
+ const char16* src = value.c_str();
char16* dst = reinterpret_cast<char16*>(&*into->begin() + current);
for (unsigned i = 0; i < length; ++i)
*dst++ = htons(*src++);
}
-string16 DecodeString(const char* p, const char* limit) {
- // Backing store is UTF-16BE, convert to host endianness.
- DCHECK_GE(limit, p);
- DCHECK(!((limit - p) % sizeof(char16)));
-
- size_t length = (limit - p) / sizeof(char16);
- string16 decoded;
- decoded.reserve(length);
- const char16* encoded = reinterpret_cast<const char16*>(p);
- for (unsigned i = 0; i < length; ++i)
- decoded.push_back(ntohs(*encoded++));
- return decoded;
-}
-
-void EncodeStringWithLength(const string16& s, std::vector<char>* into) {
- EncodeVarInt(s.length(), into);
- EncodeString(s, into);
-}
-
-const char* DecodeStringWithLength(const char* p,
- const char* limit,
- string16& found_string) {
- DCHECK_GE(limit, p);
- int64 len;
- p = DecodeVarInt(p, limit, len);
- if (!p || len < 0 || p + len * 2 > limit)
- return 0;
-
- found_string = DecodeString(p, p + len * 2);
- p += len * 2;
- return p;
+void EncodeStringWithLength(const string16& value, std::vector<char>* into) {
+ EncodeVarInt(value.length(), into);
+ EncodeString(value, into);
}
-int CompareEncodedStringsWithLength(const char*& p,
- const char* limit_p,
- const char*& q,
- const char* limit_q,
- bool& ok) {
- DCHECK_NE(&p, &q);
- DCHECK_GT(limit_p, p);
- DCHECK_GT(limit_q, q);
- int64 len_p, len_q;
- p = DecodeVarInt(p, limit_p, len_p);
- q = DecodeVarInt(q, limit_q, len_q);
- if (!p || !q || len_p < 0 || len_q < 0) {
- ok = false;
- return 0;
- }
- DCHECK(p && q);
- DCHECK_GE(len_p, 0);
- DCHECK_GE(len_q, 0);
- DCHECK_LE(p + len_p * 2, limit_p);
- DCHECK_LE(q + len_q * 2, limit_q);
-
- const char* start_p = p;
- const char* start_q = q;
- p += len_p * 2;
- q += len_q * 2;
-
- if (p > limit_p || q > limit_q) {
- ok = false;
- return 0;
- }
-
- ok = true;
- const size_t lmin = static_cast<size_t>(len_p < len_q ? len_p : len_q);
- if (int x = memcmp(start_p, start_q, lmin * 2))
- return x;
-
- if (len_p == len_q)
- return 0;
-
- return (len_p > len_q) ? 1 : -1;
-}
-
-void EncodeDouble(double x, std::vector<char>* into) {
- // TODO(jsbell): It would be nice if we could be byte order independent.
- const char* p = reinterpret_cast<char*>(&x);
- into->insert(into->end(), p, p + sizeof(x));
+void EncodeDouble(double value, std::vector<char>* into) {
+ // This always has host endianness.
+ const char* p = reinterpret_cast<char*>(&value);
+ into->insert(into->end(), p, p + sizeof(value));
}
-const char* DecodeDouble(const char* p, const char* limit, double* d) {
- if (p + sizeof(*d) > limit)
- return 0;
-
- char* x = reinterpret_cast<char*>(d);
- for (size_t i = 0; i < sizeof(*d); ++i)
- *x++ = *p++;
- return p;
-}
-
-std::vector<char> EncodeIDBKey(const IndexedDBKey& key) {
- std::vector<char> buffer;
- buffer.reserve(kDefaultInlineBufferSize);
- EncodeIDBKey(key, &buffer);
- return buffer;
-}
-
-void EncodeIDBKey(const IndexedDBKey& key, std::vector<char>* into) {
+void EncodeIDBKey(const IndexedDBKey& value, std::vector<char>* into) {
size_t previous_size = into->size();
- DCHECK(key.IsValid());
- switch (key.type()) {
+ DCHECK(value.IsValid());
+ switch (value.type()) {
case WebIDBKey::NullType:
case WebIDBKey::InvalidType:
case WebIDBKey::MinType: {
@@ -412,29 +287,29 @@ void EncodeIDBKey(const IndexedDBKey& key, std::vector<char>* into) {
}
case WebIDBKey::ArrayType: {
EncodeByte(kIndexedDBKeyArrayTypeByte, into);
- size_t length = key.array().size();
+ size_t length = value.array().size();
EncodeVarInt(length, into);
for (size_t i = 0; i < length; ++i)
- EncodeIDBKey(key.array()[i], into);
+ EncodeIDBKey(value.array()[i], into);
DCHECK_GT(into->size(), previous_size);
return;
}
case WebIDBKey::StringType: {
EncodeByte(kIndexedDBKeyStringTypeByte, into);
- EncodeStringWithLength(key.string(), into);
+ EncodeStringWithLength(value.string(), into);
DCHECK_GT(into->size(), previous_size);
return;
}
case WebIDBKey::DateType: {
EncodeByte(kIndexedDBKeyDateTypeByte, into);
- EncodeDouble(key.date(), into);
+ EncodeDouble(value.date(), into);
DCHECK_EQ(static_cast<size_t>(9),
static_cast<size_t>(into->size() - previous_size));
return;
}
case WebIDBKey::NumberType: {
EncodeByte(kIndexedDBKeyNumberTypeByte, into);
- EncodeDouble(key.number(), into);
+ EncodeDouble(value.number(), into);
DCHECK_EQ(static_cast<size_t>(9),
static_cast<size_t>(into->size() - previous_size));
return;
@@ -444,115 +319,287 @@ void EncodeIDBKey(const IndexedDBKey& key, std::vector<char>* into) {
NOTREACHED();
}
-const char* DecodeIDBKey(const char* p,
- const char* limit,
- scoped_ptr<IndexedDBKey>* found_key) {
- DCHECK_GE(limit, p);
- if (p >= limit)
- return 0;
+void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::vector<char>* into) {
+ // May be typed, or may be a raw string. An invalid leading
+ // byte is used to identify typed coding. New records are
+ // always written as typed.
+ EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into);
+ EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into);
+ EncodeByte(static_cast<char>(value.type()), into);
+ switch (value.type()) {
+ case WebIDBKeyPath::NullType:
+ break;
+ case WebIDBKeyPath::StringType: {
+ EncodeStringWithLength(value.string(), into);
+ break;
+ }
+ case WebIDBKeyPath::ArrayType: {
+ const std::vector<string16>& array = value.array();
+ size_t count = array.size();
+ EncodeVarInt(count, into);
+ for (size_t i = 0; i < count; ++i) {
+ EncodeStringWithLength(array[i], into);
+ }
+ break;
+ }
+ }
+}
+
+bool DecodeByte(StringPiece* slice, unsigned char* value) {
+ if (slice->empty())
+ return false;
+
+ *value = (*slice)[0];
+ slice->remove_prefix(1);
+ return true;
+}
+
+bool DecodeBool(StringPiece* slice, bool* value) {
+ if (slice->empty())
+ return false;
+
+ *value = !!(*slice)[0];
+ slice->remove_prefix(1);
+ return true;
+}
+
+bool DecodeInt(StringPiece* slice, int64* value) {
+ if (slice->empty())
+ return false;
+
+ StringPiece::const_iterator it = slice->begin();
+ int shift = 0;
+ int64 ret = 0;
+ while (it != slice->end()) {
+ unsigned char c = *it++;
+ ret |= static_cast<int64>(c) << shift;
+ shift += 8;
+ }
+ *value = ret;
+ slice->remove_prefix(it - slice->begin());
+ return true;
+}
+
+bool DecodeVarInt(StringPiece* slice, int64* value) {
+ if (slice->empty())
+ return false;
+
+ StringPiece::const_iterator it = slice->begin();
+ int shift = 0;
+ int64 ret = 0;
+ do {
+ if (it == slice->end())
+ return false;
+
+ unsigned char c = *it;
+ ret |= static_cast<int64>(c & 0x7f) << shift;
+ shift += 7;
+ } while (*it++ & 0x80);
+ *value = ret;
+ slice->remove_prefix(it - slice->begin());
+ return true;
+}
+
+bool DecodeString(StringPiece* slice, string16* value) {
+ if (slice->empty()) {
+ value->clear();
+ return true;
+ }
+
+ // Backing store is UTF-16BE, convert to host endianness.
+ DCHECK(!(slice->size() % sizeof(char16)));
+ size_t length = slice->size() / sizeof(char16);
+ string16 decoded;
+ decoded.reserve(length);
+ const char16* encoded = reinterpret_cast<const char16*>(slice->begin());
+ for (unsigned i = 0; i < length; ++i)
+ decoded.push_back(ntohs(*encoded++));
+
+ *value = decoded;
+ slice->remove_prefix(length * sizeof(char16));
+ return true;
+}
+
+bool DecodeStringWithLength(StringPiece* slice, string16* value) {
+ if (slice->empty())
+ return false;
- unsigned char type = *p++;
+ int64 len;
+ if (!DecodeVarInt(slice, &len) || len < 0)
+ return false;
+ size_t bytes = len * sizeof(char16);
+ if (slice->size() < bytes)
+ return false;
+
+ StringPiece subpiece(slice->begin(), bytes);
+ slice->remove_prefix(bytes);
+ if (!DecodeString(&subpiece, value))
+ return false;
+
+ return true;
+}
+
+bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) {
+ if (slice->empty())
+ return false;
+
+ unsigned char type = (*slice)[0];
+ slice->remove_prefix(1);
switch (type) {
case kIndexedDBKeyNullTypeByte:
- *found_key = make_scoped_ptr(new IndexedDBKey());
- return p;
+ *value = make_scoped_ptr(new IndexedDBKey());
+ return true;
case kIndexedDBKeyArrayTypeByte: {
int64 length;
- p = DecodeVarInt(p, limit, length);
- if (!p || length < 0)
- return 0;
+ if (!DecodeVarInt(slice, &length) || length < 0)
+ return false;
IndexedDBKey::KeyArray array;
while (length--) {
scoped_ptr<IndexedDBKey> key;
- p = DecodeIDBKey(p, limit, &key);
- if (!p)
- return 0;
+ if (!DecodeIDBKey(slice, &key))
+ return false;
array.push_back(*key);
}
- *found_key = make_scoped_ptr(new IndexedDBKey(array));
- return p;
+ *value = make_scoped_ptr(new IndexedDBKey(array));
+ return true;
}
case kIndexedDBKeyStringTypeByte: {
string16 s;
- p = DecodeStringWithLength(p, limit, s);
- if (!p)
- return 0;
- *found_key = make_scoped_ptr(new IndexedDBKey(s));
- return p;
+ if (!DecodeStringWithLength(slice, &s))
+ return false;
+ *value = make_scoped_ptr(new IndexedDBKey(s));
+ return true;
}
case kIndexedDBKeyDateTypeByte: {
double d;
- p = DecodeDouble(p, limit, &d);
- if (!p)
- return 0;
- *found_key = make_scoped_ptr(new IndexedDBKey(d, WebIDBKey::DateType));
- return p;
+ if (!DecodeDouble(slice, &d))
+ return false;
+ *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKey::DateType));
+ return true;
}
case kIndexedDBKeyNumberTypeByte: {
double d;
- p = DecodeDouble(p, limit, &d);
- if (!p)
- return 0;
- *found_key = make_scoped_ptr(new IndexedDBKey(d, WebIDBKey::NumberType));
- return p;
+ if (!DecodeDouble(slice, &d))
+ return false;
+ *value = make_scoped_ptr(new IndexedDBKey(d, WebIDBKey::NumberType));
+ return true;
}
}
NOTREACHED();
- return 0;
+ return false;
}
-const char* ExtractEncodedIDBKey(const char* start,
- const char* limit,
- std::vector<char>* result = 0) {
- DCHECK_GT(limit, start);
- const char* p = start;
- if (p >= limit)
- return 0;
+bool DecodeDouble(StringPiece* slice, double* value) {
+ if (slice->size() < sizeof(*value))
+ return false;
+
+ memcpy(value, slice->begin(), sizeof(*value));
+ slice->remove_prefix(sizeof(*value));
+ return true;
+}
- unsigned char type = *p++;
+bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) {
+ // May be typed, or may be a raw string. An invalid leading
+ // byte sequence is used to identify typed coding. New records are
+ // always written as typed.
+ if (slice->size() < 3 || (*slice)[0] != kIndexedDBKeyPathTypeCodedByte1 ||
+ (*slice)[1] != kIndexedDBKeyPathTypeCodedByte2) {
+ string16 s;
+ if (!DecodeString(slice, &s))
+ return false;
+ *value = IndexedDBKeyPath(s);
+ return true;
+ }
+
+ slice->remove_prefix(2);
+ DCHECK(!slice->empty());
+ WebIDBKeyPath::Type type = static_cast<WebIDBKeyPath::Type>((*slice)[0]);
+ slice->remove_prefix(1);
+
+ switch (type) {
+ case WebIDBKeyPath::NullType:
+ DCHECK(slice->empty());
+ *value = IndexedDBKeyPath();
+ return true;
+ case WebIDBKeyPath::StringType: {
+ string16 string;
+ if (!DecodeStringWithLength(slice, &string))
+ return false;
+ DCHECK(slice->empty());
+ *value = IndexedDBKeyPath(string);
+ return true;
+ }
+ case WebIDBKeyPath::ArrayType: {
+ std::vector<string16> array;
+ int64 count;
+ if (!DecodeVarInt(slice, &count))
+ return false;
+ DCHECK_GE(count, 0);
+ while (count--) {
+ string16 string;
+ if (!DecodeStringWithLength(slice, &string))
+ return false;
+ array.push_back(string);
+ }
+ DCHECK(slice->empty());
+ *value = IndexedDBKeyPath(array);
+ return true;
+ }
+ }
+ NOTREACHED();
+ return false;
+}
+
+bool ExtractEncodedIDBKey(StringPiece* slice) {
+
+ unsigned char type = (*slice)[0];
+ slice->remove_prefix(1);
switch (type) {
case kIndexedDBKeyNullTypeByte:
case kIndexedDBKeyMinKeyTypeByte:
- break;
+ return true;
case kIndexedDBKeyArrayTypeByte: {
int64 length;
- p = DecodeVarInt(p, limit, length);
- if (!p || length < 0)
- return 0;
+ if (!DecodeVarInt(slice, &length))
+ return false;
while (length--) {
- p = ExtractEncodedIDBKey(p, limit);
- if (!p)
- return 0;
+ if (!ExtractEncodedIDBKey(slice))
+ return false;
}
- break;
+ return true;
}
case kIndexedDBKeyStringTypeByte: {
int64 length;
- p = DecodeVarInt(p, limit, length);
- if (!p || length < 0 || p + length * 2 > limit)
- return 0;
- p += length * 2;
- break;
+ if (!DecodeVarInt(slice, &length) || length < 0)
+ return false;
+ if (slice->size() < static_cast<size_t>(length) * sizeof(char16))
+ return false;
+ slice->remove_prefix(length * sizeof(char16));
+ return true;
}
case kIndexedDBKeyDateTypeByte:
case kIndexedDBKeyNumberTypeByte:
- if (p + sizeof(double) > limit)
- return 0;
- p += sizeof(double);
- break;
+ if (slice->size() < sizeof(double))
+ return false;
+ slice->remove_prefix(sizeof(double));
+ return true;
}
+ NOTREACHED();
+ return false;
+}
- if (result) {
- DCHECK(p);
- DCHECK_LE(p, limit);
- result->assign(start, p);
- }
+bool ExtractEncodedIDBKey(StringPiece* slice, std::vector<char>* result) {
+ const char* start = slice->begin();
+ if (!ExtractEncodedIDBKey(slice))
+ return 0;
- return p;
+ if (result)
+ result->assign(start, slice->begin());
+ return true;
}
static WebIDBKey::Type KeyTypeByteToKeyType(unsigned char type) {
@@ -575,19 +622,62 @@ static WebIDBKey::Type KeyTypeByteToKeyType(unsigned char type) {
return WebIDBKey::InvalidType;
}
+int CompareEncodedStringsWithLength(StringPiece* slice1,
+ StringPiece* slice2,
+ bool& ok) {
+ int64 len1, len2;
+ if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
+ ok = false;
+ return 0;
+ }
+ DCHECK_GE(len1, 0);
+ DCHECK_GE(len2, 0);
+ if (len1 < 0 || len2 < 0) {
+ ok = false;
+ return 0;
+ }
+ DCHECK_GE(slice1->size(), len1 * sizeof(char16));
+ DCHECK_GE(slice2->size(), len2 * sizeof(char16));
+ if (slice1->size() < len1 * sizeof(char16) ||
+ slice2->size() < len2 * sizeof(char16)) {
+ ok = false;
+ return 0;
+ }
+
+ StringPiece string1(slice1->begin(), len1 * sizeof(char16));
+ StringPiece string2(slice2->begin(), len2 * sizeof(char16));
+ slice1->remove_prefix(len1 * sizeof(char16));
+ slice2->remove_prefix(len2 * sizeof(char16));
+
+ ok = true;
+ // Strings are UTF-16BE encoded, so a simple memcmp is sufficient.
+ return string1.compare(string2);
+}
+
+static int CompareInts(int64 a, int64 b) {
+#ifndef NDEBUG
+ // Exercised by unit tests in debug only.
+ DCHECK_GE(a, 0);
+ DCHECK_GE(b, 0);
+#endif
+ int64 diff = a - b;
+ if (diff < 0)
+ return -1;
+ if (diff > 0)
+ return 1;
+ return 0;
+}
+
static int CompareTypes(WebIDBKey::Type a, WebIDBKey::Type b) { return b - a; }
-int CompareEncodedIDBKeys(const char*& ptr_a,
- const char* limit_a,
- const char*& ptr_b,
- const char* limit_b,
+int CompareEncodedIDBKeys(StringPiece* slice_a,
+ StringPiece* slice_b,
bool& ok) {
ok = true;
- DCHECK_NE(&ptr_a, &ptr_b);
- DCHECK_LT(ptr_a, limit_a);
- DCHECK_LT(ptr_b, limit_b);
- unsigned char type_a = *ptr_a++;
- unsigned char type_b = *ptr_b++;
+ unsigned char type_a = (*slice_a)[0];
+ unsigned char type_b = (*slice_b)[0];
+ slice_a->remove_prefix(1);
+ slice_b->remove_prefix(1);
if (int x = CompareTypes(KeyTypeByteToKeyType(type_a),
KeyTypeByteToKeyType(type_b)))
@@ -600,34 +690,24 @@ int CompareEncodedIDBKeys(const char*& ptr_a,
return 0;
case kIndexedDBKeyArrayTypeByte: {
int64 length_a, length_b;
- ptr_a = DecodeVarInt(ptr_a, limit_a, length_a);
- ptr_b = DecodeVarInt(ptr_b, limit_b, length_b);
- if (!ptr_a || !ptr_b || length_a < 0 || length_b < 0) {
+ if (!DecodeVarInt(slice_a, &length_a) ||
+ !DecodeVarInt(slice_b, &length_b)) {
ok = false;
return 0;
}
for (int64 i = 0; i < length_a && i < length_b; ++i) {
- int result = CompareEncodedIDBKeys(ptr_a, limit_a, ptr_b, limit_b, ok);
+ int result = CompareEncodedIDBKeys(slice_a, slice_b, ok);
if (!ok || result)
return result;
}
- if (length_a < length_b)
- return -1;
- if (length_a > length_b)
- return 1;
- return 0;
+ return length_a - length_b;
}
case kIndexedDBKeyStringTypeByte:
- return CompareEncodedStringsWithLength(
- ptr_a, limit_a, ptr_b, limit_b, ok);
+ return CompareEncodedStringsWithLength(slice_a, slice_b, ok);
case kIndexedDBKeyDateTypeByte:
case kIndexedDBKeyNumberTypeByte: {
double d, e;
- ptr_a = DecodeDouble(ptr_a, limit_a, &d);
- ptr_b = DecodeDouble(ptr_b, limit_b, &e);
- DCHECK(ptr_a);
- DCHECK(ptr_b);
- if (!ptr_a || !ptr_b) {
+ if (!DecodeDouble(slice_a, &d) || !DecodeDouble(slice_b, &e)) {
ok = false;
return 0;
}
@@ -646,84 +726,12 @@ int CompareEncodedIDBKeys(const char*& ptr_a,
int CompareEncodedIDBKeys(const std::vector<char>& key_a,
const std::vector<char>& key_b,
bool& ok) {
- DCHECK_GE(key_a.size(), static_cast<size_t>(1));
- DCHECK_GE(key_b.size(), static_cast<size_t>(1));
-
- const char* ptr_a = &*key_a.begin();
- const char* limit_a = &*key_a.rbegin() + 1;
- const char* ptr_b = &*key_b.begin();
- const char* limit_b = &*key_b.rbegin() + 1;
+ DCHECK(!key_a.empty());
+ DCHECK(!key_b.empty());
- return CompareEncodedIDBKeys(ptr_a, limit_a, ptr_b, limit_b, ok);
-}
-
-void EncodeIDBKeyPath(const IndexedDBKeyPath& key_path,
- std::vector<char>* into) {
- // May be typed, or may be a raw string. An invalid leading
- // byte is used to identify typed coding. New records are
- // always written as typed.
- EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into);
- EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into);
- EncodeByte(static_cast<char>(key_path.type()), into);
- switch (key_path.type()) {
- case WebIDBKeyPath::NullType:
- break;
- case WebIDBKeyPath::StringType: {
- EncodeStringWithLength(key_path.string(), into);
- break;
- }
- case WebIDBKeyPath::ArrayType: {
- const std::vector<string16>& array = key_path.array();
- size_t count = array.size();
- EncodeVarInt(count, into);
- for (size_t i = 0; i < count; ++i) {
- EncodeStringWithLength(array[i], into);
- }
- break;
- }
- }
-}
-
-IndexedDBKeyPath DecodeIDBKeyPath(const char* p, const char* limit) {
- // May be typed, or may be a raw string. An invalid leading
- // byte sequence is used to identify typed coding. New records are
- // always written as typed.
- if (p == limit ||
- (limit - p >= 2 && (*p != kIndexedDBKeyPathTypeCodedByte1 ||
- *(p + 1) != kIndexedDBKeyPathTypeCodedByte2)))
- return IndexedDBKeyPath(DecodeString(p, limit));
- p += 2;
-
- DCHECK_NE(p, limit);
- WebIDBKeyPath::Type type = static_cast<WebIDBKeyPath::Type>(*p++);
- switch (type) {
- case WebIDBKeyPath::NullType:
- DCHECK_EQ(p, limit);
- return IndexedDBKeyPath();
- case WebIDBKeyPath::StringType: {
- string16 string;
- p = DecodeStringWithLength(p, limit, string);
- DCHECK_EQ(p, limit);
- return IndexedDBKeyPath(string);
- }
- case WebIDBKeyPath::ArrayType: {
- std::vector<string16> array;
- int64 count;
- p = DecodeVarInt(p, limit, count);
- DCHECK(p);
- DCHECK_GE(count, 0);
- while (count--) {
- string16 string;
- p = DecodeStringWithLength(p, limit, string);
- DCHECK(p);
- array.push_back(string);
- }
- DCHECK_EQ(p, limit);
- return IndexedDBKeyPath(array);
- }
- }
- NOTREACHED();
- return IndexedDBKeyPath();
+ StringPiece slice_a(&*key_a.begin(), key_a.size());
+ StringPiece slice_b(&*key_b.begin(), key_b.size());
+ return CompareEncodedIDBKeys(&slice_a, &slice_b, ok);
}
namespace {
@@ -772,7 +780,9 @@ int Compare<ExistsEntryKey>(const LevelDBSlice& a,
// Prefixes are not compared - it is assumed this was already done.
DCHECK(!prefix_a.Compare(prefix_b));
- return CompareEncodedIDBKeys(ptr_a, a.end(), ptr_b, b.end(), ok);
+ StringPiece slice_a(ptr_a, a.end() - ptr_a);
+ StringPiece slice_b(ptr_b, b.end() - ptr_b);
+ return CompareEncodedIDBKeys(&slice_a, &slice_b, ok);
}
template <>
@@ -797,7 +807,9 @@ int Compare<ObjectStoreDataKey>(const LevelDBSlice& a,
// Prefixes are not compared - it is assumed this was already done.
DCHECK(!prefix_a.Compare(prefix_b));
- return CompareEncodedIDBKeys(ptr_a, a.end(), ptr_b, b.end(), ok);
+ StringPiece slice_a(ptr_a, a.end() - ptr_a);
+ StringPiece slice_b(ptr_b, b.end() - ptr_b);
+ return CompareEncodedIDBKeys(&slice_a, &slice_b, ok);
}
template <>
@@ -823,7 +835,10 @@ int Compare<IndexDataKey>(const LevelDBSlice& a,
DCHECK(!prefix_a.Compare(prefix_b));
// index key
- int result = CompareEncodedIDBKeys(ptr_a, a.end(), ptr_b, b.end(), ok);
+
+ StringPiece slice_a(ptr_a, a.end() - ptr_a);
+ StringPiece slice_b(ptr_b, b.end() - ptr_b);
+ int result = CompareEncodedIDBKeys(&slice_a, &slice_b, ok);
if (!ok || result)
return result;
if (ignore_duplicates)
@@ -832,22 +847,24 @@ int Compare<IndexDataKey>(const LevelDBSlice& a,
// sequence number [optional]
int64 sequence_number_a = -1;
int64 sequence_number_b = -1;
- if (ptr_a != a.end())
- ptr_a = DecodeVarInt(ptr_a, a.end(), sequence_number_a);
- if (ptr_b != b.end())
- ptr_b = DecodeVarInt(ptr_b, b.end(), sequence_number_b);
+ if (!slice_a.empty()) {
+ if (!DecodeVarInt(&slice_a, &sequence_number_a))
+ return 0;
+ }
+ if (!slice_b.empty()) {
+ if (!DecodeVarInt(&slice_b, &sequence_number_b))
+ return 0;
+ }
// primary key [optional]
- if (!ptr_a || !ptr_b)
- return 0;
- if (ptr_a == a.end() && ptr_b == b.end())
+ if (slice_a.empty() && slice_b.empty())
return 0;
- if (ptr_a == a.end())
+ if (slice_a.empty())
return -1;
- if (ptr_b == b.end())
+ if (slice_b.empty())
return 1;
- result = CompareEncodedIDBKeys(ptr_a, a.end(), ptr_b, b.end(), ok);
+ result = CompareEncodedIDBKeys(&slice_a, &slice_b, ok);
if (!ok || result)
return result;
@@ -937,6 +954,7 @@ int Compare(const LevelDBSlice& a,
const bool ignore_duplicates = false;
return Compare<ObjectStoreDataKey>(a, b, ignore_duplicates, ok);
}
+
if (prefix_a.type() == KeyPrefix::EXISTS_ENTRY) {
if (ptr_a == end_a && ptr_b == end_b)
return 0;
@@ -949,6 +967,7 @@ int Compare(const LevelDBSlice& a,
const bool ignore_duplicates = false;
return Compare<ExistsEntryKey>(a, b, ignore_duplicates, ok);
}
+
if (prefix_a.type() == KeyPrefix::INDEX_DATA) {
if (ptr_a == end_a && ptr_b == end_b)
return 0;
@@ -1055,11 +1074,23 @@ const char* KeyPrefix::Decode(const char* start,
limit)
return 0;
- result->database_id_ = DecodeInt(start, start + database_id_bytes);
+ {
+ StringPiece slice(start, database_id_bytes);
+ if (!DecodeInt(&slice, &result->database_id_))
+ return 0;
+ }
start += database_id_bytes;
- result->object_store_id_ = DecodeInt(start, start + object_store_id_bytes);
+ {
+ StringPiece slice(start, object_store_id_bytes);
+ if (!DecodeInt(&slice, &result->object_store_id_))
+ return 0;
+ }
start += object_store_id_bytes;
- result->index_id_ = DecodeInt(start, start + index_id_bytes);
+ {
+ StringPiece slice(start, index_id_bytes);
+ if (!DecodeInt(&slice, &result->index_id_))
+ return 0;
+ }
start += index_id_bytes;
return start;
@@ -1181,11 +1212,15 @@ const char* DatabaseFreeListKey::Decode(const char* start,
if (p == limit)
return 0;
unsigned char type_byte = 0;
- p = DecodeByte(p, limit, type_byte);
+ StringPiece slice(p, limit - p);
+ if (!DecodeByte(&slice, &type_byte))
+ return 0;
DCHECK_EQ(type_byte, kDatabaseFreeListTypeByte);
- if (p == limit)
+ if (slice.empty())
return 0;
- return DecodeVarInt(p, limit, result->database_id_);
+ if (!DecodeVarInt(&slice, &result->database_id_))
+ return 0;
+ return slice.begin();
}
std::vector<char> DatabaseFreeListKey::Encode(int64 database_id) {
@@ -1222,14 +1257,15 @@ const char* DatabaseNameKey::Decode(const char* start,
if (p == limit)
return 0;
unsigned char type_byte = 0;
- p = DecodeByte(p, limit, type_byte);
+ StringPiece slice(p, limit - p);
+ if (!DecodeByte(&slice, &type_byte))
+ return 0;
DCHECK_EQ(type_byte, kDatabaseNameTypeByte);
- if (p == limit)
+ if (!DecodeStringWithLength(&slice, &result->origin_))
return 0;
- p = DecodeStringWithLength(p, limit, result->origin_);
- if (!p)
+ if (!DecodeStringWithLength(&slice, &result->database_name_))
return 0;
- return DecodeStringWithLength(p, limit, result->database_name_);
+ return slice.begin();
}
std::vector<char> DatabaseNameKey::Encode(const string16& origin,
@@ -1282,17 +1318,16 @@ const char* ObjectStoreMetaDataKey::Decode(const char* start,
if (p == limit)
return 0;
unsigned char type_byte = 0;
- p = DecodeByte(p, limit, type_byte);
- DCHECK_EQ(type_byte, kObjectStoreMetaDataTypeByte);
- if (p == limit)
+ StringPiece slice(p, limit - p);
+ if (!DecodeByte(&slice, &type_byte))
return 0;
- p = DecodeVarInt(p, limit, result->object_store_id_);
- if (!p)
+ DCHECK_EQ(type_byte, kObjectStoreMetaDataTypeByte);
+ if (!DecodeVarInt(&slice, &result->object_store_id_))
return 0;
DCHECK(result->object_store_id_);
- if (p == limit)
+ if (!DecodeByte(&slice, &result->meta_data_type_))
return 0;
- return DecodeByte(p, limit, result->meta_data_type_);
+ return slice.begin();
}
std::vector<char> ObjectStoreMetaDataKey::Encode(int64 database_id,
@@ -1351,19 +1386,17 @@ const char* IndexMetaDataKey::Decode(const char* start,
if (p == limit)
return 0;
unsigned char type_byte = 0;
- p = DecodeByte(p, limit, type_byte);
- DCHECK_EQ(type_byte, kIndexMetaDataTypeByte);
- if (p == limit)
+ StringPiece slice(p, limit - p);
+ if (!DecodeByte(&slice, &type_byte))
return 0;
- p = DecodeVarInt(p, limit, result->object_store_id_);
- if (!p)
+ DCHECK_EQ(type_byte, kIndexMetaDataTypeByte);
+ if (!DecodeVarInt(&slice, &result->object_store_id_))
return 0;
- p = DecodeVarInt(p, limit, result->index_id_);
- if (!p)
+ if (!DecodeVarInt(&slice, &result->index_id_))
return 0;
- if (p == limit)
+ if (!DecodeByte(&slice, &result->meta_data_type_))
return 0;
- return DecodeByte(p, limit, result->meta_data_type_);
+ return slice.begin();
}
std::vector<char> IndexMetaDataKey::Encode(int64 database_id,
@@ -1425,11 +1458,13 @@ const char* ObjectStoreFreeListKey::Decode(const char* start,
if (p == limit)
return 0;
unsigned char type_byte = 0;
- p = DecodeByte(p, limit, type_byte);
+ StringPiece slice(p, limit - p);
+ if (!DecodeByte(&slice, &type_byte))
+ return 0;
DCHECK_EQ(type_byte, kObjectStoreFreeListTypeByte);
- if (p == limit)
+ if (!DecodeVarInt(&slice, &result->object_store_id_))
return 0;
- return DecodeVarInt(p, limit, result->object_store_id_);
+ return slice.begin();
}
std::vector<char> ObjectStoreFreeListKey::Encode(int64 database_id,
@@ -1473,14 +1508,15 @@ const char* IndexFreeListKey::Decode(const char* start,
if (p == limit)
return 0;
unsigned char type_byte = 0;
- p = DecodeByte(p, limit, type_byte);
+ StringPiece slice(p, limit - p);
+ if (!DecodeByte(&slice, &type_byte))
+ return 0;
DCHECK_EQ(type_byte, kIndexFreeListTypeByte);
- if (p == limit)
+ if (!DecodeVarInt(&slice, &result->object_store_id_))
return 0;
- p = DecodeVarInt(p, limit, result->object_store_id_);
- if (!p)
+ if (!DecodeVarInt(&slice, &result->index_id_))
return 0;
- return DecodeVarInt(p, limit, result->index_id_);
+ return slice.begin();
}
std::vector<char> IndexFreeListKey::Encode(int64 database_id,
@@ -1534,9 +1570,13 @@ const char* ObjectStoreNamesKey::Decode(const char* start,
if (p == limit)
return 0;
unsigned char type_byte = 0;
- p = DecodeByte(p, limit, type_byte);
+ StringPiece slice(p, limit - p);
+ if (!DecodeByte(&slice, &type_byte))
+ return 0;
DCHECK_EQ(type_byte, kObjectStoreNamesTypeByte);
- return DecodeStringWithLength(p, limit, result->object_store_name_);
+ if (!DecodeStringWithLength(&slice, &result->object_store_name_))
+ return 0;
+ return slice.begin();
}
std::vector<char> ObjectStoreNamesKey::Encode(
@@ -1570,14 +1610,15 @@ const char* IndexNamesKey::Decode(const char* start,
if (p == limit)
return 0;
unsigned char type_byte = 0;
- p = DecodeByte(p, limit, type_byte);
+ StringPiece slice(p, limit - p);
+ if (!DecodeByte(&slice, &type_byte))
+ return 0;
DCHECK_EQ(type_byte, kIndexNamesKeyTypeByte);
- if (p == limit)
+ if (!DecodeVarInt(&slice, &result->object_store_id_))
return 0;
- p = DecodeVarInt(p, limit, result->object_store_id_);
- if (!p)
+ if (!DecodeStringWithLength(&slice, &result->index_name_))
return 0;
- return DecodeStringWithLength(p, limit, result->index_name_);
+ return slice.begin();
}
std::vector<char> IndexNamesKey::Encode(int64 database_id,
@@ -1613,7 +1654,10 @@ const char* ObjectStoreDataKey::Decode(const char* start,
DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
if (p == end)
return 0;
- return ExtractEncodedIDBKey(p, end, &result->encoded_user_key_);
+ StringPiece slice(p, end - p);
+ if (!ExtractEncodedIDBKey(&slice, &result->encoded_user_key_))
+ return 0;
+ return slice.begin();
}
std::vector<char> ObjectStoreDataKey::Encode(
@@ -1631,7 +1675,9 @@ std::vector<char> ObjectStoreDataKey::Encode(
std::vector<char> ObjectStoreDataKey::Encode(int64 database_id,
int64 object_store_id,
const IndexedDBKey& user_key) {
- return Encode(database_id, object_store_id, EncodeIDBKey(user_key));
+ std::vector<char> encoded_key;
+ EncodeIDBKey(user_key, &encoded_key);
+ return Encode(database_id, object_store_id, encoded_key);
}
int ObjectStoreDataKey::Compare(const ObjectStoreDataKey& other, bool& ok) {
@@ -1640,9 +1686,10 @@ int ObjectStoreDataKey::Compare(const ObjectStoreDataKey& other, bool& ok) {
scoped_ptr<IndexedDBKey> ObjectStoreDataKey::user_key() const {
scoped_ptr<IndexedDBKey> key;
- DecodeIDBKey(&encoded_user_key_[0],
- &encoded_user_key_[0] + encoded_user_key_.size(),
- &key);
+ StringPiece slice(&encoded_user_key_[0], encoded_user_key_.size());
+ if (!DecodeIDBKey(&slice, &key)) {
+ // TODO(jsbell): Return error.
+ }
return key.Pass();
}
@@ -1663,7 +1710,10 @@ const char* ExistsEntryKey::Decode(const char* start,
DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber);
if (p == end)
return 0;
- return ExtractEncodedIDBKey(p, end, &result->encoded_user_key_);
+ StringPiece slice(p, end - p);
+ if (!ExtractEncodedIDBKey(&slice, &result->encoded_user_key_))
+ return 0;
+ return slice.begin();
}
std::vector<char> ExistsEntryKey::Encode(int64 database_id,
@@ -1679,7 +1729,9 @@ std::vector<char> ExistsEntryKey::Encode(int64 database_id,
std::vector<char> ExistsEntryKey::Encode(int64 database_id,
int64 object_store_id,
const IndexedDBKey& user_key) {
- return Encode(database_id, object_store_id, EncodeIDBKey(user_key));
+ std::vector<char> encoded_key;
+ EncodeIDBKey(user_key, &encoded_key);
+ return Encode(database_id, object_store_id, encoded_key);
}
int ExistsEntryKey::Compare(const ExistsEntryKey& other, bool& ok) {
@@ -1688,9 +1740,10 @@ int ExistsEntryKey::Compare(const ExistsEntryKey& other, bool& ok) {
scoped_ptr<IndexedDBKey> ExistsEntryKey::user_key() const {
scoped_ptr<IndexedDBKey> key;
- DecodeIDBKey(&encoded_user_key_[0],
- &encoded_user_key_[0] + encoded_user_key_.size(),
- &key);
+ StringPiece slice(&encoded_user_key_[0], encoded_user_key_.size());
+ if (!DecodeIDBKey(&slice, &key)) {
+ // TODO(jsbell): Return error.
+ }
return key.Pass();
}
@@ -1720,25 +1773,23 @@ const char* IndexDataKey::Decode(const char* start,
result->sequence_number_ = -1;
result->encoded_primary_key_ = MinIDBKey();
- p = ExtractEncodedIDBKey(p, limit, &result->encoded_user_key_);
- if (!p)
+ StringPiece slice(p, limit - p);
+ if (!ExtractEncodedIDBKey(&slice, &result->encoded_user_key_))
return 0;
// [optional] sequence number
- if (p == limit)
- return p;
- p = DecodeVarInt(p, limit, result->sequence_number_);
- if (!p)
+ if (slice.empty())
+ return slice.begin();
+ if (!DecodeVarInt(&slice, &result->sequence_number_))
return 0;
// [optional] primary key
- if (p == limit)
- return p;
- p = ExtractEncodedIDBKey(p, limit, &result->encoded_primary_key_);
- if (!p)
+ if (slice.empty())
+ return slice.begin();
+ if (!ExtractEncodedIDBKey(&slice, &result->encoded_primary_key_))
return 0;
- return p;
+ return slice.begin();
}
std::vector<char> IndexDataKey::Encode(
@@ -1760,11 +1811,10 @@ std::vector<char> IndexDataKey::Encode(int64 database_id,
int64 object_store_id,
int64 index_id,
const IndexedDBKey& user_key) {
- return Encode(database_id,
- object_store_id,
- index_id,
- EncodeIDBKey(user_key),
- MinIDBKey());
+ std::vector<char> encoded_key;
+ EncodeIDBKey(user_key, &encoded_key);
+ return Encode(
+ database_id, object_store_id, index_id, encoded_key, MinIDBKey());
}
std::vector<char> IndexDataKey::EncodeMinKey(int64 database_id,
@@ -1821,17 +1871,19 @@ int64 IndexDataKey::IndexId() const {
scoped_ptr<IndexedDBKey> IndexDataKey::user_key() const {
scoped_ptr<IndexedDBKey> key;
- DecodeIDBKey(&encoded_user_key_[0],
- &encoded_user_key_[0] + encoded_user_key_.size(),
- &key);
+ StringPiece slice(&encoded_user_key_[0], encoded_user_key_.size());
+ if (!DecodeIDBKey(&slice, &key)) {
+ // TODO(jsbell): Return error.
+ }
return key.Pass();
}
scoped_ptr<IndexedDBKey> IndexDataKey::primary_key() const {
scoped_ptr<IndexedDBKey> key;
- DecodeIDBKey(&encoded_primary_key_[0],
- &encoded_primary_key_[0] + encoded_primary_key_.size(),
- &key);
+ StringPiece slice(&encoded_primary_key_[0], encoded_primary_key_.size());
+ if (!DecodeIDBKey(&slice, &key)) {
+ // TODO(jsbell): Return error.
+ }
return key.Pass();
}

Powered by Google App Engine
This is Rietveld 408576698