Created
July 15, 2011 18:55
-
-
Save FurryHead/1085280 to your computer and use it in GitHub Desktop.
Dynamic array and map in C.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string.h> | |
#include <stdlib.h> | |
#include "array.h" | |
typedef struct array array; | |
typedef struct map map; | |
/** @brief Allocates and initializes a new array */ | |
array *array_new(void) { | |
array *tmp = malloc(sizeof(array)); | |
tmp->size = 0; | |
tmp->items = malloc(sizeof(void*) * ARRAY_EXPAND_SIZE); | |
tmp->_num_allocated = ARRAY_EXPAND_SIZE; | |
return tmp; | |
} | |
/** @brief Sets the value of an index. | |
* | |
* Takes an array, index, and pointer to an item and adds it to the array. | |
* If index is higher than the size of the array, it appends to the end of the array. | |
* If index is negative, index from the end instead (i.e. array_set(arr, -1, item) sets the last element) | |
* item can be anything, EXCEPT null. | |
* | |
* @param arr The array to operate upon. | |
* @param index The index to access. If index is negative, index from the end instead. | |
* @param item The item to set at index. | |
* @return 1 if the operation succeeded, or 0 if it failed. | |
*/ | |
int array_set(array *arr, int index, void *item) { | |
void *_tmp; | |
int tmp_ind; | |
if (item == NULL) | |
return 0; | |
if (index >= arr->_num_elements) { | |
if (arr->_num_elements == arr->_num_allocated) { | |
_tmp = realloc(arr->items, sizeof(void*) * (arr->_num_elements + ARRAY_EXPAND_SIZE)); | |
if (!_tmp) | |
return 0; | |
arr->items = (void**)_tmp; | |
} | |
arr->items[arr->_num_elements] = item; | |
arr->_num_elements += 1; | |
arr->size += 1; | |
} else if (index < 0) { | |
tmp_ind = arr->_num_elements + index; | |
return array_set(arr, tmp_ind, item); | |
} else { | |
arr->items[index] = item; | |
} | |
return 1; | |
} | |
/** @brief Convenience function to append to an array. */ | |
int array_append(array *arr, void *item) { | |
return array_set(arr, arr->_num_elements, item); | |
} | |
/** @brief Retrieves a value from the array. Returns null if the index is out of range. | |
* | |
* @param arr The array to operate upon. | |
* @param index The index of the specified item you wish to retrieve. | |
* @return The element at index, or NULL if the index is out of range. | |
*/ | |
void *array_get(array *arr, int index) { | |
int tmp_ind; | |
if (arr->_num_elements == 0) | |
return NULL; | |
if (index >= arr->_num_elements) | |
return NULL; | |
else if (index < 0) { | |
tmp_ind = arr->_num_elements + index; | |
return array_get(arr, tmp_ind); | |
} else { | |
return arr->items[index]; | |
} | |
} | |
/** @brief Removes a value from arr, shifting the items over and returning the removed value. | |
* | |
* @param arr The array to operate upon. | |
* @param index The index of the element to remove. | |
* @return The element removed, or NULL if the index is out of range. | |
*/ | |
void *array_remove(array *arr, int index) { | |
int tmp_ind; | |
int i; | |
void *tmp = array_get(arr, index); | |
if (tmp == NULL) | |
return NULL; | |
if (arr->_num_elements == 0) | |
return NULL; | |
if (index >= arr->_num_elements) | |
return NULL; | |
if (index < 0) { | |
tmp_ind = arr->_num_elements + index; | |
if (tmp_ind < 0) return NULL; | |
return array_remove(arr, tmp_ind); | |
} | |
if (arr->_num_elements > 1) | |
for (i = index; i < (arr->_num_elements-1); i++) | |
array_set(arr, i, array_get(arr, i+1)); | |
arr->size -= 1; | |
arr->_num_elements -= 1; | |
return tmp; | |
} | |
/** @brief Convenience function to remove the last element in the array. */ | |
void *array_pop(array *arr) { | |
return array_remove(arr, arr->_num_elements-1); | |
} | |
/** @brief Deletes the array. | |
* | |
* BEWARE: In addition to freeing all the elements in the array, it also frees the array itself. | |
* Do not call free() on the array* after this function, it does it for you!! | |
* | |
* If you do not wish for all the elements in the array to be freed, call array_remove on the elements you do not wish to be freed before calling this function. | |
*/ | |
void array_free(array *arr) { | |
if (arr != NULL) { | |
if (arr->items != NULL) | |
free(arr->items); | |
free(arr); | |
} | |
} | |
/** @brief Allocates and initializes a new map */ | |
map *map_new(void) { | |
map *tmp = malloc(sizeof(map)); | |
tmp->keys = array_new(); | |
tmp->values = array_new(); | |
return tmp; | |
} | |
/** @brief Retrieves a value from the map. Returns null if the key is not valid. | |
* | |
* @param m The map to operate upon. | |
* @param key The key of the specified item you wish to retrieve. | |
* @return The element at key, or NULL if the key is not valid. | |
*/ | |
void *map_get(map *m, void *key) { | |
int i; | |
if (key == NULL) | |
return NULL; | |
for (i = 0; i < m->keys->size; i++) { | |
if (array_get(m->keys, i) == key) { | |
return array_get(m->values, i); | |
} | |
} | |
return NULL; | |
} | |
/** @brief Sets the value of a key. | |
* | |
* Takes a map, key, and pointer to an item and adds it to the map. | |
* | |
* @param m The map to operate upon. | |
* @param key The key to access. | |
* @param item The value to set for key. | |
* @return 1 if the operation succeeded, or 0 if it failed. | |
*/ | |
int map_set(map *m, void *key, void *value) { | |
int i; | |
int ind = m->keys->size; | |
if (key == NULL || value == NULL) | |
return 0; | |
for (i = 0; i < m->keys->size; i++) { | |
if (array_get(m->keys, i) == key) { | |
ind = i; | |
break; | |
} | |
} | |
array_set(m->keys, ind, key); | |
array_set(m->values, ind, value); | |
return 1; | |
} | |
/** @brief Removes the value associated with key, returning the removed value. | |
* | |
* @param m The map to operate upon. | |
* @param key The key of the element to remove. | |
* @return The element removed, or NULL if the key is not valid. | |
*/ | |
void *map_remove(map *m, void *key) { | |
int i; | |
if (key == NULL) | |
return NULL; | |
for (i = 0; i < m->keys->size; i++) { | |
if (array_get(m->keys, i) == key) { | |
array_remove(m->keys, i); | |
return array_remove(m->values, i); | |
} | |
} | |
return NULL; | |
} | |
/** @brief Deletes the map. | |
* | |
* BEWARE: In addition to freeing all the elements in the map, it also frees the map itself. | |
* Do not call free() on the map* after this function, it does it for you!! | |
* | |
* If you do not wish for all the elements in the map to be freed, call map_remove on the elements you do not wish to be freed before calling this function. | |
*/ | |
void map_free(map *m) { | |
if (m != NULL) { | |
array_free(m->keys); | |
array_free(m->values); | |
free(m); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment