00001 #ifndef UTIL_FIXED_ARRAY_H
00002 #define UTIL_FIXED_ARRAY_H
00003
00004 #include "util/scoped.hh"
00005
00006 #include <cstddef>
00007
00008 #include <cassert>
00009 #include <cstdlib>
00010
00011 namespace util {
00012
00019 template <class T> class FixedArray {
00020 public:
00022 explicit FixedArray(std::size_t limit) {
00023 Init(limit);
00024 }
00025
00033 FixedArray()
00034 : newed_end_(NULL)
00035 #ifndef NDEBUG
00036 , allocated_end_(NULL)
00037 #endif
00038 {}
00039
00046 void Init(std::size_t count) {
00047 assert(!block_.get());
00048 block_.reset(malloc(sizeof(T) * count));
00049 if (!block_.get()) throw std::bad_alloc();
00050 newed_end_ = begin();
00051 #ifndef NDEBUG
00052 allocated_end_ = begin() + count;
00053 #endif
00054 }
00055
00061 FixedArray(const FixedArray &from) {
00062 std::size_t size = from.newed_end_ - static_cast<const T*>(from.block_.get());
00063 Init(size);
00064 for (std::size_t i = 0; i < size; ++i) {
00065 push_back(from[i]);
00066 }
00067 }
00068
00072 ~FixedArray() { clear(); }
00073
00075 T *begin() { return static_cast<T*>(block_.get()); }
00076
00078 const T *begin() const { return static_cast<const T*>(block_.get()); }
00079
00081 T *end() { return newed_end_; }
00082
00084 const T *end() const { return newed_end_; }
00085
00087 T &back() { return *(end() - 1); }
00088
00090 const T &back() const { return *(end() - 1); }
00091
00093 std::size_t size() const { return end() - begin(); }
00094
00096 bool empty() const { return begin() == end(); }
00097
00103 T &operator[](std::size_t i) {
00104 assert(i < size());
00105 return begin()[i];
00106 }
00107
00113 const T &operator[](std::size_t i) const {
00114 assert(i < size());
00115 return begin()[i];
00116 }
00117
00125 void push_back() {
00126 new (end()) T();
00127 Constructed();
00128 }
00129 template <class C> void push_back(const C &c) {
00130 new (end()) T(c);
00131 Constructed();
00132 }
00133 template <class C> void push_back(C &c) {
00134 new (end()) T(c);
00135 Constructed();
00136 }
00137 template <class C, class D> void push_back(const C &c, const D &d) {
00138 new (end()) T(c, d);
00139 Constructed();
00140 }
00141
00142 void pop_back() {
00143 back().~T();
00144 --newed_end_;
00145 }
00146
00150 void clear() {
00151 while (newed_end_ != begin())
00152 pop_back();
00153 }
00154
00155 protected:
00156
00157 void Constructed() {
00158 ++newed_end_;
00159 #ifndef NDEBUG
00160 assert(newed_end_ <= allocated_end_);
00161 #endif
00162 }
00163
00164 private:
00165 util::scoped_malloc block_;
00166
00167 T *newed_end_;
00168
00169 #ifndef NDEBUG
00170 T *allocated_end_;
00171 #endif
00172 };
00173
00174 }
00175
00176 #endif // UTIL_FIXED_ARRAY_H