containers.h

J

jacob navia

#ifndef __containers_h__
#define __containers_h__
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
/* ------------------------------------------------------------
Default settings: NO_C99 NO_GC
---------------------------------------------------------------*/

#define NO_GC
#define NO_C99

#ifdef NO_C99
/* No stdbool */
typedef int bool;
/* No flexible arrays */
#define MINIMUM_ARRAY_INDEX 1
#else
/* Use C99 features */
#define MINIMUM_ARRAY_INDEX
#include <stdbool.h>
#endif

#ifdef UNIX
#define stricmp strcasecmp
#endif

#ifndef NO_GC
/* A garbage collector makes life easier but is not universally available */
#include <gc.h>
#define MALLOC GC_malloc
#define FREE(a)
#else
/* No GC, use the MALLOC/FREE system. */
#define MALLOC malloc
#define FREE free
#endif


/*
A string collection is a table of zero terminated strings that will grow
automatically when you add elements to it.

As all other containers in this proposal, it uses an interface, i.e. a table
of functions to provide the functionality and data access a string collection
needs. Since the names of the functions are enclosed within the interface
structure we can use mnemonic names like Add, etc, without fear of messing with
the user name space, and without adding lengthy prefixes.

Other advantage of an interface are the extensibility of it. You can add
functions of your own to the interface without interfering with the existing
ones. We will discuss this later when we discuss subclassing, but it is obvious
that you can define a new interface that has the first members as the given
interface, but it has some extra members of your own.

*/

/* We define first an empty structure, that will be fully defined later, to be
able to define the functions in our interface
*/
typedef struct _StringCollection StringCollection;
struct _StringEnumerator;

/* Type definition of the compare function */
typedef int (*CompareFunction)(void *elem1,void *elem2,void *ExtraArgs);
typedef void (*ErrorFunction)(const char *,int);

/* Definition of the functions associated with this type. */
typedef struct {
/* Returns the number of elements stored */
int (*GetCount)(StringCollection *SC);

/* Is this collection read only? */
int (*IsReadOnly)(StringCollection *SC);

/* Sets this collection read-only or unsets the read-only flag */
int (*SetReadOnly)(StringCollection *SC,int flag);

/* Adds one element at the end. Given string is copied */
int (*Add)(StringCollection *SC,char *newval);

/* Adds a NULL terminated table of strings */
int (*AddRange)(StringCollection *SC,char **newvalues);

/* Clears all data and frees the memory */
int (*Clear)(StringCollection *SC);

/*Case sensitive search of a character string in the data */
bool (*Contains)(StringCollection *SC,char *str);

/* Copies all strings into a NULL terminated vector */
char **(*CopyTo)(StringCollection *SC);

/*Returns the index of the given string or -1 if not found */
int (*IndexOf)(StringCollection *SC,char *SearchedString);

/* Inserts a string at the position zero. */
int (*Insert)(StringCollection *SC,char *);

/* Inserts a string at the given position */
int (*InsertAt)(StringCollection *SC,int idx,char *newval);

/* Returns the string at the given position */
char *(*GetElement)(StringCollection *SC,int idx);

/* Removes the given string if found */
int (*Remove)(StringCollection *SC,char *);

/*Removes the string at the indicated position */
int (*RemoveAt)(StringCollection *SC,int idx);

/* Frees the memory used by the collection */
int (*Finalize)(StringCollection *SC);

/* Returns the current capacity of the collection */
int (*GetCapacity)(StringCollection *SC);

/* Sets the capacity if there are no items in the collection */
bool (*SetCapacity)(StringCollection *SC,int newCapacity);

/* Calls the given function for all strings. "Arg" is a used supplied argument */
/* that can be NULL that is passed to the function to call */
void (*Apply)(StringCollection *SC,int (*Applyfn)(char *,void * arg),void *arg);

/* Calls the given function for each string and saves all results
in an integer vector */
int *(*Map)(StringCollection *SC,int (*Applyfn)(char *));

/* Pushes a string, using the collection as a stack */
int (*Push)(StringCollection *SC,char *str);

/* Pops the first (position zero) string off the collection */
char * (*Pop)(StringCollection *SC);

/* Replaces the character string at the given position with a new one */
char *(*ReplaceAt)(StringCollection *SC,int idx,char *newval);

/* Returns whether the collection makes case sensitive comparisons or not */
int (*IsCaseSensitive)(StringCollection *SC);

/* Sets case sensitivity by comparisons */
int (*SetCaseSensitive)(StringCollection *SC,int newval);

/* Compares two string collections */
bool (*Equal)(StringCollection *SC1,StringCollection *SC2);

/* Copy a string collection */
StringCollection *(*Copy)(StringCollection *SC);

/* Set or unset the error function */
ErrorFunction (*SetErrorFunction)(ErrorFunction);

} StringCollectionInterface;
/*
Note that this lengthy structure is not replicated at each string collection
object. Each string collection holds just a pointer to it, spending only
sizeof(void *) bytes.
*/


/* Definition of the String Collection type */
struct _StringCollection {
StringCollectionInterface *lpVtbl; /* The table of functions */
int count; /* in element size units */
char **contents; /* The contents of the collection */
int capacity; /* in element_size units */
unsigned int Flags; /* Read-only or other flags */
/* Error function */
ErrorFunction RaiseError;
};

struct _StringEnumerator;
typedef struct _StringEnumeratorFunctions {
int (*Next)(struct _StringEnumerator *);
int (*Previous)(struct _StringEnumerator *);
char *(*GetCurrent)(struct _StringEnumerator *);
int (*SetCurrent)(struct _StringEnumerator *,int);
}
StringEnumeratorFunctions;

typedef struct _StringEnumerator {
StringEnumeratorFunctions *lpVtbl;
StringCollection SC;
int CurrentIndex;
}
StringEnumerator;

/* This are the only exported functions from this module */
StringCollection *newStringCollection(int startsize);
/* ------------------------------------------------------------------------
* LIST Interface *
* This describes the single linked list data structure functions *
* Each list objects has a list composed of list elemants. *
*-------------------------------------------------------------------------*/
typedef struct _list_element {
struct _list_element *Next;
char Data[MINIMUM_ARRAY_INDEX];
}
list_element;

typedef struct _List List;
typedef struct {
/* Returns the number of elements stored */
int (*GetCount)(List *AL);

/* Is this collection read only? */
int (*IsReadOnly)(List *AL);

/* Sets or unsets this collection read-only flag */
int (*SetReadOnly)(List *AL,int flag);

/* Adds one element at the end. Given element is copied */
int (*Add)(List *AL,void *newval);

/* Clears all data and frees the memory */
int (*Clear)(List *AL);

/*Case sensitive search of a character string in the data */
bool (*Contains)(List *AL,void *str);

/* Copies all items into a new list */
List *(*Copy)(List *AL);

/*Returns the index of the given data or -1 if not found */
int (*IndexOf)(List *AL,void *SearchedElement);

/* Inserts a value at the start of the list (position zero). */
int (*Insert)(List *AL,void *);

/* Inserts a value at the given position */
int (*InsertAt)(List *AL,int idx,void *newval);

/* Returns the data at the given position */
void *(*GetElement)(List *AL,int idx);

/* Removes the given data if found */
int (*Remove)(List *AL,void *);

/*Removes the string at the indicated position */
int (*RemoveAt)(List *AL,int idx);

/* Frees the memory used by the collection and destroys the list */
int (*Finalize)(List *AL);

/* Pushes a string, using the collection as a stack */
int (*Push)(List *AL,void *str);

/* Pops the first element the list */
list_element * (*Pop)(List *AL);

/* Replaces the element at the given position with a new one */
void *(*ReplaceAt)(List *AL,int idx,void *newval);

/* Sorts the list */
List *(*Sort)(List *l,int (*compar)(const void *,const void *));

/* Reverses the list */
List *(*Reverse)(List *l);

/* Gets an element range from the list */
List *(*GetRange)(List *l,int start,int end);

/* Compares two lists (Shallow comparison) */
bool (*Equal)(List *l1,List *l2);

/* Add a list at the end of another */
List *(*Append)(List *l1,List *l2);

/* Set The comparison function */
CompareFunction (*SetCompareFunction)(List *l,CompareFunction fn);

/* Call a callback function with each element of the list and an extra argument */
void (*Apply)(List *L,int(Applyfn)(void *,void *),void *arg);

/* Set or unset the error function */
ErrorFunction (*SetErrorFunction)(List *L,ErrorFunction);

}
ListInterface;

struct _List {
ListInterface *lpVtbl;
size_t ElementSize;
int count; /* in elements units */
list_element *Last; /* The last item */
list_element *First; /* The contents of the list start here */
unsigned Flags;
/* Element comparison function */
int (*CompareFn)(void * elem1, void *elem2, void *ExtraArgs);
/* Error function */
ErrorFunction RaiseError;
};
List *newList(int element_size);
/*-------------------------------------------------------------------------
* inline functions
*------------------------------------------------------------------------*/
#ifdef NO_C99
/* No inline keyword, use macros instead */
#define GetFirst(list) list->First
#define GetNext(list_elem) list_elem->Next
#define GetLast(list) list->Last
#else
inline list_element * GetFirst(List *l){ return l->First; }
inline list_element * GetNext(list_element *l){ return l->Next; }
inline list_element * GetLast(List *l){ return l->Last; }
#endif

/*****************************************************************************
* *
* The array list *
* We have now a general framework for handling string collections. Looking
* at the code, it is easy to see that with a little effort, we could make
* this much more general if we would replace the strings with a fixed size
* object, that can be any data structure. This general container is present
* in other languages like C#, where it is called ArrayList. You can store
* in an ArrayList anything, in C# it is not even required that the objects
* stored inside should be of the same type.

* Since the nature of the objects stored is not known to the container,
* it is necessary to cast the result of an ArrayList into the final type
* that the user knows it is in there. In C# this is the object, the root
* of the object hierarchy, in C it is the void pointer, a pointer that can
* point to any kind of object.

* If we look at the code of one of the string collection functions we can
* see the following:
* static char *IndexAt(struct _StringCollection *SC,int idx)
* {
* if (idx >=SC->count || idx < 0)
* return NULL;
* return SC->contents[idx];
* }

* We can easily generalize this to a container by changing the char pointer
* result declaration to just a void pointer.

****************************************************************************/

/* Forward declaration of the string collection type */
typedef struct _ArrayList ArrayList;

/* Definition of the functions associated with this type. */
typedef struct {
/* Returns the number of elements stored */
int (*GetCount)(ArrayList *AL);

/* Is this collection read only? */
int (*IsReadOnly)(ArrayList *AL);

/* Sets this collection read-only or unsets the read-only flag */
int (*SetReadOnly)(ArrayList *AL,int flag);

/* Adds one element at the end. Given element is copied */
int (*Add)(ArrayList *AL,void *newval);

/* Adds a NULL terminated table of strings */
int (*AddRange)(ArrayList *AL,void **newvalues);

/* Clears all data and frees the memory */
int (*Clear)(ArrayList *AL);

/*Case sensitive search of a character string in the data */
bool (*Contains)(ArrayList *AL,void *str);

/* Copies all strings into a NULL terminated vector */
void **(*CopyTo)(ArrayList *AL);

/*Returns the index of the given string or -1 if not found */
int (*IndexOf)(ArrayList *AL,void *SearchedString);

/* Inserts a string at the position zero. */
int (*Insert)(ArrayList *AL,void *);

/* Inserts a string at the given position */
int (*InsertAt)(ArrayList *AL,int idx,void *newval);

/* Returns the string at the given position */
void *(*GetElement)(ArrayList *AL,int idx);

/* Removes the given string if found */
int (*Remove)(ArrayList *AL,void *);

/*Removes the string at the indicated position */
int (*RemoveAt)(ArrayList *AL,int idx);

/* Frees the memory used by the collection */
int (*Finalize)(ArrayList *AL);

/* Returns the current capacity of the collection */
int (*GetCapacity)(ArrayList *AL);

/* Sets the capacity if there are no items in the collection */
bool (*SetCapacity)(ArrayList *AL,int newCapacity);

/* Calls the given function for all strings in the given collection.
"Arg" is a user supplied argument (can be NULL) that is passed
to the function to call */
void (*Apply)(ArrayList *AL,int (*Applyfn)(void *,void * arg),void *arg);

/* Pushes a string, using the collection as a stack */
int (*Push)(ArrayList *AL,void *str);

/* Pops the last string off the collection */
void * (*Pop)(ArrayList *AL);

/* Replaces the character string at the given position with a new one */
void *(*ReplaceAt)(ArrayList *AL,int idx,void *newval);

ErrorFunction (*SetErrorFunction)(ArrayList *AL,ErrorFunction);

} ArrayListInterface;

/* Definition of the String Collection type */
struct _ArrayList {
ArrayListInterface *lpVtbl; /* The table of functions */
int count; /* number of elements in the array */
void **contents; /* The contents of the collection */
int capacity; /* allocated space in the contents vector */
unsigned int Flags; /* Read-only or other flags */
size_t ElementSize; /* Size of the elements stored in this array. */
/* Element comparison function */
int (*CompareFn)(void * elem1, void *elem2, void *ExtraArgs);
/* Error function */
ErrorFunction RaiseError;


} ;

/* This are the only exported functions from this module */
ArrayList *newArrayList(size_t elementsize,int startsize);
/************************************************************************** */
/* */
/* ErrorHandling */
/* */
/************************************************************************** */
#define CONTAINER_ERROR_BADARG (0x80070057)
#define CONTAINER_ERROR_NOMEMORY (0x8007000E)
#define CONTAINER_ERROR_INDEX -3
#define CONTAINER_ERROR_READONLY -4
#define CONTAINER_ERROR_FILEOPEN -5
#define CONTAINER_ERROR_NOTFOUND -6
void ContainerRaiseError(const char *fnname,int errorcode);
void EmptyErrorFunction(const char *fnname,int errcode);
#endif
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top