/*
- * $Id: Array.h,v 1.8 2002/10/25 03:13:51 robertc Exp $
+ * $Id: Array.h,v 1.9 2003/01/18 14:06:33 robertc Exp $
*
* AUTHOR: Alex Rousskov
*
#define SQUID_ARRAY_H
/* see Array.c for more documentation */
-
+#ifndef __cplusplus
typedef struct {
int capacity;
int count;
void **items;
} Array;
+#endif
+
+#ifdef __cplusplus
+
+/* iterator support */
+template <class C> 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;
+ typename C::value_type * operator -> () const;
+ ssize_t operator - (VectorIteratorBase const &rhs) const;
+ bool incrementable() const;
+ private:
+ size_t pos;
+ C * theVector;
+};
+
+template<class E>
+class Vector {
+public:
+ typedef E value_type;
+ typedef E* pointer;
+ typedef VectorIteratorBase<Vector<E> > iterator;
+ typedef VectorIteratorBase<Vector<E> 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);
+ E &back();
+ E pop_back();
+ void preAppend(int app_count);
+ bool empty() const;
+ size_t size() const;
+ iterator begin();
+ const_iterator begin () const;
+ iterator end();
+ const_iterator end () const;
+
+ size_t capacity;
+ size_t count;
+ E *items;
+};
+typedef Vector<void *> Array;
+
+#endif
SQUIDCEXTERN Array *arrayCreate(void);
SQUIDCEXTERN void arrayInit(Array * s);
SQUIDCEXTERN void arrayAppend(Array * s, void *obj);
SQUIDCEXTERN void arrayPreAppend(Array * s, int app_count);
+#ifdef __cplusplus
+
+template<class E>
+void *
+Vector<E>::operator new(size_t size)
+{
+ return xmalloc (size);
+}
+
+template<class E>
+void
+Vector<E>::operator delete (void *address)
+{
+ xfree (address);
+}
+
+template<class E>
+Vector<E>::Vector() : capacity (0), count(0), items (NULL)
+{
+}
+
+template<class E>
+Vector<E>::~Vector()
+{
+ clean();
+}
+
+template<class E>
+void
+Vector<E>::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<class E>
+void
+Vector<E>::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<class E>
+void
+Vector<E>::push_back(E obj)
+{
+ if (size() >= capacity)
+ reserve (size() + 1);
+ items[count++] = obj;
+}
+
+template<class E>
+E
+Vector<E>::pop_back()
+{
+ assert (size());
+ value_type result = items[--count];
+ items[count] = value_type();
+ return result;
+}
+
+template<class E>
+E &
+Vector<E>::back()
+{
+ assert (size());
+ return items[size() - 1];
+}
+
+/* if you are going to append a known and large number of items, call this first */
+template<class E>
+void
+Vector<E>::preAppend(int app_count)
+{
+ if (size() + app_count > capacity)
+ reserve(size() + app_count);
+}
+
+template<class E>
+Vector<E> &
+Vector<E>::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<class E>
+bool
+Vector<E>::empty() const
+{
+ return size() == 0;
+}
+
+template<class E>
+size_t
+Vector<E>::size() const
+{
+ return count;
+}
+
+template<class E>
+Vector<E>::iterator
+Vector<E>::begin()
+{
+ return iterator (0, *this);
+}
+
+template<class E>
+Vector<E>::iterator
+Vector<E>::end()
+{
+ return iterator(size(), *this);
+}
+
+template<class E>
+Vector<E>::const_iterator
+Vector<E>::begin() const
+{
+ return const_iterator (0, *this);
+}
+
+template<class E>
+Vector<E>::const_iterator
+Vector<E>::end() const
+{
+ return const_iterator(size(), *this);
+}
+
+
+template<class C>
+VectorIteratorBase<C>::VectorIteratorBase() : pos(0), theVector(NULL)
+{
+}
+
+template<class C>
+VectorIteratorBase<C>::VectorIteratorBase(C &container) : pos(container.begin()), theVector(&container)
+{
+}
+
+template<class C>
+VectorIteratorBase<C>::VectorIteratorBase(size_t aPos, C &container) : pos(aPos), theVector(&container) {}
+
+template<class C>
+bool VectorIteratorBase<C>:: operator != (VectorIteratorBase const &rhs)
+{
+ assert (theVector);
+ return pos != rhs.pos;
+}
+
+template<class C>
+bool VectorIteratorBase<C>:: operator == (VectorIteratorBase const &rhs)
+{
+ assert (theVector);
+ return pos == rhs.pos;
+}
+
+template<class C>
+bool
+VectorIteratorBase<C>::incrementable() const
+{
+ assert (theVector);
+ return pos != theVector->size();
+}
+
+template<class C>
+VectorIteratorBase<C> & VectorIteratorBase<C>:: operator ++()
+{
+ assert (theVector);
+ if (!incrementable())
+ fatal ("domain error");
+ ++pos;
+ return *this;
+}
+
+template<class C>
+VectorIteratorBase<C> VectorIteratorBase<C>:: operator ++(int)
+{
+ VectorIteratorBase result(*this);
+ ++*this;
+ return result;
+}
+
+template<class C>
+typename C::value_type & VectorIteratorBase<C>::operator *() const
+{
+ return theVector->items[pos];
+}
+
+template<class C>
+typename C::value_type * VectorIteratorBase<C>::operator -> () const
+{
+ return &theVector->items[pos];
+}
+
+template<class C>
+VectorIteratorBase<C>&
+VectorIteratorBase<C>::operator =(VectorIteratorBase const &old) {
+ pos = old.pos;
+ theVector = old.theVector;
+ return *this;
+}
+
+template<class C>
+ssize_t
+VectorIteratorBase<C>::operator - (VectorIteratorBase const &rhs) const
+{
+ assert(theVector == rhs.theVector);
+ return pos - rhs.pos;
+}
+#endif
#endif /* SQUID_ARRAY_H */
/*
- * $Id: Array.cc,v 1.8 2003/01/18 04:50:39 robertc Exp $
+ * $Id: Array.cc,v 1.9 2003/01/18 14:06:32 robertc Exp $
*
* AUTHOR: Alex Rousskov
*
#include "util.h"
#include "Array.h"
-static void arrayGrow(Array * a, int min_capacity);
-
-Array *
-arrayCreate(void)
-{
- Array *a = new Array;
- arrayInit(a);
- return a;
-}
+Array *arrayCreate(void) {return new Array;}
+void arrayClean(Array * s) {s->clean();}
+void arrayDestroy(Array * s) { delete s;}
+void arrayAppend(Array * s, void *obj) {s->push_back(obj);}
+void arrayPreAppend(Array * s, int app_count) {s->preAppend(app_count);}
void
arrayInit(Array * a)
assert(a);
memset(a, 0, sizeof(Array));
}
-
-void
-arrayClean(Array * a)
-{
- assert(a);
- /* could also warn if some objects are left */
- xfree(a->items);
- a->items = NULL;
-}
-
-void
-arrayDestroy(Array * a)
-{
- assert(a);
- arrayClean(a);
- delete a;
-}
-
-void
-arrayAppend(Array * a, void *obj)
-{
- assert(a);
- if (a->count >= a->capacity)
- arrayGrow(a, a->count + 1);
- a->items[a->count++] = obj;
-}
-
-/* if you are going to append a known and large number of items, call this first */
-void
-arrayPreAppend(Array * a, int app_count)
-{
- assert(a);
- if (a->count + app_count > a->capacity)
- arrayGrow(a, a->count + app_count);
-}
-
-/* grows internal buffer to satisfy required minimal capacity */
-static void
-arrayGrow(Array * a, int min_capacity)
-{
- const int min_delta = 16;
- int delta;
- assert(a->capacity < min_capacity);
- delta = min_capacity;
- /* make delta a multiple of min_delta */
- delta += min_delta - 1;
- delta /= min_delta;
- delta *= min_delta;
- /* actual grow */
- assert(delta > 0);
- a->capacity += delta;
- a->items = (void **) (a->items ?
- xrealloc(a->items, a->capacity * sizeof(void *)) :
- xmalloc(a->capacity * sizeof(void *)));
- /* reset, just in case */
- memset(a->items + a->count, 0, (a->capacity - a->count) * sizeof(void *));
-}