Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > A container library in C. Part 1: Header file

Reply
Thread Tools

A container library in C. Part 1: Header file

 
 
jacob navia
Guest
Posts: n/a
 
      09-28-2009
This is the first part of this posting. This is the header file
containers.h
--------------------------------------------------------cut here

#ifndef __containers_h__
#define __containers_h__
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdbool.h>
/*
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);

// 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 *(*IndexAt)(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 last 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);
} 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
};

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);
#if 0
char *operator[](StringCollection *,int);
char *operator[]=(StringCollection SC,int idx,char *newval);
#endif
/* ------------------------------------------------------------------------
* 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[];
} 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 this collection read-only or unsets the 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 strings into a NULL terminated vector
List (*Copy)(List AL);

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

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

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

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

// Removes the given string 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
int (*Finalize)(List AL);

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

// Pops the last string off the list
list_element * (*Pop)(List AL);

// Replaces the character string 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 list (Shallow comparison)
bool (*Equal)(List l1,List l2);

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

// Comparison function
int (*CompareFn)(void * elem1, void *elem2);

// Set The comparison function
CompareFunction (*SetCompareFunction)(List l,CompareFunction fn);
} 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;
};
List newList(int element_size);
#if 0
list_element * operator[]=(List &l,size_t position,void *data);
list_element * operator[](List &l,int position);
#endif
/*-------------------------------------------------------------------------
* inline functions

*------------------------------------------------------------------------*/
list_element *inline GetFirst(List *l)
{
return l->First;
}
list_element * inline GetNext(list_element *l)
{
return l->Next;
}

list_element * inline GetLast(List *l)
{
return l->Last;
}

/************************************************** ***************************
*
*
* 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 *(*IndexAt)(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. "Arg" is a used supplied
argument
// that 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);

} 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.
};

// This are the only exported functions from this module
ArrayList newArrayList(size_t elementsize,int startsize);
#if 0
void *operator[](ArrayList AL,int idx);
void *operator[]=(ArrayList AL,int idx,void *newval);
#endif
//************************************************** ****************************
//
// 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
void ContainerRaiseError(char *fnname,unsigned errorcode);
#endif
 
Reply With Quote
 
 
 
 
David RF
Guest
Posts: n/a
 
      09-28-2009
On 28 sep, 12:04, jacob navia <(E-Mail Removed)> wrote:
[...]

Hi Jacob,

1.
With gcc ...

david@debian:~$ gcc -std=c89 -o demo demo.c
demo.c:36: error: expected identifier or ‘(’ before ‘/’ token
demo.c:39: error: expected identifier or ‘(’ before ‘/’ token
demo.c:120: warning: data definition has no type or storage class
demo.c:128: error: expected identifier or ‘(’ before ‘/’ token
demo.c:149: error: field ‘SC’ has incomplete type
demo.c:154: error: expected identifier or ‘(’ before ‘/’ token
demo.c:177: error: expected specifier-qualifier-list before ‘/’ token
demo.c:270: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’
before ‘GetFirst’
demo.c:275: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’
before ‘GetNext’
demo.c:281: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’
before ‘GetLast’
demo.c:329: error: expected identifier or ‘(’ before ‘/’ token
demo.c:332: error: expected identifier or ‘(’ before ‘/’ token
demo.c:398: warning: data definition has no type or storage class
demo.c:400: error: expected identifier or ‘(’ before ‘/’ token
demo.c:412: error: expected identifier or ‘(’ before ‘/’ token
demo.c:418: error: expected identifier or ‘(’ before ‘/’ token
demo.c:418:2: error: unterminated comment
demo.c:1:1: error: unterminated #ifndef

david@debian:~$ gcc -std=c99 -o demo demo.c
demo.c:270: error: expected identifier or ‘(’ before ‘inline’
demo.c:275: error: expected identifier or ‘(’ before ‘inline’
demo.c:281: error: expected identifier or ‘(’ before ‘inline’

sugest
inline list_element *GetFirst(List *l)
inline list_element *GetNext(list_element *l)
inline list_element *GetLast(List *l)
instead of
list_element *inline GetFirst(List *l)
list_element * inline GetNext(list_element *l)
list_element * inline GetLast(List *l)


2.
#ifndef __containers_h__
struct _List {
....
An initial underscore should not be used for any user-created names
 
Reply With Quote
 
 
 
 
jacob navia
Guest
Posts: n/a
 
      09-28-2009
David RF a ιcrit :
> On 28 sep, 12:04, jacob navia <(E-Mail Removed)> wrote:
> [...]
>
> Hi Jacob,
>
> 1.
> With gcc ...
>
> david@debian:~$ gcc -std=c89 -o demo demo.c
> demo.c:36: error: expected identifier or ‘(’ before ‘/’ token
> demo.c:39: error: expected identifier or ‘(’ before ‘/’ token
> demo.c:120: warning: data definition has no type or storage class
> demo.c:128: error: expected identifier or ‘(’ before ‘/’ token
> demo.c:149: error: field ‘SC’ has incomplete type
> demo.c:154: error: expected identifier or ‘(’ before ‘/’ token
> demo.c:177: error: expected specifier-qualifier-list before ‘/’ token
> demo.c:270: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’
> before ‘GetFirst’
> demo.c:275: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’
> before ‘GetNext’
> demo.c:281: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’
> before ‘GetLast’
> demo.c:329: error: expected identifier or ‘(’ before ‘/’ token
> demo.c:332: error: expected identifier or ‘(’ before ‘/’ token
> demo.c:398: warning: data definition has no type or storage class
> demo.c:400: error: expected identifier or ‘(’ before ‘/’ token
> demo.c:412: error: expected identifier or ‘(’ before ‘/’ token
> demo.c:418: error: expected identifier or ‘(’ before ‘/’ token
> demo.c:418:2: error: unterminated comment
> demo.c:1:1: error: unterminated #ifndef


The program is written in standard C. Please use a standard C compiler.

>
> david@debian:~$ gcc -std=c99 -o demo demo.c

^^^^^^^^

better



> demo.c:270: error: expected identifier or ‘(’ before ‘inline’
> demo.c:275: error: expected identifier or ‘(’ before ‘inline’
> demo.c:281: error: expected identifier or ‘(’ before ‘inline’
>


OK, lcc-win accepts inline as written. It should be changed, I did not realize that.

> sugest
> inline list_element *GetFirst(List *l)
> inline list_element *GetNext(list_element *l)
> inline list_element *GetLast(List *l)
> instead of
> list_element *inline GetFirst(List *l)
> list_element * inline GetNext(list_element *l)
> list_element * inline GetLast(List *l)
>
>


OK


> 2.
> #ifndef __containers_h__
> struct _List {
> ...
> An initial underscore should not be used for any user-created names


That is why the underscore is there!
To avoid using the user's name space. Remember, the container library should be
part of the implementation.
 
Reply With Quote
 
bartc
Guest
Posts: n/a
 
      09-28-2009

"jacob navia" <(E-Mail Removed)> wrote in message
news:h9q6v1$1l3$(E-Mail Removed)...
> David RF a ιcrit :


> The program is written in standard C. Please use a standard C compiler.
>
>>
>> david@debian:~$ gcc -std=c99 -o demo demo.c

> ^^^^^^^^
>
> better
>
>
>
>> demo.c:270: error: expected identifier or ‘(’ before ‘inline’
>> demo.c:275: error: expected identifier or ‘(’ before ‘inline’
>> demo.c:281: error: expected identifier or ‘(’ before ‘inline’
>>

>
> OK, lcc-win accepts inline as written. It should be changed, I did not
> realize that.


Have you ever thought of trying this stuff with other compilers? Just for a
second opinion?

My first problems were with the // comments wrapping (it would convenient to
wrap-proof such comments, for serious bits of code like this, by converting
//.... to /*....*/, as such problems are not going to improve the
dispositions of any critics)

Then my gcc (3.4.5 mingw) didn't like the function declarations (with or
without the c99 switch), saying "warning: parameter has incomplete type",
starting from line 42 (obviously).

--
Bartc

 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      09-28-2009
Sorry, I have mixed up things when transferring to the
email sofwtare. Here is an updated version, compatible with gcc

#ifndef __containers_h__
#define __containers_h__
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#ifndef __LCC__
#define NO_GC
#define bool int
#define true 1
#define false 0
#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);

// 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 *(*IndexAt)(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 last 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);
} 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
};

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);
#if 0
char *operator[](StringCollection *,int);
char *operator[]=(StringCollection SC,int idx,char *newval);
#endif
/* ------------------------------------------------------------------------
* 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[];
} 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 this collection read-only or unsets the 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 strings into a NULL terminated vector
List (*Copy)(List AL);

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

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

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

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

// Removes the given string 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
int (*Finalize)(List AL);

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

// Pops the last string off the list
list_element * (*Pop)(List AL);

// Replaces the character string 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 list (Shallow comparison)
bool (*Equal)(List l1,List l2);

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

// Comparison function
int (*CompareFn)(void * elem1, void *elem2);

// Set The comparison function
CompareFunction (*SetCompareFunction)(List l,CompareFunction fn);
} 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;
};
List newList(int element_size);
#if 0
list_element * operator[]=(List &l,size_t position,void *data);
list_element * operator[](List &l,int position);
#endif
/*-------------------------------------------------------------------------
* inline functions
*------------------------------------------------------------------------*/
#ifdef _MSC
#define inline static
#endif
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;
}

/************************************************** ***************************
* *
* 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 *(*IndexAt)(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. "Arg" is a used supplied argument
// that 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);

} 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.
};

// This are the only exported functions from this module
ArrayList newArrayList(size_t elementsize,int startsize);
#if 0
void *operator[](ArrayList AL,int idx);
void *operator[]=(ArrayList AL,int idx,void *newval);
#endif
//************************************************** ****************************
//
// 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
void ContainerRaiseError(char *fnname,unsigned errorcode);
#endif
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      09-28-2009
jacob navia <(E-Mail Removed)> writes:

> Sorry, I have mixed up things when transferring to the
> email sofwtare. Here is an updated version, compatible with gcc


Apart from a number of spacing changes the only difference i can see
(that applies to non-MSC implementations) is:

6c6,11
< #include <stdbool.h>
---
> #ifndef __LCC__
> #define NO_GC
> #define bool int
> #define true 1
> #define false 0
> #endif


Why replace a standard header with something code that breaks any
program that wants to use stdbool?

The use of NO_GC suggests that it is optional, but I can't see where
anything gets freed. The choice seems to be between GC and a space
leak.

Can you post a main function that uses your list code because I still
can't see how it could do anything at all (Lists, rather than List *s,
seem to be passed to all the functions)?

<snip>
--
Ben.
 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      09-28-2009
On Mon, 28 Sep 2009 12:04:35 +0200, jacob navia <(E-Mail Removed)>
wrote:

>This is the first part of this posting. This is the header file
>containers.h
>--------------------------------------------------------cut here
>
>#ifndef __containers_h__
>#define __containers_h__


snip

>typedef struct _StringCollection StringCollection;
>struct _StringEnumerator;


Is there some reason you chose to invade the implementation name
space?

--
Remove del for email
 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      09-29-2009
On Mon, 28 Sep 2009 17:41:09 +0000, Richard Heathfield
<(E-Mail Removed)> wrote:

>In <(E-Mail Removed)>, Barry Schwarz wrote:
>
>> On Mon, 28 Sep 2009 12:04:35 +0200, jacob navia <(E-Mail Removed)>
>> wrote:
>>

><snip>
>>
>>>typedef struct _StringCollection StringCollection;
>>>struct _StringEnumerator;

>>
>> Is there some reason you chose to invade the implementation name
>> space?

>
>He is an *implementor*, proposing a new *implementation* feature. He
>is therefore quite within his rights to use the implementation
>namespace. Of course, he runs the risk of clashing with other
>implementations, but I don't see a way around that.


Everyone who writes code is an implementer.

There is no indication this was proposed to become a standard header
and part of the standard run-time library or built into the
compiler/linker. Paragraph 7.1.3 reserves these names for use in that
context.

--
Remove del for email
 
Reply With Quote
 
bartc
Guest
Posts: n/a
 
      09-29-2009

"Barry Schwarz" <(E-Mail Removed)> wrote in message
news(E-Mail Removed)...
> On Mon, 28 Sep 2009 17:41:09 +0000, Richard Heathfield
> <(E-Mail Removed)> wrote:
>
>>In <(E-Mail Removed)>, Barry Schwarz wrote:
>>
>>> On Mon, 28 Sep 2009 12:04:35 +0200, jacob navia <(E-Mail Removed)>
>>> wrote:
>>>

>><snip>
>>>
>>>>typedef struct _StringCollection StringCollection;
>>>>struct _StringEnumerator;
>>>
>>> Is there some reason you chose to invade the implementation name
>>> space?

>>
>>He is an *implementor*, proposing a new *implementation* feature. He
>>is therefore quite within his rights to use the implementation
>>namespace. Of course, he runs the risk of clashing with other
>>implementations, but I don't see a way around that.

>
> Everyone who writes code is an implementer.


But not necessarily of a C language system. He can add extensions to his C
implementation which I can guess can use the underscore prefix.

However this library doesn't seem specific to one implementation so perhaps
the underscores are not appropriate. As I think you point out next:

> There is no indication this was proposed to become a standard header
> and part of the standard run-time library or built into the
> compiler/linker. Paragraph 7.1.3 reserves these names for use in that
> context.


--
bartc

 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      09-29-2009
Barry Schwarz wrote:
> On Mon, 28 Sep 2009 17:41:09 +0000, Richard Heathfield
> <(E-Mail Removed)> wrote:
>
>> In <(E-Mail Removed)>, Barry Schwarz wrote:
>>
>>> On Mon, 28 Sep 2009 12:04:35 +0200, jacob navia <(E-Mail Removed)>
>>> wrote:
>>>

>> <snip>
>>>> typedef struct _StringCollection StringCollection;
>>>> struct _StringEnumerator;
>>> Is there some reason you chose to invade the implementation name
>>> space?

>> He is an *implementor*, proposing a new *implementation* feature. He
>> is therefore quite within his rights to use the implementation
>> namespace. Of course, he runs the risk of clashing with other
>> implementations, but I don't see a way around that.

>
> Everyone who writes code is an implementer.


RH was referring to an implementor of a C implementation. I been writing
C code for more than 3 decades, and I've implemented a great many
things, but I've never implemented C itself, not even a simplified
version thereof. Jacob has. When acting in his role as a C implementor,
he is allowed to use the name space reserved for implementors of C.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
review of the "container library", part 1/? Alan Curry C Programming 18 03-11-2011 01:02 AM
A container library in C Part 4. The arraylist container jacob navia C Programming 10 10-01-2009 02:26 PM
A container library in C. Part 2: String collection implementation jacob navia C Programming 3 09-29-2009 01:27 PM
A container library in C: Part 3. List container implementation jacob navia C Programming 5 09-28-2009 08:19 PM
Header files with "header.h" or <header.h> ?? mlt C++ 2 01-31-2009 02:54 PM



Advertisments