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 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