blob: 31e2db7031ff898f403ec472de1b7b8262720ee9 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TerminatedArrayBuilder_h
#define TerminatedArrayBuilder_h
#include "platform/wtf/Allocator.h"
namespace WTF {
template <typename T, template <typename> class ArrayType = TerminatedArray>
class TerminatedArrayBuilder {
STACK_ALLOCATED();
WTF_MAKE_NONCOPYABLE(TerminatedArrayBuilder);
public:
explicit TerminatedArrayBuilder(
typename ArrayType<T>::Allocator::PassPtr array)
: array_(array), count_(0), capacity_(0) {
if (!array_)
return;
capacity_ = count_ = array_->size();
DCHECK(array_->at(count_ - 1).IsLastInArray());
}
void Grow(size_t count) {
DCHECK(count);
if (!array_) {
DCHECK(!count_);
DCHECK(!capacity_);
capacity_ = count;
array_ = ArrayType<T>::Allocator::Create(capacity_);
} else {
DCHECK(array_->at(count_ - 1).IsLastInArray());
capacity_ += count;
array_ = ArrayType<T>::Allocator::Resize(
ArrayType<T>::Allocator::Release(array_), capacity_);
array_->at(count_ - 1).SetLastInArray(false);
}
array_->at(capacity_ - 1).SetLastInArray(true);
}
void Append(const T& item) {
CHECK_LT(count_, capacity_);
DCHECK(!item.IsLastInArray());
array_->at(count_++) = item;
if (count_ == capacity_)
array_->at(capacity_ - 1).SetLastInArray(true);
}
typename ArrayType<T>::Allocator::PassPtr Release() {
CHECK_EQ(count_, capacity_);
AssertValid();
return ArrayType<T>::Allocator::Release(array_);
}
private:
#if DCHECK_IS_ON()
void AssertValid() {
for (size_t i = 0; i < count_; ++i) {
bool is_last_in_array = (i + 1 == count_);
DCHECK_EQ(array_->at(i).IsLastInArray(), is_last_in_array);
}
}
#else
void AssertValid() {}
#endif
typename ArrayType<T>::Allocator::Ptr array_;
size_t count_;
size_t capacity_;
};
} // namespace WTF
using WTF::TerminatedArrayBuilder;
#endif // TerminatedArrayBuilder_h