fairly cool Array class for c++
Thant Tessman
thant at horus.esd.sgi.com
Fri Mar 1 10:54:38 AEST 1991
Here's an array class folks may or may not find usefull. It is
completely unsupported, comes with no guarantees, and you use it
at your own risk. But I like it. It can hold objects of any size,
it holds them in contiguous memory, and it is type safe. I wrote
it in c++ 2.0 so those using 1.2 or gnu may have to bang on it a
little bit. Enjoy...
#!/bin/sh -v
# this is a shell archive (once) named array.mail
# created by thant at horus at Thu Feb 28 15:48:31 PST 1991
#
# The rest of this file is a shell script which will extract:
# Makefile
# testArray.h
# testArray.c++
# Array.h
# Array.c++
#
# to use, type sh array.mail
#
echo x - Makefile
cat > Makefile << 'EndOfRecord'
#!smake
#
include ${ROOT}/usr/include/make/commondefs
C++FILES = \
testArray.c++ \
Array.c++ \
${NULL}
OPTIMIZER = -g
LDFLAGS = -lgl_s -lm
TARGETS = testArray
all default: ${TARGETS}
include ${ROOT}/usr/include/make/commonrules
${TARGETS}: ${OBJECTS}
${C++F} -o $@ ${OBJECTS} ${LDFLAGS}
EndOfRecord
len=`wc -c < Makefile `
if [ $len != 298 ] ; then
echo error: Makefile was $len bytes long, should have been 298
fi
echo x - testArray.h
cat > testArray.h << 'EndOfRecord'
#pragma once
#include "Array.h"
declareArray(MyArray,char*);
/*
The reason that declareArray() and implementArray() are separate
is that the declareArray() generates a declaration, and like
declarations can appear in many places, which makes it good
for header (.h) files. The implementArray() can only appear
once per list type (usually in a .c++ file).
*/
EndOfRecord
len=`wc -c < testArray.h `
if [ $len != 385 ] ; then
echo error: testArray.h was $len bytes long, should have been 385
fi
echo x - testArray.c++
cat > testArray.c++ << 'EndOfRecord'
#include <stdio.h>
#include <stdlib.h>
#include "testArray.h"
implementArray(MyArray,char*);
MyArray myArray;
main() {
int i;
char* three = "three";
myArray.add("one");
myArray.add("two");
myArray.add(three);
myArray.add("four");
myArray.insert("zero");
printf("\nall:\n");
for (i=0; i<myArray.size(); i++) printf("%s ", myArray[i]);
printf("\n");
printf("\nfound three at %d\n", myArray.find(three));
myArray.remove(1);
myArray.remove(three);
printf("\neven:\n");
for (i=0; i<myArray.size(); i++) printf("%s ", myArray[i]);
printf("\n");
MyArray newArray;
newArray = myArray;
printf("\ncopy of list:\n");
for (i=0; i<myArray.size(); i++) printf("%s ", newArray[i]);
printf("\n\n");
}
EndOfRecord
len=`wc -c < testArray.c++ `
if [ $len != 784 ] ; then
echo error: testArray.c++ was $len bytes long, should have been 784
fi
echo x - Array.h
cat > Array.h << 'EndOfRecord'
#pragma once
// This is what the declaration of a Array looks like to the user:
/*
declareArray(ARRAY,ITEM);
implementArray(ARRAY,ITEM);
struct ARRAY<ITEM> : Array {
ARRAY();
ARRAY(ARRAY&);
virtual ~ARRAY();
void add(ITEM const &item);
void insert(ITEM const &item, int index=0);
void remove(ITEM const &);
void remove(int index);
void removeAll();
int find(ITEM const &);
ITEM& operator[](int index);
ARRAY& operator=(ARRAY&);
int size() {return listsize;};
operator ITEM*();
}
*/
/*
NOTE: There is a bug in the C++ compiler that won't allow 'this'
to be passed by reference. So if you build a list of class
pointers, and you want to pass 'this' to a list member function,
it must be preceeded by &* For example: myArray.insert(&*this);
*/
struct Array {
int size() {return listSize;};
protected:
Array(Array&);
Array();
Array(int elementSize);
virtual ~Array();
void insert(void const *item, int index=0);
void remove(void const *);
void remove(int index);
void removeAll();
Array& operator=(Array&);
struct Address { // will be local to scope eventually
Address() { ptr = 0; }
Address(void* p) { ptr = (char*)p; }
Address operator+(int offset) { return ptr + offset; }
operator void*() { return ptr;}
protected:
char* ptr;
} data;
int listSize;
int elementSize;
private:
void makeRoom(int index);
int room; // >=listSize*elementSize
};
#define declareArray(ARRAY,ITEM) \
\
struct ARRAY : Array { \
ARRAY(); \
ARRAY(ARRAY&); \
~ARRAY(); \
int find(ITEM const &); \
void add(ITEM const &item) { \
ARRAY::insert(item, listSize); \
} \
\
void insert(ITEM const &item, int index=0) { \
Array::insert((void*)(&item), index); \
} \
\
void remove(ITEM const &item) { \
Array::remove((void*)(&item)); \
} \
\
void remove(int index) {Array::remove(index);} \
\
void removeAll() {Array::removeAll();} \
\
ITEM& operator[](int index) { \
return ((ITEM*)((void*)data))[index]; \
} \
\
operator ITEM*() { \
return (ITEM*)((void*)data); \
} \
\
ARRAY& operator=(ARRAY&); \
\
} \
#define implementArray(ARRAY,ITEM) \
\
ARRAY::ARRAY() : Array (sizeof(ITEM)) {} \
ARRAY& ARRAY::operator=(ARRAY& old) { \
return (ARRAY&) Array::operator=(old); \
} \
ARRAY::ARRAY(ARRAY& old) : Array(old) {} \
ARRAY::~ARRAY() {} \
\
int ARRAY::find(ITEM const &item) { \
for (int i=0; i<listSize; i++) { \
if (((ITEM*)((void*)data))[i]==item) return i; \
} \
return(-1); \
} \
\
\
EndOfRecord
len=`wc -c < Array.h `
if [ $len != 2911 ] ; then
echo error: Array.h was $len bytes long, should have been 2911
fi
echo x - Array.c++
cat > Array.c++ << 'EndOfRecord'
#include "Array.h"
#include <stdio.h>
#include <stdlib.h>
#include <libc.h>
Array::Array(int s) {
listSize = 0;
elementSize = s;
data = 0;
room = 0;
}
Array::Array(Array& old) {
listSize = old.listSize;
elementSize = old.elementSize;
room = old.room;
if (room) {
data = malloc(room);
bcopy(old.data, data, listSize*elementSize);
}
}
Array::~Array() {
listSize = 0;
elementSize = 0;
if (data) free(data);
data = NULL;
room = 0;
}
Array& Array::operator=(Array& old) {
listSize = old.listSize;
room = old.room;
if (data) {free(data); data=NULL;}
if (room) {
data = malloc(room);
bcopy(old.data, data, listSize*elementSize);
}
return *this;
}
void Array::insert(void const * item, int index) {
if ((index>listSize) || (index<0)) {
fprintf(stderr, "\nArray::insert(%d) out of bounds. (size: %d)\n",
index, listSize);
abort();
}
if (!listSize) {
room = elementSize;
data = malloc(room);
} else if (((listSize+1)*elementSize) > room) {
room = listSize*2*elementSize;
data = realloc(data, room);
}
if (!data) {
fprintf(stderr, "\nArray::insert(%d) out of memory.\n", index);
abort();
}
if (index<listSize) makeRoom(index);
listSize++;
bcopy(item, data+elementSize*index, elementSize);
}
void Array::remove(int index) {
if ( (index<0) || (index>=listSize) ) {
fprintf(stderr, "\nArray::remove(%d) out of bounds.\n", index);
abort();
}
bcopy(data+elementSize*(index+1),
data+elementSize*index,
(listSize-index-1)*elementSize);
listSize--;
if (listSize*2*elementSize == room) {
room = listSize*elementSize;
if (!room) {free(data); data=NULL;}
else data = realloc(data, room);
}
}
void Array::remove(void const * item) {
for (int i=0; i<elementSize; i++) {
if (!bcmp(item, data+i*elementSize, elementSize)) {
remove(i);
return;
}
}
fprintf(stderr, "\nArray::remove(item) item doesn't exist.\n");
abort();
}
void Array::removeAll() {
listSize=0;
if (data) {free(data); data=NULL;}
room = 0;
}
void Array::makeRoom(int index) {
bcopy(data+elementSize*index,
data+elementSize*(index+1),
(listSize-index)*elementSize);
}
EndOfRecord
len=`wc -c < Array.c++ `
if [ $len != 2272 ] ; then
echo error: Array.c++ was $len bytes long, should have been 2272
fi
More information about the Comp.sys.sgi
mailing list