|
Packit |
7dae13 |
/*
|
|
Packit |
7dae13 |
* Dynamic array, to store all your flims in Includes macros required
|
|
Packit |
7dae13 |
* to create an array of strings but as the primitive type for the
|
|
Packit |
7dae13 |
* array is void * providing your own duplicate_primitive and
|
|
Packit |
7dae13 |
* destroy_primitive functions will allow you to use the dynamic_array
|
|
Packit |
7dae13 |
* API to have a dynamic array containing any primitive
|
|
Packit |
7dae13 |
*
|
|
Packit |
7dae13 |
* Authors: Horms <horms@vergenet.net>
|
|
Packit |
7dae13 |
*
|
|
Packit |
7dae13 |
* Released under the terms of the GNU GPL
|
|
Packit |
7dae13 |
*
|
|
Packit |
7dae13 |
*/
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
#include "dynamic_array.h"
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
/**********************************************************************
|
|
Packit |
7dae13 |
* dynamic_array_create
|
|
Packit |
7dae13 |
* Create a dynamic array
|
|
Packit |
7dae13 |
* pre: block_size: blocking size to use.
|
|
Packit |
7dae13 |
* DEFAULT_DYNAMIC_ARRAY_BLOCK_SIZE is used if block_size is 0
|
|
Packit |
7dae13 |
* Block size refers to how many elements are prealocated
|
|
Packit |
7dae13 |
* each time the array is grown.
|
|
Packit |
7dae13 |
* return: An empty dynamic array
|
|
Packit |
7dae13 |
* NULL on error
|
|
Packit |
7dae13 |
**********************************************************************/
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
dynamic_array_t *
|
|
Packit |
7dae13 |
dynamic_array_create(size_t block_size)
|
|
Packit |
7dae13 |
{
|
|
Packit |
7dae13 |
dynamic_array_t *a;
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
if ((a = (dynamic_array_t *) malloc(sizeof(dynamic_array_t))) == NULL) {
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
a->vector = NULL;
|
|
Packit |
7dae13 |
a->count = 0;
|
|
Packit |
7dae13 |
a->allocated_size = 0;
|
|
Packit |
7dae13 |
a->block_size =
|
|
Packit |
7dae13 |
block_size ? block_size : DEFAULT_DYNAMIC_ARRAY_BLOCK_SIZE;
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
return (a);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
/**********************************************************************
|
|
Packit |
7dae13 |
* dynamic_array_destroy
|
|
Packit |
7dae13 |
* Free an array an all the elements held within
|
|
Packit |
7dae13 |
* pre: a: array to destroy
|
|
Packit |
7dae13 |
* destroy_element: pointer to funtion to destroy array elements
|
|
Packit |
7dae13 |
* Function should take an argument of a pointer
|
|
Packit |
7dae13 |
* and free the memory allocated to the structure
|
|
Packit |
7dae13 |
* pointed to.
|
|
Packit |
7dae13 |
* post: array is freed and destroy_element is called for all elements
|
|
Packit |
7dae13 |
* of the array.
|
|
Packit |
7dae13 |
* Nothing if a is NULL
|
|
Packit |
7dae13 |
**********************************************************************/
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
void
|
|
Packit |
7dae13 |
dynamic_array_destroy(dynamic_array_t * a,
|
|
Packit |
7dae13 |
void (*destroy_element) (void *))
|
|
Packit |
7dae13 |
{
|
|
Packit |
7dae13 |
if (a == NULL)
|
|
Packit |
7dae13 |
return;
|
|
Packit |
7dae13 |
while (a->count-- > 0) {
|
|
Packit |
7dae13 |
destroy_element(*(a->vector + a->count));
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
if (a->allocated_size > 0) {
|
|
Packit |
7dae13 |
free(a->vector);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
/**********************************************************************
|
|
Packit |
7dae13 |
* dynamic_array_add_element
|
|
Packit |
7dae13 |
* Add an element to a dynamic array
|
|
Packit |
7dae13 |
* pre: a: dynamic array to add element to
|
|
Packit |
7dae13 |
* e: element to add
|
|
Packit |
7dae13 |
* destroy_element: pointer to a function to destroy an element
|
|
Packit |
7dae13 |
* passed to dynamic_array_destroy on error
|
|
Packit |
7dae13 |
* duplicate_element: pointer to a function to duplicate an
|
|
Packit |
7dae13 |
* element should take a pointer to an element
|
|
Packit |
7dae13 |
* to duplicate as the only element and return
|
|
Packit |
7dae13 |
* a copy of the element Any memory allocation
|
|
Packit |
7dae13 |
* required should be done by this function.
|
|
Packit |
7dae13 |
* post: element in inserted in the first unused position in the array
|
|
Packit |
7dae13 |
* array size is increased by a->block_size if there is
|
|
Packit |
7dae13 |
* insufficient room in the array to add the element.
|
|
Packit |
7dae13 |
* Nothing is done if e is NULL
|
|
Packit |
7dae13 |
* return: a on success
|
|
Packit |
7dae13 |
* NULL if a is NULL or an error occurs
|
|
Packit |
7dae13 |
**********************************************************************/
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
dynamic_array_t *
|
|
Packit |
7dae13 |
dynamic_array_add_element(dynamic_array_t * a,
|
|
Packit |
7dae13 |
const void *e, void (*destroy_element) (void *s), void
|
|
Packit |
7dae13 |
*(*duplicate_element) (const void *s))
|
|
Packit |
7dae13 |
{
|
|
Packit |
7dae13 |
if (a == NULL)
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
if (e == NULL)
|
|
Packit |
7dae13 |
return (a);
|
|
Packit |
7dae13 |
if (a->count == a->allocated_size) {
|
|
Packit |
7dae13 |
a->allocated_size += a->block_size;
|
|
Packit |
7dae13 |
if (
|
|
Packit |
7dae13 |
(a->vector =
|
|
Packit |
7dae13 |
(void **) realloc(a->vector,
|
|
Packit |
7dae13 |
a->allocated_size * sizeof(void *))) == NULL) {
|
|
Packit |
7dae13 |
dynamic_array_destroy(a, destroy_element);
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
if ((*(a->vector + a->count) = (void *) duplicate_element(e)) == NULL) {
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
a->count++;
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
return (a);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
/**********************************************************************
|
|
Packit |
7dae13 |
* dynamic_array_display
|
|
Packit |
7dae13 |
* Print the contents of a dynamic array to a string
|
|
Packit |
7dae13 |
* pre: a: dynamic array to display
|
|
Packit |
7dae13 |
* delimiter: character to place between elements of the array
|
|
Packit |
7dae13 |
* display_element: pointer to a function to display an element
|
|
Packit |
7dae13 |
* element_length: pointer to a function to return the
|
|
Packit |
7dae13 |
* length of an element
|
|
Packit |
7dae13 |
* post: If a is NULL or there are no elements in a then nothing is done
|
|
Packit |
7dae13 |
* Else a character buffer is alocated and the contents
|
|
Packit |
7dae13 |
* of each array element, separated by delimiter is placed
|
|
Packit |
7dae13 |
* in the '\0' termintated buffer returned. It is up to the
|
|
Packit |
7dae13 |
* user to free this buffer.
|
|
Packit |
7dae13 |
* return: Allocated buffer as above
|
|
Packit |
7dae13 |
* NULL on error, NULL a or empty a
|
|
Packit |
7dae13 |
**********************************************************************/
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
char *
|
|
Packit |
7dae13 |
dynamic_array_display(dynamic_array_t * a,
|
|
Packit |
7dae13 |
char delimiter,
|
|
Packit |
7dae13 |
void (*display_element) (char *, void *),
|
|
Packit |
7dae13 |
size_t(*element_length) (void *))
|
|
Packit |
7dae13 |
{
|
|
Packit |
7dae13 |
void **a_current;
|
|
Packit |
7dae13 |
void **a_top;
|
|
Packit |
7dae13 |
char *buffer;
|
|
Packit |
7dae13 |
char *buffer_current;
|
|
Packit |
7dae13 |
size_t nochar;
|
|
Packit |
7dae13 |
size_t len = 0;
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
if (a == NULL || a->count == 0) {
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
a_top = a->vector + a->count;
|
|
Packit |
7dae13 |
nochar = a->count;
|
|
Packit |
7dae13 |
for (a_current = a->vector; a_current < a_top; a_current++) {
|
|
Packit |
7dae13 |
nochar += (len = element_length(*a_current));
|
|
Packit |
7dae13 |
if (!len) {
|
|
Packit |
7dae13 |
nochar--;
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
if ((buffer = (char *) malloc(nochar)) == NULL) {
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
buffer_current = buffer;
|
|
Packit |
7dae13 |
for (a_current = a->vector; a_current < a_top; a_current++) {
|
|
Packit |
7dae13 |
if ((len = element_length(*a_current))) {
|
|
Packit |
7dae13 |
display_element(buffer_current, *a_current);
|
|
Packit |
7dae13 |
buffer_current += element_length(*a_current);
|
|
Packit |
7dae13 |
*buffer_current++ = delimiter;
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
if (len) {
|
|
Packit |
7dae13 |
buffer_current--;
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
*buffer_current = '\0';
|
|
Packit |
7dae13 |
return (buffer);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
/**********************************************************************
|
|
Packit |
7dae13 |
* dynamic_array_get_element
|
|
Packit |
7dae13 |
* Get an element from an array
|
|
Packit |
7dae13 |
* pre: a: array to retrieve element from
|
|
Packit |
7dae13 |
* elementno: index element in array to retrieve
|
|
Packit |
7dae13 |
* post: no change is made to a
|
|
Packit |
7dae13 |
* return: element requested
|
|
Packit |
7dae13 |
* NULL if element is beyond the number of elements in the arary
|
|
Packit |
7dae13 |
**********************************************************************/
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
void *
|
|
Packit |
7dae13 |
dynamic_array_get_element(dynamic_array_t * a, size_t elementno)
|
|
Packit |
7dae13 |
{
|
|
Packit |
7dae13 |
if (elementno > a->count)
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
return (*((a->vector) + elementno));
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
/**********************************************************************
|
|
Packit |
7dae13 |
* dynamic_array_get_count
|
|
Packit |
7dae13 |
* Get the number of elements in the array
|
|
Packit |
7dae13 |
* pre: array to find the number of elements in
|
|
Packit |
7dae13 |
* return: number of elements in the array
|
|
Packit |
7dae13 |
* -1 if a is NULL
|
|
Packit |
7dae13 |
**********************************************************************/
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
size_t
|
|
Packit |
7dae13 |
dynamic_array_get_count(dynamic_array_t * a)
|
|
Packit |
7dae13 |
{
|
|
Packit |
7dae13 |
if (a == NULL)
|
|
Packit |
7dae13 |
return (-1);
|
|
Packit |
7dae13 |
return (a->count);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
/**********************************************************************
|
|
Packit |
7dae13 |
* dynamic_array_get_vector
|
|
Packit |
7dae13 |
* Get the array contained in the dynamic array
|
|
Packit |
7dae13 |
* pre: array to find the vector of
|
|
Packit |
7dae13 |
* return: vector
|
|
Packit |
7dae13 |
* NULL if a is NULL
|
|
Packit |
7dae13 |
**********************************************************************/
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
void *
|
|
Packit |
7dae13 |
dynamic_array_get_vector(dynamic_array_t * a)
|
|
Packit |
7dae13 |
{
|
|
Packit |
7dae13 |
if (a == NULL)
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
return (a->vector);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
/**********************************************************************
|
|
Packit |
7dae13 |
* dynamic_array_split_str
|
|
Packit |
7dae13 |
* Split a string into substrings on a delimiter
|
|
Packit |
7dae13 |
* pre: str: string to split
|
|
Packit |
7dae13 |
* delimiter: character to split string on
|
|
Packit |
7dae13 |
* post: string is split.
|
|
Packit |
7dae13 |
* Note: The string is modified.
|
|
Packit |
7dae13 |
* return: dynamic array containing sub_strings
|
|
Packit |
7dae13 |
* NULL on error
|
|
Packit |
7dae13 |
* string being NULL is an error state
|
|
Packit |
7dae13 |
**********************************************************************/
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
dynamic_array_t *
|
|
Packit |
7dae13 |
dynamic_array_split_str(char *string, const char delimiter)
|
|
Packit |
7dae13 |
{
|
|
Packit |
7dae13 |
dynamic_array_t *a;
|
|
Packit |
7dae13 |
char *sub_string;
|
|
Packit |
7dae13 |
|
|
Packit |
7dae13 |
if (string == NULL) {
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
if ((a = dynamic_array_create(0)) == NULL) {
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
while ((sub_string = strchr(string, delimiter)) != NULL) {
|
|
Packit |
7dae13 |
*sub_string = '\0';
|
|
Packit |
7dae13 |
if (dynamic_array_add_element(a, string, DESTROY_STR, DUP_STR) == NULL) {
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
string = sub_string + 1;
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
if (*string != '\0' &&
|
|
Packit |
7dae13 |
dynamic_array_add_element(a, string, DESTROY_STR, DUP_STR) == NULL) {
|
|
Packit |
7dae13 |
return (NULL);
|
|
Packit |
7dae13 |
}
|
|
Packit |
7dae13 |
return (a);
|
|
Packit |
7dae13 |
}
|