/* * $Id$ * * AUTHOR: Alex Rousskov * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from * the Internet community; see the CONTRIBUTORS file for full * details. Many organizations have provided support for Squid's * development; see the SPONSORS file for full details. Squid is * Copyrighted (C) 2001 by the Regents of the University of * California; see the COPYRIGHT file for full details. Squid * incorporates software developed and/or copyrighted by other * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #ifndef SQUID_ARRAY_H #define SQUID_ARRAY_H /** \todo CLEANUP: this file should be called Vector.h at least, and probably be replaced by STL Vector */ #include "fatal.h" #include "util.h" /* users of this template also need assert() */ #include "compat/assert.h" /* iterator support */ template class VectorIteratorBase { public: VectorIteratorBase(); VectorIteratorBase(C &); VectorIteratorBase(size_t, C &); VectorIteratorBase & operator =(VectorIteratorBase const &); bool operator != (VectorIteratorBase const &rhs); bool operator == (VectorIteratorBase const &rhs); VectorIteratorBase & operator ++(); VectorIteratorBase operator ++(int); typename C::value_type & operator *() const { return theVector->items[pos]; } typename C::value_type * operator -> () const { return &theVector->items[pos]; } ssize_t operator - (VectorIteratorBase const &rhs) const; bool incrementable() const; private: size_t pos; C * theVector; }; template class Vector { public: typedef E value_type; typedef E* pointer; typedef VectorIteratorBase > iterator; typedef VectorIteratorBase const> const_iterator; void *operator new (size_t); void operator delete (void *); Vector(); ~Vector(); Vector(Vector const &); Vector &operator = (Vector const &); void clean(); void reserve (size_t capacity); void push_back (E); Vector &operator += (E item) {push_back(item); return *this;}; void insert (E); const E &front() const; E &front(); E &back(); E pop_back(); E shift(); // aka pop_front void prune(E); void preAppend(int app_count); bool empty() const; size_t size() const; iterator begin(); const_iterator begin () const; iterator end(); const_iterator end () const; E& operator [] (unsigned i); const E& operator [] (unsigned i) const; /* Do not change these, until the entry C struct is removed */ size_t capacity; size_t count; E *items; }; template void * Vector::operator new(size_t size) { return xmalloc(size); } template void Vector::operator delete (void *address) { xfree (address); } template Vector::Vector() : capacity (0), count(0), items (NULL) {} template Vector::~Vector() { clean(); } template void Vector::clean() { /* could also warn if some objects are left */ delete[] items; items = NULL; capacity = 0; count = 0; } /* grows internal buffer to satisfy required minimal capacity */ template void Vector::reserve(size_t min_capacity) { const int min_delta = 16; int delta; if (capacity >= min_capacity) return; delta = min_capacity; /* make delta a multiple of min_delta */ delta += min_delta - 1; delta /= min_delta; delta *= min_delta; /* actual grow */ if (delta < 0) delta = min_capacity - capacity; E*newitems = new E[capacity + delta]; for (size_t counter = 0; counter < size(); ++counter) { newitems[counter] = items[counter]; } capacity += delta; delete[]items; items = newitems; } template void Vector::push_back(E obj) { if (size() >= capacity) reserve (size() + 1); items[count++] = obj; } template void Vector::insert(E obj) { if (size() >= capacity) reserve (size() + 1); int i; for (i = count; i > 0; i--) items[i] = items[i - 1]; items[i] = obj; count += 1; } template E Vector::shift() { assert (size()); value_type result = items[0]; for (unsigned int i = 1; i < count; i++) items[i-1] = items[i]; count--; /*reset the last (unused) element...*/ items[count] = value_type(); return result; } template E Vector::pop_back() { assert (size()); value_type result = items[--count]; items[count] = value_type(); return result; } template E & Vector::back() { assert (size()); return items[size() - 1]; } template const E & Vector::front() const { assert (size()); return items[0]; } template E & Vector::front() { assert (size()); return items[0]; } template void Vector::prune(E item) { unsigned int n = 0; for (unsigned int i = 0; i < count; i++) { if (items[i] != item) { if (i != n) items[n] = items[i]; n++; } } count = n; } /* if you are going to append a known and large number of items, call this first */ template void Vector::preAppend(int app_count) { if (size() + app_count > capacity) reserve(size() + app_count); } template Vector::Vector (Vector const &rhs) { items = NULL; capacity = 0; count = 0; reserve (rhs.size()); for (size_t counter = 0; counter < rhs.size(); ++counter) push_back (rhs.items[counter]); } template Vector & Vector::operator = (Vector const &old) { clean(); reserve (old.size()); for (size_t counter = 0; counter < old.size(); ++counter) push_back (old.items[counter]); return *this; } template bool Vector::empty() const { return size() == 0; } template size_t Vector::size() const { return count; } template typename Vector::iterator Vector::begin() { return iterator (0, *this); } template typename Vector::iterator Vector::end() { return iterator(size(), *this); } template typename Vector::const_iterator Vector::begin() const { return const_iterator (0, *this); } template typename Vector::const_iterator Vector::end() const { return const_iterator(size(), *this); } template E & Vector::operator [] (unsigned i) { assert (size() > i); return items[i]; } template const E & Vector::operator [] (unsigned i) const { assert (size() > i); return items[i]; } template VectorIteratorBase::VectorIteratorBase() : pos(0), theVector(NULL) {} template VectorIteratorBase::VectorIteratorBase(C &container) : pos(container.begin()), theVector(&container) {} template VectorIteratorBase::VectorIteratorBase(size_t aPos, C &container) : pos(aPos), theVector(&container) {} template bool VectorIteratorBase:: operator != (VectorIteratorBase const &rhs) { assert (theVector); return pos != rhs.pos; } template bool VectorIteratorBase:: operator == (VectorIteratorBase const &rhs) { assert (theVector); return pos == rhs.pos; } template bool VectorIteratorBase::incrementable() const { assert (theVector); return pos != theVector->size(); } template VectorIteratorBase & VectorIteratorBase:: operator ++() { assert (theVector); if (!incrementable()) fatal ("domain error"); ++pos; return *this; } template VectorIteratorBase VectorIteratorBase:: operator ++(int) { VectorIteratorBase result(*this); ++*this; return result; } template VectorIteratorBase& VectorIteratorBase::operator =(VectorIteratorBase const &old) { pos = old.pos; theVector = old.theVector; return *this; } template ssize_t VectorIteratorBase::operator - (VectorIteratorBase const &rhs) const { assert(theVector == rhs.theVector); return pos - rhs.pos; } #endif /* SQUID_ARRAY_H */