blob: 6bc38007cb3167162fc7c1dd05dab8b231d6a70e [file] [log] [blame]
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef NB_REWINDABLE_VECTOR_CAST_H_
#define NB_REWINDABLE_VECTOR_CAST_H_
#include <vector>
#include "starboard/common/log.h"
namespace nb {
// Like an std::vector, but supports an additional rewind operation. rewind()
// is like a light-weight clear() operation which does not destroy contained
// objects.
// This is important for performance where the same elements need to be
// re-used. For example, a vector of structs which contain std::strings in
// which it's more desirable for the strings are re-assigned rather than
// destroyed and then re-constructed through rewind() / grow().
//
// Object destruction occurs on clear() or container destruction.
//
// Example:
// RewindableVector<std::string> values;
// values.push_back("ABCDEF");
// values.rewindAll(); // string at [0] is unchanged.
// EXPECT_EQ(0, values.size());
// values.expand(1); // string at [0] is unchanged.
// values[0].assign("ABC"); // string is re-assigned, no memory allocated.
template <typename T, typename VectorT = std::vector<T> >
class RewindableVector {
public:
RewindableVector() : size_(0) {}
const T& operator[](size_t i) const { return at(i); }
T& operator[](size_t i) { return at(i); }
const T& at(size_t i) const {
SB_DCHECK(i < size_);
return vector_[i];
}
T& at(size_t i) {
SB_DCHECK(i < size_);
return vector_[i];
}
bool empty() const { return size() == 0; }
size_t size() const { return size_; }
void clear() {
vector_.clear();
size_ = 0;
}
void rewindAll() { size_ = 0; }
void rewind(size_t i) {
if (i <= size_) {
size_ -= i;
} else {
SB_NOTREACHED() << "underflow condition.";
rewindAll();
}
}
// Grows the array by n values. The new last element is returned.
T& grow(size_t n) {
size_ += n;
if (size_ > vector_.size()) {
vector_.resize(size_);
}
return back();
}
T& back() { return vector_[size_ - 1]; }
void pop_back() { rewind(1); }
void push_back(const T& v) {
if (size_ == vector_.size()) {
vector_.push_back(v);
} else {
vector_[size_] = v;
}
++size_;
}
VectorT& InternalData() { return vector_; }
private:
VectorT vector_;
size_t size_;
};
} // namespace nb
#endif // NB_REWINDABLE_VECTOR_CAST_H_