diff --git a/.gitignore b/.gitignore index 4b8577f..b9d81a5 100644 --- a/.gitignore +++ b/.gitignore @@ -85,7 +85,6 @@ CMakeCache.txt CMakeFiles CMakeScripts Testing -Makefile cmake_install.cmake install_manifest.txt compile_commands.json @@ -506,7 +505,6 @@ Doxyfile.docs # End of Doxygen rules DartConfiguration.tcl -Makefile build obj libft diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 2d7296d..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -cmake_minimum_required(VERSION 3.12) -project( - hashmap - VERSION 0.1 - DESCRIPTION "Harrou's and Stan's hashmap library for C" - LANGUAGES C CXX) - -# CMakeLists.txt inspired by: -# https://gitlab.com/CLIUtils/modern-cmake/tree/master/examples/extended-project - -# Only do these if this is the main project, and not if it is included through add_subdirectory -if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) - # global compilation standards - set(CMAKE_C_STANDARD 99) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wextra -pedantic") - - set(CMAKE_CXX_STANDARD 98) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra -pedantic") - - include(CTest) - - if(BUILD_TESTING) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=address") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address") - endif() - - # Let's nicely support folders in IDEs - set_property(GLOBAL PROPERTY USE_FOLDERS ON) - - # Docs only available if this is the main app - find_package(Doxygen) - if(Doxygen_FOUND) - add_subdirectory(docs) - else() - message(STATUS "Doxygen not found, not building docs") - endif() -endif() - -# FetchContent added in CMake 3.11, downloads during the configure step -include(FetchContent) - -# FetchContent_MakeAvailable was not added until CMake 3.14; use our shim -if(${CMAKE_VERSION} VERSION_LESS 3.14) - include(cmake/add_FetchContent_MakeAvailable.cmake) -endif() - - -add_subdirectory(lib) -add_subdirectory(src) - -# Testing only available if this is the main app -# Emergency override MODERN_CMAKE_BUILD_TESTING provided as well -if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR MODERN_CMAKE_BUILD_TESTING) - AND BUILD_TESTING) - add_subdirectory(tests) -endif() diff --git a/Makefile b/Makefile index ca41cd9..33c23e2 100644 --- a/Makefile +++ b/Makefile @@ -16,17 +16,36 @@ SRC_D = src INC_D = inc OBJ_D = obj LIB_D = lib -TEST_D = tests/standalone_tests - -SRC = $(SRC_D)/hash_map.c +TEST_D = tests + +SRC = $(SRC_D)/hash.c\ + $(SRC_D)/new_node.c\ + $(SRC_D)/add_node_to_history.c\ + $(SRC_D)/history_destroy.c\ + $(SRC_D)/hm_new.c\ + $(SRC_D)/hm_destroy.c\ + $(SRC_D)/find_node_by_key.c\ + $(SRC_D)/node_remove_from_list.c\ + $(SRC_D)/hm_remove.c\ + $(SRC_D)/hm_add_new_key.c\ + $(SRC_D)/hm_find_existing_node_and_replace_value.c\ + $(SRC_D)/hm_insert_node.c\ + $(SRC_D)/hm_handle_collision.c\ + $(SRC_D)/hm_set.c\ + $(SRC_D)/hm_get_seq.c\ + $(SRC_D)/hm_get.c\ + $(SRC_D)/hm_get_collision_count.c + INC = $(INC_D)/hashmap.h OBJ := $(SRC:$(SRC_D)/%.c=$(OBJ_D)/%.o) LIBFT = $(LIB_D)/libft/libft.a +LIBPAIR = $(LIB_D)/pair/pair.a LIB_INC = $(LIB_D)/libft/inc +LIB_INC_PAIR = $(LIB_D)/pair/inc CC = clang LD = ar @@ -37,34 +56,39 @@ LD_FLAGS = -rcs all: $(NAME) -$(NAME): $(LIBFT) $(OBJ_D) $(OBJ) $(INC_D) $(INC) +$(NAME): $(LIBFT) $(LIBPAIR) $(OBJ_D) $(OBJ) $(INC_D) $(INC) @$(LD) $(LD_FLAGS) $(NAME) $(OBJ) $(OBJ_D): @mkdir -p $(OBJ_D) $(OBJ): $(OBJ_D)/%.o: $(SRC_D)/%.c - @$(CC) $(CC_FLAGS) -I$(INC_D) -I$(LIB_INC) -c $< -o $@ + @$(CC) $(CC_FLAGS) -I$(INC_D) -I$(LIB_INC) -I$(LIB_INC_PAIR) -c $< -o $@ $(LIBFT): @make -C $(LIB_D)/libft +$(LIBPAIR): + @make -C $(LIB_D)/pair + clean: @rm -rf $(OBJ_D) @rm -rf *.dSYM @make -C $(LIB_D)/libft clean + @make -C $(LIB_D)/pair clean fclean: clean @rm -f $(NAME) @rm -f test @make -C $(LIB_D)/libft fclean + @make -C $(LIB_D)/pair fclean submodule: @git submodule init @git submodule update test: $(NAME) - @$(CC) $(CC_FLAGS) -I$(INC_D) -I$(LIB_INC) -o test $(TEST_D)/main.c $(NAME) $(LIBFT) + @$(CC) $(CC_FLAGS) -I$(INC_D) -I$(LIB_INC) -I$(LIB_INC_PAIR) -o test $(TEST_D)/main.c $(NAME) $(LIBFT) @./test re: fclean all diff --git a/cmake/add_FetchContent_MakeAvailable.cmake b/cmake/add_FetchContent_MakeAvailable.cmake deleted file mode 100644 index f939da8..0000000 --- a/cmake/add_FetchContent_MakeAvailable.cmake +++ /dev/null @@ -1,7 +0,0 @@ -macro(FetchContent_MakeAvailable NAME) - FetchContent_GetProperties(${NAME}) - if(NOT ${NAME}_POPULATED) - FetchContent_Populate(${NAME}) - add_subdirectory(${${NAME}_SOURCE_DIR} ${${NAME}_BINARY_DIR}) - endif() -endmacro() diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt deleted file mode 100644 index f833062..0000000 --- a/docs/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(DOXYGEN_EXTRACT_ALL YES) -set(DOXYGEN_BUILTIN_STL_SUPPORT YES) - -doxygen_add_docs(docs modern/lib.hpp "${CMAKE_CURRENT_SOURCE_DIR}/mainpage.md" - WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/include") diff --git a/docs/mainpage.md b/docs/mainpage.md deleted file mode 100644 index bf7f65e..0000000 --- a/docs/mainpage.md +++ /dev/null @@ -1,11 +0,0 @@ -# Documentation for Modern Library {#mainpage} - -This is the documentation for my simple example library. - -It is good documentation because: - -1. It exists. -2. I wrote it. -3. Everthing is documented (pretty easy since there's only one function) - -The single provided function is `::accumulate_vector`. diff --git a/inc/hashmap.h b/inc/hashmap.h index 882cfe3..74fcd34 100644 --- a/inc/hashmap.h +++ b/inc/hashmap.h @@ -10,18 +10,18 @@ /* */ /* ************************************************************************** */ -#ifndef LIBHASHMAP_H -# define LIBHASHMAP_H +#ifndef HASHMAP_H +# define HASHMAP_H -#include -#include "pair.h" +# include +# include "pair.h" -void *hm_new(size_t _size); -void hm_destroy(void *_hm, void (*f)(void *)); -void *hm_set(void *_hm, const char *_key, void *_value); -void *hm_get(const void *_hm, const char *_key); -t_pair hm_get_seq(const void *_hm); -size_t hm_get_collision_count(void *_hm); -void hm_remove(void *_hm, const char *_key, void (*_ft_delete)(void*)); +void *hm_new(size_t _size); +void hm_destroy(void *_hm, void (*f)(void *)); +void *hm_set(void *_hm, const char *_key, void *_value); +void *hm_get(const void *_hm, const char *_key); +t_pair hm_get_seq(const void *_hm); +size_t hm_get_collision_count(void *_hm); +void hm_remove(void *_hm, const char *_key, void (*_ft_delete)(void*)); #endif diff --git a/inc/hashmap_internal.h b/inc/hashmap_internal.h index 9862b3d..00814ff 100644 --- a/inc/hashmap_internal.h +++ b/inc/hashmap_internal.h @@ -1,26 +1,40 @@ -#ifndef LIBHASHMAP_INTERNAL_H -# define LIBHASHMAP_INTERNAL_H +#ifndef HASHMAP_INTERNAL_H +# define HASHMAP_INTERNAL_H # include # include # include "libft.h" # include "hashmap.h" -typedef struct s_hm_node { - char *key; - void *value; - struct s_hm_node *next; - struct s_hm_node *prev; -} t_hm_node; +typedef struct s_hm_node { + struct s_hm_node *next; + struct s_hm_node *prev; + char *key; + void *value; +} t_hm_node; -typedef struct s_hash_map { - t_hm_node **nodes; - t_hm_node *first_node; - t_hm_node *last_node; - t_hm_node *history; - size_t collisions; - size_t cap; - size_t size; -} t_hash_map; +typedef struct s_hash_map { + t_hm_node **nodes; + t_hm_node *first_node; + t_hm_node *last_node; + t_hm_node *history; + size_t collisions; + size_t cap; + size_t size; +} t_hash_map; +uint64_t hash(const size_t cap, const char *key); +t_hm_node *new_node(const char *_key, void *_value); +void add_node_to_history(t_hm_node **root, t_hm_node *node); +void history_destroy(t_hm_node *root, void (*f)(void *)); +t_hm_node *find_node_by_key(t_hm_node *_node, const char *_key); +void node_remove_from_list(t_hash_map *_hm, t_hm_node *_node); +void *hm_add_new_key(t_hash_map *hm, t_hm_node **node, + const char *_key, void *_value); +void node_destroy(t_hm_node *_to_destroy, void (*_ft_delete)(void*)); +void *hm_find_existing_node_and_replace_value(t_hash_map *hm, + t_hm_node *node_at_index, const char *_key, void *_value); +void *hm_insert_node(t_hash_map *hm, t_hm_node *node, t_hm_node *new); +void *hm_handle_collision(t_hash_map *hm, + t_hm_node *node, const char *_key, void *_value); #endif diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt deleted file mode 100644 index 493e95d..0000000 --- a/lib/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# source: https://cliutils.gitlab.io/modern-cmake/chapters/projects/submodule.html -find_package(Git QUIET) -if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") -# Update submodules as needed - option(GIT_SUBMODULE "Check submodules during build" ON) - if(GIT_SUBMODULE) - message(STATUS "Submodule update") - execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE GIT_SUBMOD_RESULT) - if(NOT GIT_SUBMOD_RESULT EQUAL "0") - message(FATAL_ERROR "git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules") - endif() - endif() -endif() - -#if(NOT EXISTS "${PROJECT_SOURCE_DIR}/extern/repo/CMakeLists.txt") -# message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.") -#endif() - -if (NOT TARGET ft) - add_subdirectory(libft) -endif() -if (NOT TARGET pair) - add_subdirectory(pair) -endif() diff --git a/lib/pair b/lib/pair index 6295fb3..c5d47c2 160000 --- a/lib/pair +++ b/lib/pair @@ -1 +1 @@ -Subproject commit 6295fb334af42b1581e0cd7d15d739c56856d33b +Subproject commit c5d47c25da3eee59303719176190d084da2a7bbd diff --git a/minimake.sh b/minimake.sh deleted file mode 100755 index 882f28e..0000000 --- a/minimake.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# https://github.com/s-t-a-n -build_dir=build - -if [ $# -eq 1 ] && [ "$1" == "test" ]; then - # compile and test - cmake -S . -B $build_dir -DBUILD_TESTING=ON && ( cd $build_dir && make ) \ - && ( cd $build_dir && ctest --output-on-failure ./) \ - && echo -e "Tests ran: \e[92mok\e[39m." \ - || { echo -e "Tests ran: \e[91mNOPE\e[39m."; false; } -elif [ $# -eq 1 ] && [ "$1" == "clean" ]; then - # clean all files which are specified in .gitignore - git clean -d -f -X -elif [ $# -eq 0 ]; then - # compile and copy hashmap binary and lib to root folder - cmake -S . -B $build_dir -DBUILD_TESTING=OFF && ( cd $build_dir && make ) \ - && cp $build_dir/src/libhashmap.a ./ \ - && echo -e "You can include \e[92mlibhashmap.a\e[39m in your library." \ - || { echo -e "Compilation ran: \e[91mNOPE\e[39m."; false; } -else - cat<<-EOF - usage: - $0 -> compile - $0 test -> compile and test - $0 clean -> remove build files - EOF -fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index f16d460..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Note that headers are optional, and do not affect add_library, but they will not -# show up in IDEs unless they are listed in add_library. - -# Optionally glob, but only for CMake 3.12 or later: -file(GLOB HEADER_LIST CONFIGURE_DEPENDS "${hashmap_SOURCE_DIR}/inc/*.h") -file(GLOB SRC_LIST CONFIGURE_DEPENDS "${hashmap_SOURCE_DIR}/src/*.c") -file(GLOB SRC_SUBROOT_LIST CONFIGURE_DEPENDS "${hashmap_SOURCE_DIR}/src/*/*.c") - -# Make an automatic library - will be static or dynamic based on user setting -add_library(hashmap ${SRC_LIST} ${SRC_SUBROOT_LIST} ${HEADER_LIST}) - -# Set the compilation standards -set_property(TARGET hashmap PROPERTY C_STANDARD 99) - -# We need this directory, and users of our library will need it too -target_include_directories(hashmap PUBLIC ../inc) - -# This depends on (header only) boost -target_link_libraries(hashmap PRIVATE ft pair) - -# IDEs should put the headers in a nice place -source_group( - TREE "${PROJECT_SOURCE_DIR}/inc" - PREFIX "Header Files" - FILES ${HEADER_LIST}) diff --git a/src/add_node_to_history.c b/src/add_node_to_history.c new file mode 100644 index 0000000..134674e --- /dev/null +++ b/src/add_node_to_history.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void add_node_to_history(t_hm_node **root, t_hm_node *node) +{ + t_hm_node *lst; + + if (!*root) + { + (*root) = node; + } + else + { + lst = *root; + while (lst->next) + lst = lst->next; + lst->next = node; + } +} diff --git a/src/find_node_by_key.c b/src/find_node_by_key.c new file mode 100644 index 0000000..740a26d --- /dev/null +++ b/src/find_node_by_key.c @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +t_hm_node *find_node_by_key(t_hm_node *_node, const char *_key) +{ + while (_node) + { + if (ft_strcmp(_key, _node->key) == 0) + break ; + _node = _node->next; + } + if (!_node || ft_strcmp(_key, _node->key) != 0) + return (NULL); + return (_node); +} diff --git a/src/hash.c b/src/hash.c new file mode 100644 index 0000000..bf51f9a --- /dev/null +++ b/src/hash.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +uint64_t hash(const size_t cap, const char *key) +{ + uint64_t value; + size_t i; + size_t length; + + value = 0; + i = 0; + length = ft_strlen(key); + while (i < length) + { + value = value * 37 + key[i]; + i++; + } + value = value % cap; + return (value); +} diff --git a/src/hash_map.c b/src/hash_map.c deleted file mode 100644 index a72e66e..0000000 --- a/src/hash_map.c +++ /dev/null @@ -1,351 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* :::::::: */ -/* main.c :+: :+: */ -/* +:+ */ -/* By: haachtch +#+ */ -/* +#+ */ -/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ -/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ -/* */ -/* ************************************************************************** */ - -#include - -#include "hashmap_internal.h" - -static uint64_t hash(const size_t cap, const char *key) -{ - uint64_t value; - size_t i; - size_t length; - - value = 0; - i = 0; - length = ft_strlen(key); - while (i < length) - { - value = value * 37 + key[i]; - i++; - } - value = value % cap; - return (value); -} - -static t_hm_node *new_node(const char *_key, void *_value) -{ - t_hm_node *node; - - node = ft_calloc(sizeof(t_hm_node), 1); - if (node) - { - node->key = ft_strdup(_key); - node->value = _value; - } - return (node); -} - -static void add_node_to_history(t_hm_node **root, t_hm_node *node) -{ - t_hm_node *lst; - - if (!*root) - { - (*root) = node; - } - else - { - lst = *root; - while(lst->next) - lst = lst->next; - lst->next = node; - } -} - -static void history_destroy(t_hm_node *root, void (*f)(void *)) -{ - t_hm_node *prev; - - while(root) - { - prev = root; - root = root->next; - f(prev->value); - free(prev->key); - free(prev); - } -} - -void *hm_new(size_t _cap) -{ - t_hash_map *hm; - - if (_cap == 0) - return (NULL); - hm = ft_calloc(sizeof(t_hash_map), 1); - hm->nodes = ft_calloc(sizeof(t_hm_node*), _cap); - hm->cap = _cap; - return ((void *)hm); -} - -void hm_destroy(void *_hm, void (*f)(void *)) -{ - t_hash_map *hm; - t_hm_node *node; - t_hm_node *dnode; - - hm = (t_hash_map *)_hm; - node = hm->first_node; - while(node) - { - dnode = node; - node = node->next; - f(dnode->value); - free(dnode->key); - free(dnode); - } - free(hm->nodes); - history_destroy(hm->history, f); - free(hm); -} - -static t_hm_node *find_node_by_key(t_hm_node *_node, const char *_key) -{ - while(_node) - { - if (ft_strcmp(_key, _node->key) == 0) - break ; - _node = _node->next; - } - if (!_node || ft_strcmp(_key, _node->key) != 0) - return (NULL); - return (_node); -} - -static void node_remove_from_list(t_hash_map *_hm, t_hm_node *_node) -{ - if (_node->prev) - _node->prev->next = _node->next; - else - _hm->first_node = _node->next; - if (_node->next) - _node->next->prev = _node->prev; - else - _hm->last_node = _node->prev; -} - -void node_destroy(t_hm_node *_to_destroy, void (*_ft_delete)(void*)) -{ - free(_to_destroy->key); - _ft_delete(_to_destroy->value); - free(_to_destroy); -} - -void hm_remove(void *_hm, const char *_key, void (*_ft_delete)(void*)) -{ - t_hash_map *hm; - t_hm_node **to_remove; - - hm = (t_hash_map *)_hm; - to_remove = &hm->nodes[hash(hm->cap, _key)]; - if (*to_remove) - { - if (ft_strcmp((*to_remove)->key, _key) != 0) - { - if (!(*to_remove)->next) - return; - *to_remove = find_node_by_key((*to_remove)->next, _key); - if (!*to_remove) - return; - } - node_remove_from_list(_hm, *to_remove); - node_destroy(*to_remove, _ft_delete); - } -} - -static void *hm_add_new_key(t_hash_map *hm, - t_hm_node **node, - const char *_key, - void *_value) -{ - *node = new_node(_key, _value); - if (*node) - { - hm->size++; - if (!hm->last_node) - { - assert(!hm->first_node); - hm->first_node = *node; - hm->last_node = *node; - } - else - { - hm->last_node->next = *node; - (*node)->prev = hm->last_node; - hm->last_node = *node; - } - return (_value); - } - else - return (NULL); -} - -static void *hm_find_existing_node_and_replace_value(t_hash_map *hm, - t_hm_node *node_at_index, - const char *_key, - void *_value) -{ - void *old_value; - t_hm_node *prev; - - assert(node_at_index); - assert(_key); - prev = node_at_index; - while (node_at_index->next) - { - node_at_index = node_at_index->next; - if (ft_strcmp(node_at_index->key, _key) == 0) - { - /* we found the same key */ - old_value = node_at_index->value; - - /* dead key, add to history -> IS THIS NECCESSARY?*/ - add_node_to_history(&hm->history, new_node(node_at_index->key, old_value)); - - node_at_index->value = _value; - return (NULL); - } - prev = node_at_index; - } - return (prev); -} - -static void *hm_insert_node(t_hash_map *hm, t_hm_node *node, t_hm_node *new) -{ - assert(node); - assert(new); - if (node->next) { - t_hm_node *node_next = node->next; - node->next = new; - new->prev = node; - new->next = node_next; - node_next->prev = new; - } - else { - node->next = new; - node->next->prev = node; - hm->last_node = new; - } - hm->size++; - return (new->value); -} - -static void *hm_handle_collision(t_hash_map *hm, - t_hm_node *node, - const char *_key, - void *_value) -{ - t_hm_node *last; - - last = hm_find_existing_node_and_replace_value(hm, node, _key, _value); - if (!last) /* NULL indicates a key was found */ - return (_value); - - /* only gets here if this is a different key */ - return (hm_insert_node(hm, node, new_node(_key, _value))); -} - -void *hm_set(void *_hm, - const char *_key, - void *_value) -{ - void *old_value; - t_hash_map *hm; - t_hm_node **node; - - if (_key == NULL) - return (NULL); - hm = (t_hash_map *)_hm; - node = &hm->nodes[hash(hm->cap, _key)]; - if (*node) - { - if (ft_strcmp((*node)->key, _key) != 0) - { - /* a collision happened */ - hm->collisions++; - assert(hm->first_node); - assert(hm->last_node); - assert(((*node)->prev || (*node)->next) || hm->size == 1); - return (hm_handle_collision(hm, *node, _key, _value)); - } - else - { - /* update value for key */ - hm->size++; - old_value = (*node)->value; - (*node)->value = _value; - - /* store ref to old value here */ - add_node_to_history(&hm->history, new_node((*node)->key, old_value)); - return ((*node)->value); - } - } - else - return (hm_add_new_key(hm, node, _key, _value)); -} - -t_pair hm_get_seq(const void *_hm) -{ - const t_hash_map *hm = (t_hash_map *)_hm; - static t_hm_node *node; - t_pair pair; - - node = node ? node->next : hm->first_node; - if (node) - { - pair.f.key = node->key; - pair.s.value = node->value; - } - else - { - node = hm->first_node; - pair.f.key = NULL; - pair.s.value = NULL; - } - return (pair); -} - -void *hm_get(const void *_hm, const char *_key) -{ - const t_hash_map *hm = (t_hash_map *)_hm; - t_hm_node *node; - - if (_key == NULL) - return (NULL); - node = hm->nodes[hash(hm->cap, _key)]; - - /* verify with strcmp if key is actually key ? */ - - if (node && node->next) - { - /* check for collision */ - while (node) - { - if (ft_strcmp(node->key, _key) == 0) - return (node->value); - node = node->next; - } - return (NULL); - } - else if (node) - return (node->value); - else - return (NULL); -} - -size_t hm_get_collision_count(void *_hm) -{ - const t_hash_map *hm = (t_hash_map *)_hm; - - return (hm->collisions); -} diff --git a/src/history_destroy.c b/src/history_destroy.c new file mode 100644 index 0000000..2307d8f --- /dev/null +++ b/src/history_destroy.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void history_destroy(t_hm_node *root, void (*f)(void *)) +{ + t_hm_node *prev; + + while (root) + { + prev = root; + root = root->next; + f(prev->value); + free(prev->key); + free(prev); + } +} diff --git a/src/hm_add_new_key.c b/src/hm_add_new_key.c new file mode 100644 index 0000000..797d596 --- /dev/null +++ b/src/hm_add_new_key.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void *hm_add_new_key(t_hash_map *hm, + t_hm_node **node, + const char *_key, + void *_value) +{ + *node = new_node(_key, _value); + if (*node) + { + hm->size++; + if (!hm->last_node) + { + hm->first_node = *node; + hm->last_node = *node; + } + else + { + hm->last_node->next = *node; + (*node)->prev = hm->last_node; + hm->last_node = *node; + } + return (_value); + } + else + return (NULL); +} diff --git a/src/hm_destroy.c b/src/hm_destroy.c new file mode 100644 index 0000000..84f4319 --- /dev/null +++ b/src/hm_destroy.c @@ -0,0 +1,34 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void hm_destroy(void *_hm, void (*f)(void *)) +{ + t_hash_map *hm; + t_hm_node *node; + t_hm_node *dnode; + + hm = (t_hash_map *)_hm; + node = hm->first_node; + while (node) + { + dnode = node; + node = node->next; + f(dnode->value); + free(dnode->key); + free(dnode); + } + free(hm->nodes); + history_destroy(hm->history, f); + free(hm); +} diff --git a/src/hm_find_existing_node_and_replace_value.c b/src/hm_find_existing_node_and_replace_value.c new file mode 100644 index 0000000..430890a --- /dev/null +++ b/src/hm_find_existing_node_and_replace_value.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void *hm_find_existing_node_and_replace_value(t_hash_map *hm, + t_hm_node *node_at_index, + const char *_key, + void *_value) +{ + void *old_value; + t_hm_node *prev; + + prev = node_at_index; + while (node_at_index->next) + { + node_at_index = node_at_index->next; + if (ft_strcmp(node_at_index->key, _key) == 0) + { + old_value = node_at_index->value; + add_node_to_history(&hm->history, + new_node(node_at_index->key, old_value)); + node_at_index->value = _value; + return (NULL); + } + prev = node_at_index; + } + return (prev); +} diff --git a/src/hm_get.c b/src/hm_get.c new file mode 100644 index 0000000..f20811a --- /dev/null +++ b/src/hm_get.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void *hm_get(const void *_hm, const char *_key) +{ + const t_hash_map *hm = (t_hash_map *)_hm; + t_hm_node *node; + + if (_key == NULL) + return (NULL); + node = hm->nodes[hash(hm->cap, _key)]; + if (node && node->next) + { + while (node) + { + if (ft_strcmp(node->key, _key) == 0) + return (node->value); + node = node->next; + } + return (NULL); + } + else if (node) + return (node->value); + else + return (NULL); +} diff --git a/src/hm_get_collision_count.c b/src/hm_get_collision_count.c new file mode 100644 index 0000000..954bd96 --- /dev/null +++ b/src/hm_get_collision_count.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +size_t hm_get_collision_count(void *_hm) +{ + const t_hash_map *hm = (t_hash_map *)_hm; + + return (hm->collisions); +} diff --git a/src/hm_get_seq.c b/src/hm_get_seq.c new file mode 100644 index 0000000..7359ac0 --- /dev/null +++ b/src/hm_get_seq.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +t_pair hm_get_seq(const void *_hm) +{ + const t_hash_map *hm = (t_hash_map *)_hm; + static t_hm_node *node; + t_pair pair; + + if (node) + node = node->next; + else + node = hm->first_node; + if (node) + { + pair.u_f.key = node->key; + pair.u_s.value = node->value; + } + else + { + node = hm->first_node; + pair.u_f.key = NULL; + pair.u_s.value = NULL; + } + return (pair); +} diff --git a/src/hm_handle_collision.c b/src/hm_handle_collision.c new file mode 100644 index 0000000..46d595f --- /dev/null +++ b/src/hm_handle_collision.c @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void *hm_handle_collision(t_hash_map *hm, + t_hm_node *node, + const char *_key, + void *_value) +{ + t_hm_node *last; + + last = hm_find_existing_node_and_replace_value(hm, node, _key, _value); + if (!last) + return (_value); + return (hm_insert_node(hm, node, new_node(_key, _value))); +} diff --git a/src/hm_insert_node.c b/src/hm_insert_node.c new file mode 100644 index 0000000..f0fe0e4 --- /dev/null +++ b/src/hm_insert_node.c @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void *hm_insert_node(t_hash_map *hm, t_hm_node *node, t_hm_node *new) +{ + t_hm_node *node_next; + + if (node->next) + { + node_next = node->next; + node->next = new; + new->prev = node; + new->next = node_next; + node_next->prev = new; + } + else + { + node->next = new; + node->next->prev = node; + hm->last_node = new; + } + hm->size++; + return (new->value); +} diff --git a/src/hm_new.c b/src/hm_new.c new file mode 100644 index 0000000..17ec650 --- /dev/null +++ b/src/hm_new.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void *hm_new(size_t _cap) +{ + t_hash_map *hm; + + if (_cap == 0) + return (NULL); + hm = ft_calloc(sizeof(t_hash_map), 1); + hm->nodes = ft_calloc(sizeof(t_hm_node *), _cap); + hm->cap = _cap; + return ((void *)hm); +} diff --git a/src/hm_remove.c b/src/hm_remove.c new file mode 100644 index 0000000..e924119 --- /dev/null +++ b/src/hm_remove.c @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void hm_remove(void *_hm, const char *_key, void (*_ft_delete)(void*)) +{ + t_hash_map *hm; + t_hm_node **to_remove; + + hm = (t_hash_map *)_hm; + to_remove = &hm->nodes[hash(hm->cap, _key)]; + if (*to_remove) + { + if (ft_strcmp((*to_remove)->key, _key) != 0) + { + if (!(*to_remove)->next) + return ; + *to_remove = find_node_by_key((*to_remove)->next, _key); + if (!*to_remove) + return ; + } + node_remove_from_list(_hm, *to_remove); + node_destroy(*to_remove, _ft_delete); + } +} diff --git a/src/hm_set.c b/src/hm_set.c new file mode 100644 index 0000000..adb39e0 --- /dev/null +++ b/src/hm_set.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +static void *__set(t_hash_map *hm, t_hm_node **node, + const char *_key, void *_value) +{ + void *old_value; + + if (ft_strcmp((*node)->key, _key) != 0) + { + hm->collisions++; + return (hm_handle_collision(hm, *node, _key, _value)); + } + else + { + hm->size++; + old_value = (*node)->value; + (*node)->value = _value; + add_node_to_history(&hm->history, new_node((*node)->key, + old_value)); + return ((*node)->value); + } +} + +void *hm_set(void *_hm, + const char *_key, + void *_value) +{ + t_hash_map *hm; + t_hm_node **node; + + if (_key == NULL) + return (NULL); + hm = (t_hash_map *)_hm; + node = &hm->nodes[hash(hm->cap, _key)]; + if (*node) + return (__set(hm, node, _key, _value)); + else + return (hm_add_new_key(hm, node, _key, _value)); +} diff --git a/src/new_node.c b/src/new_node.c new file mode 100644 index 0000000..364e3da --- /dev/null +++ b/src/new_node.c @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +t_hm_node *new_node(const char *_key, void *_value) +{ + t_hm_node *node; + + node = ft_calloc(sizeof(t_hm_node), 1); + if (node) + { + node->key = ft_strdup(_key); + node->value = _value; + } + return (node); +} diff --git a/src/node_destroy.c b/src/node_destroy.c new file mode 100644 index 0000000..9505c2a --- /dev/null +++ b/src/node_destroy.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void node_destroy(t_hm_node *_to_destroy, void (*_ft_delete)(void*)) +{ + free(_to_destroy->key); + _ft_delete(_to_destroy->value); + free(_to_destroy); +} diff --git a/src/node_remove_from_list.c b/src/node_remove_from_list.c new file mode 100644 index 0000000..ec1fea9 --- /dev/null +++ b/src/node_remove_from_list.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: haachtch +#+ */ +/* +#+ */ +/* Created: 2020/07/13 09:34:21 by haachtch #+# #+# */ +/* Updated: 2020/09/03 14:12:42 by haachtch ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "hashmap_internal.h" + +void node_remove_from_list(t_hash_map *_hm, t_hm_node *_node) +{ + if (_node->prev) + _node->prev->next = _node->next; + else + _hm->first_node = _node->next; + if (_node->next) + _node->next->prev = _node->prev; + else + _hm->last_node = _node->prev; +} diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index a8a0dce..0000000 --- a/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.bin diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index eb076fa..0000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -FetchContent_Declare( - Catch2 - GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v2.13.4) -FetchContent_MakeAvailable(Catch2) - -#### Combined unittest - -if((CMAKE_PROJECT_NAME STREQUAL hashmap OR MODERN_CMAKE_BUILD_TESTING)) - set (TEST "test-all") - file(GLOB SRC_LIST CONFIGURE_DEPENDS "src/*.cpp") - - add_executable(${TEST}.bin ${SRC_LIST}) - target_compile_features(${TEST}.bin PRIVATE cxx_std_14) - target_link_libraries(${TEST}.bin PRIVATE Catch2::Catch2WithMain) - target_link_libraries(${TEST}.bin PRIVATE hashmap ft pair) - add_test(NAME ${TEST} - COMMAND ${TEST}.bin) -endif() - -#### Individual unittests - -### Hashmap unittest -set (TEST "test-hashmap") -set (SRC_LIST "src/hashmap.cpp") - -add_executable(${TEST}.bin ${MAIN} ${SRC_LIST}) -target_compile_features(${TEST}.bin PRIVATE cxx_std_14) -target_link_libraries(${TEST}.bin PRIVATE Catch2::Catch2WithMain) -target_link_libraries(${TEST}.bin PRIVATE hashmap ft pair) -add_test(NAME ${TEST} - COMMAND ${TEST}.bin) - -### Hashmap unittest -set (TEST "test-hashmap-collision") -set (SRC_LIST "src/hashmap_collisions.cpp") - -add_executable(${TEST}.bin ${MAIN} ${SRC_LIST}) -target_compile_features(${TEST}.bin PRIVATE cxx_std_14) -target_link_libraries(${TEST}.bin PRIVATE Catch2::Catch2WithMain) -target_link_libraries(${TEST}.bin PRIVATE hashmap ft pair) -add_test(NAME ${TEST} - COMMAND ${TEST}.bin) diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index 612493f..0000000 --- a/tests/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Catch2 Unittesting library - -### Source - https://github.com/catchorg/Catch2 diff --git a/tests/standalone_tests/main.c b/tests/main.c similarity index 88% rename from tests/standalone_tests/main.c rename to tests/main.c index 5944f31..a0cc930 100644 --- a/tests/standalone_tests/main.c +++ b/tests/main.c @@ -4,8 +4,8 @@ #include "hashmap_internal.h" #include "libft.h" -size_t nb_nodes = 1400; -size_t hm_size = 1000; +size_t nb_nodes = 10; +size_t hm_size = 10; void run_key_null_test(void *hashmap) { @@ -44,11 +44,13 @@ void generate_nodes(void *hashmap) void print_hashmap(void *hashmap) { - t_kv_pair pair; + t_pair pair; printf("----------------Print hash map----------------->\n\n"); - while ((pair = hm_get_seq(hashmap)).key != NULL) + pair = hm_get_seq(hashmap); + while ((pair.u_f.key != NULL)) { - printf("%s -> %s\n", pair.key, (char *)pair.value); + printf("%s -> %s\n", pair.u_f.key, (char *)pair.u_s.value); + pair = hm_get_seq(hashmap); } printf("------------------------------------------------\n\n"); } @@ -62,7 +64,7 @@ void run_loop_test(void *hashmap) void check_for_leaks(void *hashmap) { - hm_destroy(hashmap); + hm_destroy(hashmap, free); system("leaks a.out"); } diff --git a/tests/src/hashmap.cpp b/tests/src/hashmap.cpp deleted file mode 100644 index 3e6e184..0000000 --- a/tests/src/hashmap.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include - -/* - * Catch2: examples - * for more examples checkout: - * https://github.com/catchorg/Catch2/tree/devel/examples - * - * Catch has two natural expression assertion macro's: - * - REQUIRE() stops at first failure. - * - CHECK() continues after failure. - * - * There are two variants to support decomposing negated expressions: - * - REQUIRE_FALSE() stops at first failure. - * - CHECK_FALSE() continues after failure. - * - * TEST_CASE( "Title here", "[short name]" ) { - * REQUIRE( [BOOLEAN CONDITION] ) ; - * } - */ - -extern "C" { -# include "hashmap.h" -# include "libft.h" -} - -#include -#define HM_SIZE 100 - -TEST_CASE( "create_destroy hashmap", "[hashmap]" ) { - void *hashmap = hm_new(HM_SIZE); - REQUIRE(hashmap != NULL); - hm_destroy(hashmap, free); -} - -TEST_CASE( "hm_set hashmap", "[hashmap]" ) { - void *hashmap = hm_new(HM_SIZE); - int i = 0; - while(i < 5) - { - char *key = ft_strdup("HELLO"); - char *value = ft_strdup("this"); - REQUIRE(hm_set(hashmap, key, value) != NULL); - free(key); - i++; - } - hm_destroy(hashmap, free); -} - -TEST_CASE("hm_set further testing", "[hashmap]") -{ - void *hashmap = hm_new(HM_SIZE); - extern char **environ; - char **env = environ; - int i = 0; - while (i < 15) - { - char *key = ft_substr(env[i], 0, 5); - char *value = ft_substr(env[i], 6, ft_strlen(env[i])); - REQUIRE(hm_set(hashmap, key, value) != NULL); - free(key); - i++; - } - hm_destroy(hashmap, free); -} - -TEST_CASE("hm_remove test", "[hashmap]") -{ - void *hashmap = hm_new(HM_SIZE); - extern char **environ; - char **env = environ; - int i = 0; - while (i < 15) - { - char *key = ft_substr(env[i], 0, 5); - char *value = ft_substr(env[i], 6, ft_strlen(env[i])); - REQUIRE(hm_set(hashmap, key, value) != NULL); - free(key); - i++; - } - char *to_remove = ft_strdup("SHELL"); - hm_remove(hashmap, to_remove, free); - free(to_remove); - hm_destroy(hashmap, free); -} - diff --git a/tests/src/hashmap_collisions.cpp b/tests/src/hashmap_collisions.cpp deleted file mode 100644 index 58e4b76..0000000 --- a/tests/src/hashmap_collisions.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include - -/* - * Catch2: examples - * for more examples checkout: - * https://github.com/catchorg/Catch2/tree/devel/examples - * - * Catch has two natural expression assertion macro's: - * - REQUIRE() stops at first failure. - * - CHECK() continues after failure. - * - * There are two variants to support decomposing negated expressions: - * - REQUIRE_FALSE() stops at first failure. - * - CHECK_FALSE() continues after failure. - * - * TEST_CASE( "Title here", "[short name]" ) { - * REQUIRE( [BOOLEAN CONDITION] ) ; - * } - */ - -extern "C" { -# include "hashmap.h" -# include "libft.h" -} - -#include - -#define TEST_SIZE 256 - -void __randinit() -{ - static bool israndinit; - - if (!israndinit) { - srand(time(NULL)); - israndinit = true; - } -} - -char get_random_char() -{ - char c; - __randinit(); - - c = rand() % 127; - while (!isprint(c)) { - c = rand() % 127; - } - return (c); -} - -static void fill_string_with_random_ascii(char *buf, size_t buflen) -{ - for (size_t i = 0; i < buflen; i++) { - buf[i] = get_random_char(); - } - buf[buflen - 1] = '\0'; -} - -TEST_CASE( "basics", "[hashmap]" ) { - const size_t max_size = TEST_SIZE; - for (size_t size = 1; size < max_size; size++) { - void *hm = hm_new(size); - REQUIRE(hm != NULL); - hm_destroy(hm, free); - } - REQUIRE(hm_new(0) == NULL); -} - -TEST_CASE( "collisions with various sizes", "[hashmap]" ) { - const size_t max_size = TEST_SIZE; - for (size_t size = 1; size < max_size; size++) { - void *hm = hm_new(size); - REQUIRE(hm != NULL); - hm_destroy(hm, free); - } -} - -TEST_CASE( "collisions with various sizes and multiple of the same key", "[hashmap]" ) { - const size_t max_size = TEST_SIZE; - char *key = (char *)"key"; - char *value = (char *)"value"; - - for (size_t size = 1; size < max_size; size++) { - void *hm = hm_new(size); - REQUIRE(hm != NULL); - - for (size_t i = 0; i < TEST_SIZE; i++) { - char *v = ft_strdup(value); - REQUIRE(hm_set(hm, key, v) != NULL); - } - CHECK(hm_get(hm, key)); - CHECK(strcmp((char *)hm_get(hm, key), value) == 0); - hm_destroy(hm, free); - } -} - -TEST_CASE( "collisions with various sizes and different keys", "[hashmap]" ) { - const size_t max_size = TEST_SIZE; - for (size_t size = 1; size < max_size; size++) { - void *hm = hm_new(size); - REQUIRE(hm != NULL); - - for (size_t i = 0; i < TEST_SIZE; i++) { - char *key = (char *)malloc(TEST_SIZE); - key[TEST_SIZE - 1] = '\0'; - char *value = ft_strdup("value"); - CHECK(hm_set(hm, key, value) != NULL); - free(key); - } - hm_destroy(hm, free); - } -} - -TEST_CASE( "collisions for random keys/values with various sizes and different keys", "[hashmap]" ) { - const size_t max_size = TEST_SIZE; - for (size_t size = 1; size < max_size; size++) { - void *hm = hm_new(size); - REQUIRE(hm != NULL); - - for (size_t i = 1; i < TEST_SIZE; i++) { - const size_t keylen = i; - const size_t valuelen = i; - char *key = (char *)malloc(keylen); - fill_string_with_random_ascii(key, keylen); - char *value = (char *)malloc(valuelen); - fill_string_with_random_ascii(value, valuelen); - CHECK(hm_set(hm, key, value) != NULL); - free(key); - } - hm_destroy(hm, free); - } -} diff --git a/tests/src/stub-test.cpp b/tests/src/stub-test.cpp deleted file mode 100644 index ff9f4d2..0000000 --- a/tests/src/stub-test.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -/* - * Catch2: examples - * for more examples checkout: - * https://github.com/catchorg/Catch2/tree/devel/examples - * - * Catch has two natural expression assertion macro's: - * - REQUIRE() stops at first failure. - * - CHECK() continues after failure. - * - * There are two variants to support decomposing negated expressions: - * - REQUIRE_FALSE() stops at first failure. - * - CHECK_FALSE() continues after failure. - * - * TEST_CASE( "Title here", "[short name]" ) { - * REQUIRE( [BOOLEAN CONDITION] ) ; - * } - */ - -/* -extern "C" { -#include "[YOUR_C_LIBRARY]" -} -*/ - -TEST_CASE( "Title here", "[short name]" ) { - const bool condition = true; - REQUIRE(condition) ; -} diff --git a/tests/src/test.cpp.template b/tests/src/test.cpp.template deleted file mode 100644 index ff9f4d2..0000000 --- a/tests/src/test.cpp.template +++ /dev/null @@ -1,29 +0,0 @@ -#include -/* - * Catch2: examples - * for more examples checkout: - * https://github.com/catchorg/Catch2/tree/devel/examples - * - * Catch has two natural expression assertion macro's: - * - REQUIRE() stops at first failure. - * - CHECK() continues after failure. - * - * There are two variants to support decomposing negated expressions: - * - REQUIRE_FALSE() stops at first failure. - * - CHECK_FALSE() continues after failure. - * - * TEST_CASE( "Title here", "[short name]" ) { - * REQUIRE( [BOOLEAN CONDITION] ) ; - * } - */ - -/* -extern "C" { -#include "[YOUR_C_LIBRARY]" -} -*/ - -TEST_CASE( "Title here", "[short name]" ) { - const bool condition = true; - REQUIRE(condition) ; -}