A container library in C. Part 1: Header file

Discussion in 'C Programming' started by jacob navia, Sep 28, 2009.

  1. jacob navia

    jacob navia Guest

    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
    jacob navia, Sep 28, 2009
    #1
    1. Advertising

  2. jacob navia

    David RF Guest

    On 28 sep, 12:04, jacob navia <> 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
    David RF, Sep 28, 2009
    #2
    1. Advertising

  3. jacob navia

    jacob navia Guest

    David RF a écrit :
    > On 28 sep, 12:04, jacob navia <> 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.
    jacob navia, Sep 28, 2009
    #3
  4. jacob navia

    bartc Guest

    "jacob navia" <> wrote in message
    news:h9q6v1$1l3$...
    > 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
    bartc, Sep 28, 2009
    #4
  5. jacob navia

    jacob navia Guest

    Gcc compatible header file

    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
    jacob navia, Sep 28, 2009
    #5
  6. Re: Gcc compatible header file

    jacob navia <> 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.
    Ben Bacarisse, Sep 28, 2009
    #6
  7. On Mon, 28 Sep 2009 12:04:35 +0200, jacob navia <>
    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
    Barry Schwarz, Sep 28, 2009
    #7
  8. On Mon, 28 Sep 2009 17:41:09 +0000, Richard Heathfield
    <> wrote:

    >In <>, Barry Schwarz wrote:
    >
    >> On Mon, 28 Sep 2009 12:04:35 +0200, jacob navia <>
    >> 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
    Barry Schwarz, Sep 29, 2009
    #8
  9. jacob navia

    bartc Guest

    "Barry Schwarz" <> wrote in message
    news:eek:...
    > On Mon, 28 Sep 2009 17:41:09 +0000, Richard Heathfield
    > <> wrote:
    >
    >>In <>, Barry Schwarz wrote:
    >>
    >>> On Mon, 28 Sep 2009 12:04:35 +0200, jacob navia <>
    >>> 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
    bartc, Sep 29, 2009
    #9
  10. jacob navia

    James Kuyper Guest

    Barry Schwarz wrote:
    > On Mon, 28 Sep 2009 17:41:09 +0000, Richard Heathfield
    > <> wrote:
    >
    >> In <>, Barry Schwarz wrote:
    >>
    >>> On Mon, 28 Sep 2009 12:04:35 +0200, jacob navia <>
    >>> 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.
    James Kuyper, Sep 29, 2009
    #10
  11. jacob navia

    Tech07 Guest

    jacob navia wrote:
    > 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.


    How old are you?

    >
    > As all other containers in this proposal,


    Whoa! Cowboy, do really believe that people are gonna read anything further
    unless they too believe that a string is a container? Prove it cowboy!
    "string"? You mean like roping calves? That would be a rope. "string", like
    that 80-year old lady in Europe uses to painstakingly make <I don't think
    we'll ever know what she makes>, or is that "thread"? Is there sheep
    involved in that process? Maybe she just gets the raw materials in a
    container, I dunno. Do you?

    (Are you howling at the moon?).
    Tech07, Sep 30, 2009
    #11
  12. "Tech07" <> wrote in message
    news:dyzwm.13783$...
    > jacob navia wrote:
    >> 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.

    >
    > How old are you?
    >
    >>
    >> As all other containers in this proposal,

    >
    > Whoa! Cowboy, do really believe that people are gonna read anything
    > further unless they too believe that a string is a container?


    IMVHO, a string is a container of characters.




    > Prove it cowboy!


    Yeeeeeeeeeeeeee, Hawwwwwwwwwww!

    ;^D




    > "string"? You mean like roping calves? That would be a rope.


    Explain to me how to implement a rope... Please?




    > "string", like that 80-year old lady in Europe uses to painstakingly make
    > <I don't think we'll ever know what she makes>, or is that "thread"? Is
    > there sheep involved in that process? Maybe she just gets the raw
    > materials in a container, I dunno. Do you?
    >
    > (Are you howling at the moon?).


    ;^|
    Chris M. Thomasson, Sep 30, 2009
    #12
  13. "Chris M. Thomasson" <> wrote in message
    news:h9uih5$kkr$...
    >
    > "Tech07" <> wrote in message
    > news:dyzwm.13783$...
    >> jacob navia wrote:
    >>> 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.

    >>
    >> How old are you?
    >>
    >>>
    >>> As all other containers in this proposal,

    >>
    >> Whoa! Cowboy, do really believe that people are gonna read anything
    >> further unless they too believe that a string is a container?

    >
    > IMVHO, a string is a container of characters.


    Correction...

    a string is a container of characters, with the last character being equal
    to '\0'.


    [...]
    Chris M. Thomasson, Sep 30, 2009
    #13
  14. jacob navia

    Tech07 Guest

    Chris M. Thomasson wrote:
    > "Chris M. Thomasson" <> wrote in message
    > news:h9uih5$kkr$...
    >>
    >> "Tech07" <> wrote in message
    >> news:dyzwm.13783$...
    >>> jacob navia wrote:
    >>>> 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.
    >>>
    >>> How old are you?
    >>>
    >>>>
    >>>> As all other containers in this proposal,
    >>>
    >>> Whoa! Cowboy, do really believe that people are gonna read anything
    >>> further unless they too believe that a string is a container?

    >>
    >> IMVHO, a string is a container of characters.

    >
    > Correction...
    >
    > a string is a container of characters, with the last character being
    > equal to '\0'.
    >
    >

    I have more important things to do than to consult to you for free. :p
    Tech07, Oct 3, 2009
    #14
  15. jacob navia

    Tech07 Guest

    jacob navia wrote:
    > 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.


    That would be a student look at it (an elementary student of the science).
    Tech07, Oct 3, 2009
    #15
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. mlt
    Replies:
    2
    Views:
    828
    Jean-Marc Bourguet
    Jan 31, 2009
  2. jacob navia
    Replies:
    3
    Views:
    323
    jacob navia
    Sep 29, 2009
  3. jacob navia
    Replies:
    5
    Views:
    498
    jacob navia
    Sep 28, 2009
  4. jacob navia
    Replies:
    10
    Views:
    641
    jacob navia
    Oct 1, 2009
  5. Alan Curry

    review of the "container library", part 1/?

    Alan Curry, Mar 1, 2011, in forum: C Programming
    Replies:
    18
    Views:
    651
    jacob navia
    Mar 11, 2011
Loading...

Share This Page