• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CalculateArraySize(const IndexedDBKey::KeyArray & keys)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>
Compare(const T & a,const T & b)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>
CopyKeyArray(const T & array)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 
IndexedDBKey()57 IndexedDBKey::IndexedDBKey()
58     : type_(WebIDBKeyTypeNull),
59       date_(0),
60       number_(0),
61       size_estimate_(kOverheadSize) {}
62 
IndexedDBKey(WebIDBKeyType type)63 IndexedDBKey::IndexedDBKey(WebIDBKeyType type)
64     : type_(type), date_(0), number_(0), size_estimate_(kOverheadSize) {
65   DCHECK(type == WebIDBKeyTypeNull || type == WebIDBKeyTypeInvalid);
66 }
67 
IndexedDBKey(double number,WebIDBKeyType type)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 
IndexedDBKey(const KeyArray & array)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 
IndexedDBKey(const std::string & binary)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 
IndexedDBKey(const base::string16 & string)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 
~IndexedDBKey()95 IndexedDBKey::~IndexedDBKey() {}
96 
IndexedDBKey(const IndexedDBKey & other)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 
operator =(const IndexedDBKey & other)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 
IsValid() const120 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 
IsLessThan(const IndexedDBKey & other) const134 bool IndexedDBKey::IsLessThan(const IndexedDBKey& other) const {
135   return CompareTo(other) < 0;
136 }
137 
Equals(const IndexedDBKey & other) const138 bool IndexedDBKey::Equals(const IndexedDBKey& other) const {
139   return !CompareTo(other);
140 }
141 
CompareTo(const IndexedDBKey & other) const142 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