Home | History | Annotate | Download | only in indexed_db
      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