General refactoring
This commit is contained in:
2030
src/bigint.c
2030
src/bigint.c
File diff suppressed because it is too large
Load Diff
84
src/map.c
84
src/map.c
@@ -11,10 +11,6 @@
|
||||
#include "map.h"
|
||||
|
||||
// Internal methods
|
||||
static uint64_t hash_key(const char *key);
|
||||
static size_t map_insert_index(const map_t *map, const char *key);
|
||||
static size_t map_find_index(const map_t *map, const char *key);
|
||||
static map_result_t map_resize(map_t *map);
|
||||
|
||||
/**
|
||||
* hash_key
|
||||
@@ -22,7 +18,7 @@ static map_result_t map_resize(map_t *map);
|
||||
*
|
||||
* Returns the digest of @key using the Fowler-Noll-Vo hashing algorithm
|
||||
*/
|
||||
uint64_t hash_key(const char *key) {
|
||||
static uint64_t hash_key(const char *key) {
|
||||
uint64_t hash = FNV_OFFSET_BASIS_64;
|
||||
|
||||
while (*key) {
|
||||
@@ -33,43 +29,6 @@ uint64_t hash_key(const char *key) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* map_new
|
||||
*
|
||||
* Returns a map_result_t data type containing a new hash map
|
||||
*/
|
||||
map_result_t map_new(void) {
|
||||
map_result_t result = {0};
|
||||
|
||||
map_t *map = malloc(sizeof(map_t));
|
||||
if (map == NULL) {
|
||||
result.status = MAP_ERR_ALLOCATE;
|
||||
SET_MSG(result, "Failed to allocate memory for map");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
map->elements = calloc(INITIAL_CAP, sizeof(map_element_t));
|
||||
if (map->elements == NULL) {
|
||||
free(map);
|
||||
result.status = MAP_ERR_ALLOCATE;
|
||||
SET_MSG(result, "Failed to allocate memory for map elements");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Initialize map
|
||||
map->capacity = INITIAL_CAP;
|
||||
map->size = 0;
|
||||
map->tombstone_count = 0;
|
||||
|
||||
result.status = MAP_OK;
|
||||
SET_MSG(result, "Map successfully created");
|
||||
result.value.map = map;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* map_insert_index
|
||||
* @map: a non-null map
|
||||
@@ -80,7 +39,7 @@ map_result_t map_new(void) {
|
||||
*
|
||||
* Returns the index of available slot or SIZE_MAX otherwise
|
||||
*/
|
||||
size_t map_insert_index(const map_t *map, const char *key) {
|
||||
static size_t map_insert_index(const map_t *map, const char *key) {
|
||||
const uint64_t key_digest = hash_key(key);
|
||||
size_t idx = key_digest % map->capacity;
|
||||
size_t delete_tracker = map->capacity; // Fallback index
|
||||
@@ -113,7 +72,7 @@ size_t map_insert_index(const map_t *map, const char *key) {
|
||||
*
|
||||
* Returns a a map_result_t data type containing the status
|
||||
*/
|
||||
map_result_t map_resize(map_t *map) {
|
||||
static map_result_t map_resize(map_t *map) {
|
||||
map_result_t result = {0};
|
||||
|
||||
const size_t old_capacity = map->capacity;
|
||||
@@ -174,6 +133,43 @@ map_result_t map_resize(map_t *map) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* map_new
|
||||
*
|
||||
* Returns a map_result_t data type containing a new hash map
|
||||
*/
|
||||
map_result_t map_new(void) {
|
||||
map_result_t result = {0};
|
||||
|
||||
map_t *map = malloc(sizeof(map_t));
|
||||
if (map == NULL) {
|
||||
result.status = MAP_ERR_ALLOCATE;
|
||||
SET_MSG(result, "Failed to allocate memory for map");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
map->elements = calloc(INITIAL_CAP, sizeof(map_element_t));
|
||||
if (map->elements == NULL) {
|
||||
free(map);
|
||||
result.status = MAP_ERR_ALLOCATE;
|
||||
SET_MSG(result, "Failed to allocate memory for map elements");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Initialize map
|
||||
map->capacity = INITIAL_CAP;
|
||||
map->size = 0;
|
||||
map->tombstone_count = 0;
|
||||
|
||||
result.status = MAP_OK;
|
||||
SET_MSG(result, "Map successfully created");
|
||||
result.value.map = map;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* map_add
|
||||
* @map: a non-null map
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include <stdint.h>
|
||||
#define SET_MSG(result, msg) \
|
||||
do { \
|
||||
snprintf((char *)(result).message, RESULT_MSG_SIZE, "%s", (const char *)msg); \
|
||||
@@ -6,6 +5,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
216
src/vector.c
216
src/vector.c
@@ -10,10 +10,112 @@
|
||||
#include "vector.h"
|
||||
|
||||
// Internal methods
|
||||
static vector_result_t vector_resize(vector_t *vector);
|
||||
static void swap(void *x, void *y, size_t size);
|
||||
static size_t partition(void *base, size_t low, size_t high, size_t size, vector_cmp_fn cmp);
|
||||
static void quicksort(void *base, size_t low, size_t high, size_t size, vector_cmp_fn cmp);
|
||||
/**
|
||||
* vector_resize
|
||||
* @vector: a non-null vector
|
||||
*
|
||||
* Increases the size of @vector
|
||||
*
|
||||
* Returns a vector_result_t data type containing the status
|
||||
*/
|
||||
static vector_result_t vector_resize(vector_t *vector) {
|
||||
vector_result_t result = {0};
|
||||
|
||||
const size_t old_capacity = vector->capacity;
|
||||
const size_t new_capacity = old_capacity > 0 ? old_capacity * 2 : 1;
|
||||
|
||||
// Check for stack overflow errors
|
||||
if (new_capacity > SIZE_MAX / vector->data_size) {
|
||||
result.status = VECTOR_ERR_OVERFLOW;
|
||||
SET_MSG(result, "Exceeded maximum size while resizing vector");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void *new_elements = realloc(vector->elements, new_capacity * vector->data_size);
|
||||
if (new_elements == NULL) {
|
||||
result.status = VECTOR_ERR_ALLOCATE;
|
||||
SET_MSG(result, "Failed to reallocate memory for vector");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
vector->elements = new_elements;
|
||||
vector->capacity = new_capacity;
|
||||
|
||||
result.status = VECTOR_OK;
|
||||
SET_MSG(result, "Vector successfully resized");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* swap
|
||||
* @x: first element
|
||||
* @y: second element
|
||||
*
|
||||
* Swaps @x and @y
|
||||
*/
|
||||
static void swap(void *x, void *y, size_t size) {
|
||||
uint8_t temp[size];
|
||||
|
||||
memcpy(temp, x, size);
|
||||
memcpy(x, y, size);
|
||||
memcpy(y, temp, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* partition
|
||||
* @base: the array/partition
|
||||
* @low: lower index
|
||||
* @high: higher index
|
||||
* @size: data size
|
||||
* @cmp: comparison function
|
||||
*
|
||||
* Divides an array into two partitions
|
||||
*
|
||||
* Returns the pivot index
|
||||
*/
|
||||
static size_t partition(void *base, size_t low, size_t high, size_t size, vector_cmp_fn cmp) {
|
||||
uint8_t *arr = (uint8_t*)base;
|
||||
void *pivot = arr + (high * size);
|
||||
size_t i = low;
|
||||
|
||||
for (size_t j = low; j < high; j++) {
|
||||
vector_order_t order = cmp(arr + (j * size), pivot);
|
||||
|
||||
if (order == VECTOR_ORDER_LT || order == VECTOR_ORDER_EQ) {
|
||||
swap(arr + (i * size), arr + (j * size), size);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
swap(arr + (i * size), arr + (high * size), size);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* quicksort
|
||||
* @base: the base array/partition
|
||||
* @low: lower index
|
||||
* @high: higher index
|
||||
* @size: data size
|
||||
* @cmp: comparision function
|
||||
*
|
||||
* Recursively sorts an array/partition using the Quicksort algorithm
|
||||
*/
|
||||
static void quicksort(void *base, size_t low, size_t high, size_t size, vector_cmp_fn cmp) {
|
||||
if (low < high) {
|
||||
const size_t pivot = partition(base, low, high, size, cmp);
|
||||
|
||||
if (pivot > 0) {
|
||||
quicksort(base, low, pivot - 1, size, cmp);
|
||||
}
|
||||
quicksort(base, pivot + 1, high, size, cmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* vector_new
|
||||
@@ -61,112 +163,6 @@ vector_result_t vector_new(size_t size, size_t data_size) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* vector_resize
|
||||
* @vector: a non-null vector
|
||||
*
|
||||
* Increases the size of @vector
|
||||
*
|
||||
* Returns a vector_result_t data type containing the status
|
||||
*/
|
||||
vector_result_t vector_resize(vector_t *vector) {
|
||||
vector_result_t result = {0};
|
||||
|
||||
const size_t old_capacity = vector->capacity;
|
||||
const size_t new_capacity = old_capacity > 0 ? old_capacity * 2 : 1;
|
||||
|
||||
// Check for stack overflow errors
|
||||
if (new_capacity > SIZE_MAX / vector->data_size) {
|
||||
result.status = VECTOR_ERR_OVERFLOW;
|
||||
SET_MSG(result, "Exceeded maximum size while resizing vector");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void *new_elements = realloc(vector->elements, new_capacity * vector->data_size);
|
||||
if (new_elements == NULL) {
|
||||
result.status = VECTOR_ERR_ALLOCATE;
|
||||
SET_MSG(result, "Failed to reallocate memory for vector");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
vector->elements = new_elements;
|
||||
vector->capacity = new_capacity;
|
||||
|
||||
result.status = VECTOR_OK;
|
||||
SET_MSG(result, "Vector successfully resized");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* swap
|
||||
* @x: first element
|
||||
* @y: second element
|
||||
*
|
||||
* Swaps @x and @y
|
||||
*/
|
||||
void swap(void *x, void *y, size_t size) {
|
||||
uint8_t temp[size];
|
||||
|
||||
memcpy(temp, x, size);
|
||||
memcpy(x, y, size);
|
||||
memcpy(y, temp, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* partition
|
||||
* @base: the array/partition
|
||||
* @low: lower index
|
||||
* @high: higher index
|
||||
* @size: data size
|
||||
* @cmp: comparison function
|
||||
*
|
||||
* Divides an array into two partitions
|
||||
*
|
||||
* Returns the pivot index
|
||||
*/
|
||||
size_t partition(void *base, size_t low, size_t high, size_t size, vector_cmp_fn cmp) {
|
||||
uint8_t *arr = (uint8_t*)base;
|
||||
void *pivot = arr + (high * size);
|
||||
size_t i = low;
|
||||
|
||||
for (size_t j = low; j < high; j++) {
|
||||
vector_order_t order = cmp(arr + (j * size), pivot);
|
||||
|
||||
if (order == VECTOR_ORDER_LT || order == VECTOR_ORDER_EQ) {
|
||||
swap(arr + (i * size), arr + (j * size), size);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
swap(arr + (i * size), arr + (high * size), size);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* quicksort
|
||||
* @base: the base array/partition
|
||||
* @low: lower index
|
||||
* @high: higher index
|
||||
* @size: data size
|
||||
* @cmp: comparision function
|
||||
*
|
||||
* Recursively sorts an array/partition using the Quicksort algorithm
|
||||
*/
|
||||
void quicksort(void *base, size_t low, size_t high, size_t size, vector_cmp_fn cmp) {
|
||||
if (low < high) {
|
||||
const size_t pivot = partition(base, low, high, size, cmp);
|
||||
|
||||
if (pivot > 0) {
|
||||
quicksort(base, low, pivot - 1, size, cmp);
|
||||
}
|
||||
quicksort(base, pivot + 1, high, size, cmp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* vector_push
|
||||
* @vector: a non-null vector
|
||||
|
||||
Reference in New Issue
Block a user