/* Copyright (c) 2008-2010, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// This file is part of ThreadSanitizer, a dynamic data race detector.
// Author: Konstantin Serebryany.
#ifndef TS_DENSE_MULTIMAP_
#define TS_DENSE_MULTIMAP_
#include "ts_util.h"
// DenseMultimap is imilar to STL multimap, but optimized for memory.
// DenseMultimap objects are immutable after creation.
// All CTORs have linear complexity.
template<class T, int kPreallocatedElements>
class DenseMultimap {
public:
typedef const T *const_iterator;
enum RemoveEnum {REMOVE};
// Create multimap {t1, t2}
DenseMultimap(const T &t1, const T &t2) {
Allocate(2);
if (t1 < t2) {
ptr_[0] = t1;
ptr_[1] = t2;
} else {
ptr_[0] = t2;
ptr_[1] = t1;
}
Validate();
}
// Create a copy of m.
DenseMultimap(const DenseMultimap &m) {
Allocate(m.size());
copy(m.begin(), m.end(), ptr_);
Validate();
}
// Create multimap m+{t}
DenseMultimap(const DenseMultimap &m, const T &t) {
Allocate(m.size() + 1);
const_iterator it = lower_bound(m.begin(), m.end(), t);
copy(m.begin(), it, ptr_);
ptr_[it - m.begin()] = t;
copy(it, m.end(), ptr_ + (it - m.begin()) + 1);
Validate();
}
// Create multimap m-{t}
DenseMultimap(const DenseMultimap &m, RemoveEnum remove, const T &t) {
const_iterator it = lower_bound(m.begin(), m.end(), t);
CHECK(it < m.end() && it >= m.begin());
Allocate(m.size() - 1);
copy(m.begin(), it, ptr_);
copy(it + 1, m.end(), ptr_ + (it - m.begin()));
Validate();
}
~DenseMultimap() {
if (size_ > kPreallocatedElements) {
CHECK(ptr_ != (T*)&array_);
delete [] ptr_;
} else {
CHECK(ptr_ == (T*)&array_);
}
}
size_t size() const { return size_; }
const T &operator [] (size_t i) const {
CHECK(i < size());
return ptr_[i];
}
const_iterator begin() const { return ptr_; }
const_iterator end() const { return ptr_ + size(); }
bool has(const T&t) const {
return binary_search(begin(), end(), t);
}
bool operator < (const DenseMultimap &m) const {
if (size() != m.size()) return size() < m.size();
for (size_t i = 0; i < size(); i++) {
if (ptr_[i] != m.ptr_[i])
return ptr_[i] < m.ptr_[i];
}
return false;
}
private:
void Allocate(int required_size) {
size_ = required_size;
if (size_ <= kPreallocatedElements) {
ptr_ = (T*)&array_;
} else {
ptr_ = new T[size_];
}
}
void Validate() {
for (size_t i = 1; i < size(); i++) {
CHECK(ptr_[i-1] <= ptr_[i]);
}
}
T *ptr_;
int size_;
T array_[kPreallocatedElements];
};
#endif // TS_DENSE_MULTIMAP_