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 bool IndexedDBKey::IsValid() const { 98 if (type_ == WebIDBKeyTypeInvalid || type_ == WebIDBKeyTypeNull) 99 return false; 100 101 if (type_ == WebIDBKeyTypeArray) { 102 for (size_t i = 0; i < array_.size(); i++) { 103 if (!array_[i].IsValid()) 104 return false; 105 } 106 } 107 108 return true; 109 } 110 111 bool IndexedDBKey::IsLessThan(const IndexedDBKey& other) const { 112 return CompareTo(other) < 0; 113 } 114 115 bool IndexedDBKey::Equals(const IndexedDBKey& other) const { 116 return !CompareTo(other); 117 } 118 119 int IndexedDBKey::CompareTo(const IndexedDBKey& other) const { 120 DCHECK(IsValid()); 121 DCHECK(other.IsValid()); 122 if (type_ != other.type_) 123 return type_ > other.type_ ? -1 : 1; 124 125 switch (type_) { 126 case WebIDBKeyTypeArray: 127 for (size_t i = 0; i < array_.size() && i < other.array_.size(); ++i) { 128 int result = array_[i].CompareTo(other.array_[i]); 129 if (result != 0) 130 return result; 131 } 132 return Compare(array_.size(), other.array_.size()); 133 case WebIDBKeyTypeBinary: 134 return binary_.compare(other.binary_); 135 case WebIDBKeyTypeString: 136 return string_.compare(other.string_); 137 case WebIDBKeyTypeDate: 138 return Compare(date_, other.date_); 139 case WebIDBKeyTypeNumber: 140 return Compare(number_, other.number_); 141 case WebIDBKeyTypeInvalid: 142 case WebIDBKeyTypeNull: 143 case WebIDBKeyTypeMin: 144 default: 145 NOTREACHED(); 146 return 0; 147 } 148 } 149 150 } // namespace content 151