/* c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil
 * vi: set shiftwidth=2 tabstop=2 expandtab:
 * :indentSize=2:tabSize=2:noTabs=true:
 */

#ifndef __H_DYNAMIC_ARRAY__
#define __H_DYNAMIC_ARRAY__
#include <stdlib.h>
#include "defs.h"

/* This file, as the rest of the project is under MIT license.
 * see http://opensource.org/licenses/MIT
 *
 * Author Gustav Hartvigsson <gustav.hartvigsson _at_ gmail.com> 2014
 */

/** @file
 * Dynamic Array.
 *
 * This file contains an imlpementation of a "dynamic" array, it is usefule when
 * dealing with lare amounts of data that may change over time, or with an
 * unknowned numebr of items.
 * 
 * Note that accsess time is constant, but write time is not guarenteed to be.
 * 
 * When the size of the array is equal to the number of elements in it, it will
 * re-allocate the array with a larger size.
 */

/**
 * The padding that is added when expanding the array.
 */
#define ARRAY_PADDING 8

/**
 * an opaque data structure that represents the dynamic array.
 */
typedef struct DynamicArray DynamicArray;

#if 0
#ifndef __H_DEFS__
/**
 * Represents a for each function.
 * 
 * @param self the dynamic array.
 * @param data the data to be passed to the each iteration.
 * @returns data to be put in a new \c DynamicArray, if used with
 *          <tt>dynamic_array_for_each_with_return</tt>.
 */
typedef _pointer (* ForEachFunc)(DynamicArray * self, _pointer item, _pointer data);

/**
 * Represents a function to be used when freeing some item in a dynamic array.
 *
 * @param obj The object to be freed.
 */
typedef _pointer (* FreeFunc)(_pointer obj);

#endif /* __H_DEFS__ */
#endif /* #if 0*/

/**
 * Create a new dynamic array.
 *
 * @param len The length of the initial array.
 * @param free_func The function to be used when freeing the items. Can be \c NULL.
 *        If free_func is NULL, it will use the standard library's 
 *       <tt>free()</tt>.
 *        
 *        Normally a function with the signature <tt> (DynamicArray * self,
          _pointer item, _pointer data) </tt> should be used but cast to FreeFunc.
 */
DynamicArray * dynamic_array_new (size_t len, FreeFunc free_func);

/**
 * Frees the dynamic array.
 * 
 * after this is run the data will be lost.
 */
void dynamic_array_free (DynamicArray * self);


/**
 * Get an item from the array.
 */
_pointer dynamic_array_get (DynamicArray * self, size_t index);

/**
 * Get the length of the array.
 */
size_t dynamic_array_len (DynamicArray * self);


/**
 * Get the size of the array, this is not the same as the length of the array.
 * The size is the number of elements that can be allocated without resizing
 * the array.
 * 
 * To get the length of the array use dynamic_array_len ().
 */
size_t dynamic_array_size (DynamicArray * self);


/**
 * Add an item to the array.
 */
void dynamic_array_add (DynamicArray * self, _pointer item);

/**
 * Dumps a copy of the array. Must be cast.
 * 
 * Is not freed when the dynamic array is freed.
 * 
 * Is null-terminated.
 */
_pointer* dynamic_array_dump_array (DynamicArray * self);

/**
 * Use a function on the array.
 */
void dynamic_array_for_each (DynamicArray * self, ForEachFunc func,
                             _pointer data);

/** TODO
 * same as dynamic_array_for_each (), with the difference that it returns a new
 * DynamicArray.
 */
DynamicArray * dynamic_array_for_each_with_return (DynamicArray * self,
                                                   ForEachFunc func,
                                                   _pointer data);

#endif /* #define __H_DYNAMIC_ARRAY__ */
