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"
|
#include "map.h"
|
||||||
|
|
||||||
// Internal methods
|
// 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
|
* 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
|
* 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;
|
uint64_t hash = FNV_OFFSET_BASIS_64;
|
||||||
|
|
||||||
while (*key) {
|
while (*key) {
|
||||||
@@ -33,43 +29,6 @@ uint64_t hash_key(const char *key) {
|
|||||||
return hash;
|
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_insert_index
|
||||||
* @map: a non-null map
|
* @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
|
* 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);
|
const uint64_t key_digest = hash_key(key);
|
||||||
size_t idx = key_digest % map->capacity;
|
size_t idx = key_digest % map->capacity;
|
||||||
size_t delete_tracker = map->capacity; // Fallback index
|
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
|
* 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};
|
map_result_t result = {0};
|
||||||
|
|
||||||
const size_t old_capacity = map->capacity;
|
const size_t old_capacity = map->capacity;
|
||||||
@@ -174,6 +133,43 @@ map_result_t map_resize(map_t *map) {
|
|||||||
return result;
|
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_add
|
||||||
* @map: a non-null map
|
* @map: a non-null map
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#define SET_MSG(result, msg) \
|
#define SET_MSG(result, msg) \
|
||||||
do { \
|
do { \
|
||||||
snprintf((char *)(result).message, RESULT_MSG_SIZE, "%s", (const char *)msg); \
|
snprintf((char *)(result).message, RESULT_MSG_SIZE, "%s", (const char *)msg); \
|
||||||
@@ -6,6 +5,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|||||||
216
src/vector.c
216
src/vector.c
@@ -10,10 +10,112 @@
|
|||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
// Internal methods
|
// Internal methods
|
||||||
static vector_result_t vector_resize(vector_t *vector);
|
/**
|
||||||
static void swap(void *x, void *y, size_t size);
|
* vector_resize
|
||||||
static size_t partition(void *base, size_t low, size_t high, size_t size, vector_cmp_fn cmp);
|
* @vector: a non-null vector
|
||||||
static void quicksort(void *base, size_t low, size_t high, size_t size, vector_cmp_fn cmp);
|
*
|
||||||
|
* 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
|
* vector_new
|
||||||
@@ -61,112 +163,6 @@ vector_result_t vector_new(size_t size, size_t data_size) {
|
|||||||
return result;
|
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_push
|
||||||
* @vector: a non-null vector
|
* @vector: a non-null vector
|
||||||
|
|||||||
Reference in New Issue
Block a user