1 // Copyright (c) 2012 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/common/indexed_db/indexed_db_key.h" 6 7 #include <string> 8 #include "base/logging.h" 9 10 namespace content { 11 12 using blink::WebIDBKey; 13 using blink::WebIDBKeyType; 14 using blink::WebIDBKeyTypeArray; 15 using blink::WebIDBKeyTypeBinary; 16 using blink::WebIDBKeyTypeDate; 17 using blink::WebIDBKeyTypeInvalid; 18 using blink::WebIDBKeyTypeMin; 19 using blink::WebIDBKeyTypeNull; 20 using blink::WebIDBKeyTypeNumber; 21 using blink::WebIDBKeyTypeString; 22 23 namespace { 24 25 // Very rough estimate of minimum key size overhead. 26 const size_t kOverheadSize = 16; 27 28 static size_t CalculateArraySize(const IndexedDBKey::KeyArray& keys) { 29 size_t size(0); 30 for (size_t i = 0; i < keys.size(); ++i) 31 size += keys[i].size_estimate(); 32 return size; 33 } 34 35 template<typename T> 36 int Compare(const T& a, const T& b) { 37 // Using '<' for both comparisons here is as generic as possible (for e.g. 38 // objects which only define operator<() and not operator>() or operator==()) 39 // and also allows e.g. floating point NaNs to compare equal. 40 if (a < b) 41 return -1; 42 return (b < a) ? 1 : 0; 43 } 44 45 template <typename T> 46 static IndexedDBKey::KeyArray CopyKeyArray(const T& array) { 47 IndexedDBKey::KeyArray result; 48 result.reserve(array.size()); 49 for (size_t i = 0; i < array.size(); ++i) { 50 result.push_back(IndexedDBKey(array[i])); 51 } 52 return result; 53 } 54 55 } // namespace 56 57 IndexedDBKey::IndexedDBKey() 58 : type_(WebIDBKeyTypeNull), 59 date_(0), 60 number_(0), 61 size_estimate_(kOverheadSize) {} 62 63 IndexedDBKey::IndexedDBKey(WebIDBKeyType type) 64 : type_(type), date_(0), number_(0), size_estimate_(kOverheadSize) { 65 DCHECK(type == WebIDBKeyTypeNull || type == WebIDBKeyTypeInvalid); 66 } 67 68 IndexedDBKey::IndexedDBKey(double number, WebIDBKeyType type) 69 : type_(type), 70 date_(number), 71 number_(number), 72 size_estimate_(kOverheadSize + sizeof(number)) { 73 DCHECK(type == WebIDBKeyTypeNumber || type == WebIDBKeyTypeDate); 74 } 75 76 IndexedDBKey::IndexedDBKey(const KeyArray& array) 77 : type_(WebIDBKeyTypeArray), 78 array_(CopyKeyArray(array)), 79 date_(0), 80 number_(0), 81 size_estimate_(kOverheadSize + CalculateArraySize(array)) {} 82 83 IndexedDBKey::IndexedDBKey(const std::string& binary) 84 : type_(WebIDBKeyTypeBinary), 85 binary_(binary), 86 size_estimate_(kOverheadSize + 87 (binary.length() * sizeof(std::string::value_type))) {} 88 89 IndexedDBKey::IndexedDBKey(const base::string16& string) 90 : type_(WebIDBKeyTypeString), 91 string_(string), 92 size_estimate_(kOverheadSize + 93 (string.length() * sizeof(base::string16::value_type))) {} 94 95 IndexedDBKey::~IndexedDBKey() {} 96 97 IndexedDBKey::IndexedDBKey(const IndexedDBKey& other) 98 : type_(other.type_), 99 array_(other.array_), 100 binary_(other.binary_), 101 string_(other.string_), 102 date_(other.date_), 103 number_(other.number_), 104 size_estimate_(other.size_estimate_) { 105 DCHECK((!IsValid() && !other.IsValid()) || CompareTo(other) == 0); 106 } 107 108 IndexedDBKey& IndexedDBKey::operator=(const IndexedDBKey& other) { 109 type_ = other.type_; 110 array_ = other.array_; 111 binary_ = other.binary_; 112 string_ = other.string_; 113 date_ = other.date_; 114 number_ = other.number_; 115 size_estimate_ = other.size_estimate_; 116 DCHECK((!IsValid() && !other.IsValid()) || CompareTo(other) == 0); 117 return *this; 118 } 119 120 bool IndexedDBKey::IsValid() const { 121 if (type_ == WebIDBKeyTypeInvalid || type_ == WebIDBKeyTypeNull) 122 return false; 123 124 if (type_ == WebIDBKeyTypeArray) { 125 for (size_t i = 0; i < array_.size(); i++) { 126 if (!array_[i].IsValid()) 127 return false; 128 } 129 } 130 131 return true; 132 } 133 134 bool IndexedDBKey::IsLessThan(const IndexedDBKey& other) const { 135 return CompareTo(other) < 0; 136 } 137 138 bool IndexedDBKey::Equals(const IndexedDBKey& other) const { 139 return !CompareTo(other); 140 } 141 142 int IndexedDBKey::CompareTo(const IndexedDBKey& other) const { 143 DCHECK(IsValid()); 144 DCHECK(other.IsValid()); 145 if (type_ != other.type_) 146 return type_ > other.type_ ? -1 : 1; 147 148 switch (type_) { 149 case WebIDBKeyTypeArray: 150 for (size_t i = 0; i < array_.size() && i < other.array_.size(); ++i) { 151 int result = array_[i].CompareTo(other.array_[i]); 152 if (result != 0) 153 return result; 154 } 155 return Compare(array_.size(), other.array_.size()); 156 case WebIDBKeyTypeBinary: 157 return binary_.compare(other.binary_); 158 case WebIDBKeyTypeString: 159 return string_.compare(other.string_); 160 case WebIDBKeyTypeDate: 161 return Compare(date_, other.date_); 162 case WebIDBKeyTypeNumber: 163 return Compare(number_, other.number_); 164 case WebIDBKeyTypeInvalid: 165 case WebIDBKeyTypeNull: 166 case WebIDBKeyTypeMin: 167 default: 168 NOTREACHED(); 169 return 0; 170 } 171 } 172 173 } // namespace content 174