Skip to content

Instantly share code, notes, and snippets.

@junxie6
Forked from FurryHead/array.c
Created May 11, 2021 04:34
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save junxie6/80fed83de68a1ebe751fc274009b0e2a to your computer and use it in GitHub Desktop.
Dynamic array and map in C.
#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