
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include <string.h>

#include "string_collection.h"

struct s_StringCollection
{
    int numStrings;
    char **strings;
};

static void string_collection_growArray (StringCollection *instance, int newLength);


StringCollection *
string_collection_new (void)
{
    StringCollection *instance = (StringCollection *) malloc (sizeof (StringCollection));

    instance->numStrings = 0;
    instance->strings = NULL;

    /* 
     * this will allocate the initial array
     *
     * from execvp man page:
     * The array of pointers _must_ be terminated by a NULL pointer.
     */
    string_collection_growArray (instance, 0);

    return (instance);
}

void
string_collection_destroy (void *ptr)
{
    StringCollection *instance = (StringCollection *) ptr;

    if (instance->numStrings > 0)
    {
        int i;

        for (i = 0; i < instance->numStrings; i++)
        {
            free (instance->strings[i]);
        }
    }

    free (instance->strings);

    free (instance);
}

static void
string_collection_growArray (StringCollection *instance, int newLength)
{
    int i;

    assert (newLength >= 0);
    assert (newLength >= instance->numStrings);

    instance->strings = realloc (instance->strings, sizeof (char *) * (newLength + 1));

    /* set each new entry to NULL */
    for (i = instance->numStrings; i <= newLength; i++)
    {
        instance->strings[i] = NULL;
    }
}

void
string_collection_addString (StringCollection *instance, const char *string)
{
    assert (string != NULL);

    string_collection_addData (instance, string, strlen (string));
}

void
string_collection_addData (StringCollection *instance, const char *string, int len)
{
    assert (string != NULL);
    assert (len > 0);

    /* allocate one for the added entry */
    string_collection_growArray (instance, instance->numStrings + 1);

    /* allocate an extra one for the NULL */
    instance->strings[instance->numStrings] = malloc (sizeof (char) * (len + 1));

    /* add the NULL to the end of the string */
    instance->strings[instance->numStrings][len] = 0;

    /* copy the string to the array */
    memcpy (instance->strings[instance->numStrings], string, len);

    instance->numStrings++;
}

char **
string_collection_getInternal (StringCollection *instance)
{
    return (instance->strings);
}
