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