├── .gitattributes ├── .github └── workflows │ └── cmake.yml ├── msvc ├── test-cstl.vcxproj.filters ├── cstl.sln ├── cstl.vcxproj.filters ├── cstl.vcxproj └── test-cstl.vcxproj ├── inc ├── c_iterator.h ├── c_algorithms.h ├── rb-tree.h ├── c_set.h ├── c_list.h ├── c_deque.h ├── c_errors.h ├── c_array.h ├── c_map.h └── c_stl_lib.h ├── CMakeLists.txt ├── src ├── c_algorithms.c ├── c_util.c ├── c_set.c ├── c_list.c ├── c_deque.c ├── c_array.c ├── c_map.c └── rb-tree.c ├── .gitignore ├── test ├── t_clib.c ├── t_c_deque.c ├── t_c_set.c ├── t_c_slist.c ├── t_c_algorithms.c ├── t_c_map.c ├── t_c_rb.c └── t_c_array.c ├── .clang-format └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | os: [ubuntu-latest, macos-latest, windows-latest] 14 | build: [Release, Debug] 15 | 16 | runs-on: ${{ matrix.os }} 17 | 18 | env: 19 | BUILD_TYPE: ${{ matrix.build }} 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | 24 | - name: Configure CMake 25 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} 26 | 27 | - name: Build 28 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} 29 | 30 | - name: Test on Windows 31 | if: matrix.os == 'windows-latest' 32 | run: ${{github.workspace}}/build/${{env.BUILD_TYPE}}/test-cstl.exe 33 | 34 | - name: Test on linux and macos 35 | if: runner.os != 'Windows' 36 | run: ${{github.workspace}}/build/test-cstl 37 | -------------------------------------------------------------------------------- /msvc/test-cstl.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source Files 6 | 7 | 8 | Source Files 9 | 10 | 11 | Source Files 12 | 13 | 14 | Source Files 15 | 16 | 17 | Source Files 18 | 19 | 20 | Source Files 21 | 22 | 23 | Source Files 24 | 25 | 26 | Source Files 27 | 28 | 29 | 30 | 31 | {B4B10EE7-BF3F-325B-8FBB-8B1F07CCB69E} 32 | 33 | 34 | -------------------------------------------------------------------------------- /inc/c_iterator.h: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 23 | 24 | #ifndef __C_STL_ITERATOR_H__ 25 | #define __C_STL_ITERATOR_H__ 26 | 27 | #endif /* __C_STL_ITERATOR_H__ */ 28 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(cstl) 3 | 4 | include(CMakeDependentOption) 5 | 6 | set(CMAKE_CXX_STANDARD 11) 7 | 8 | set(CSTL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "cstl library root directory" FORCE) 9 | 10 | cmake_dependent_option(BUILD_CSTL_TESTING 11 | "Build both cstl library and testing or build Library only" 12 | ON "CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF) 13 | 14 | if (UNIX) 15 | add_definitions(-Wall -Werror -ggdb3 -std=c90 -Wextra -pedantic) 16 | add_definitions("-D_DEFAULT_SOURCE -D_GNU_SOURCE") 17 | endif() 18 | 19 | if (MSVC) 20 | add_compile_options(/wd4996) 21 | endif() 22 | 23 | set(CSTL_SRC_FILES 24 | inc/c_algorithms.h 25 | inc/c_array.h 26 | inc/c_deque.h 27 | inc/c_errors.h 28 | inc/c_iterator.h 29 | inc/c_stl_lib.h 30 | inc/c_list.h 31 | inc/c_map.h 32 | inc/rb-tree.h 33 | inc/c_set.h 34 | src/c_algorithms.c 35 | src/c_array.c 36 | src/c_deque.c 37 | src/c_list.c 38 | src/c_map.c 39 | src/rb-tree.c 40 | src/c_set.c 41 | src/c_util.c 42 | ) 43 | 44 | set(CSTL_TEST_FILES 45 | test/t_c_algorithms.c 46 | test/t_c_array.c 47 | test/t_c_deque.c 48 | test/t_c_map.c 49 | test/t_c_rb.c 50 | test/t_c_set.c 51 | test/t_c_slist.c 52 | test/t_clib.c 53 | ) 54 | 55 | include_directories(inc) 56 | 57 | add_library(cstl STATIC ${CSTL_SRC_FILES}) 58 | 59 | if (BUILD_CSTL_TESTING) 60 | add_executable(test-cstl ${CSTL_TEST_FILES}) 61 | target_link_libraries(test-cstl cstl) 62 | endif() 63 | -------------------------------------------------------------------------------- /inc/c_algorithms.h: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | #ifndef __C_STL_ALGORITHMS__ 25 | #define __C_STL_ALGORITHMS__ 26 | 27 | struct cstl_iterator; 28 | 29 | extern void 30 | cstl_for_each(struct cstl_iterator* pIterator, 31 | void (*fn)(const void* value, const void* key, void* p), void* p); 32 | 33 | #endif /* __C_STL_ALGORITHMS__ */ 34 | -------------------------------------------------------------------------------- /src/c_algorithms.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include 26 | #include "c_stl_lib.h" 27 | 28 | void cstl_for_each(struct cstl_iterator* pIterator, 29 | void (*fn)(const void* value, const void* key, void* p), 30 | void* p) 31 | { 32 | const void* pElement; 33 | if (pIterator == NULL || fn == NULL) { 34 | return; 35 | } 36 | while ((pElement = pIterator->next(pIterator)) != NULL) { 37 | const void* value = pIterator->current_value(pIterator); 38 | const void* key = 39 | pIterator->current_key ? pIterator->current_key(pIterator) : NULL; 40 | fn(value, key, p); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /inc/rb-tree.h: -------------------------------------------------------------------------------- 1 | #ifndef __RB_TREE_H__ 2 | #define __RB_TREE_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | typedef enum { rbt_red = 0, rbt_black = 1 } rbt_color; 11 | 12 | typedef enum { 13 | rbt_status_success = 0, 14 | rbt_status_memory_out = -1, 15 | rbt_status_key_duplicate = -2, 16 | rbt_status_key_not_exist = -3 17 | } rbt_status; 18 | 19 | struct rbt_tree; 20 | struct rbt_node; 21 | 22 | int rbt_node_is_valid(const struct rbt_node* node); 23 | rbt_color rbt_node_get_color(const struct rbt_node* node); 24 | struct rbt_node* rbt_node_get_left(const struct rbt_node* node); 25 | struct rbt_node* rbt_node_get_right(const struct rbt_node* node); 26 | struct rbt_node* rbt_node_get_parent(const struct rbt_node* node); 27 | const void* rbt_node_get_key(const struct rbt_node* node); 28 | 29 | typedef void* (*rbt_mem_allocate)(size_t size); 30 | typedef void (*rbt_mem_release)(void* ptr); 31 | 32 | typedef void (*rbt_node_destruct)(void*); 33 | typedef int (*rbt_node_compare)(const void*, const void*); 34 | 35 | struct rbt_tree* rbt_tree_create(rbt_mem_allocate allocator, 36 | rbt_mem_release releaser, int allow_dup, 37 | rbt_node_compare cmp, rbt_node_destruct dest); 38 | struct rbt_node* rbt_tree_get_root(struct rbt_tree* tree); 39 | rbt_status rbt_tree_insert(struct rbt_tree* tree, void* key, size_t size); 40 | struct rbt_node* rbt_tree_find(struct rbt_tree* tree, const void* key); 41 | rbt_status rbt_tree_remove_node(struct rbt_tree* tree, const void* key); 42 | rbt_status rbt_tree_destroy(struct rbt_tree* tree); 43 | int rbt_tree_is_empty(struct rbt_tree* tree); 44 | struct rbt_node* rbt_tree_minimum(struct rbt_tree* tree, struct rbt_node* x); 45 | struct rbt_node* rbt_tree_maximum(struct rbt_tree* tree, struct rbt_node* x); 46 | struct rbt_node* rbt_tree_successor(struct rbt_tree* tree, struct rbt_node* x); 47 | 48 | typedef void (*rbt_node_walk_cb)(struct rbt_node* x, void* p); 49 | void rbt_inorder_walk(struct rbt_tree* tree, rbt_node_walk_cb cb, void* p); 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | #endif /* __RB_TREE_H__ */ 56 | -------------------------------------------------------------------------------- /msvc/cstl.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cstl", "cstl.vcxproj", "{475DE074-DA8E-3E95-929A-5D73E659170A}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test-cstl", "test-cstl.vcxproj", "{2C18D160-302B-3D88-BD12-F0714E0C1263}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {475DE074-DA8E-3E95-929A-5D73E659170A} = {475DE074-DA8E-3E95-929A-5D73E659170A} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Debug|x64 = Debug|x64 15 | Release|Win32 = Release|Win32 16 | Release|x64 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {475DE074-DA8E-3E95-929A-5D73E659170A}.Debug|Win32.ActiveCfg = Debug|Win32 20 | {475DE074-DA8E-3E95-929A-5D73E659170A}.Debug|Win32.Build.0 = Debug|Win32 21 | {475DE074-DA8E-3E95-929A-5D73E659170A}.Debug|x64.ActiveCfg = Debug|x64 22 | {475DE074-DA8E-3E95-929A-5D73E659170A}.Debug|x64.Build.0 = Debug|x64 23 | {475DE074-DA8E-3E95-929A-5D73E659170A}.Release|Win32.ActiveCfg = Release|Win32 24 | {475DE074-DA8E-3E95-929A-5D73E659170A}.Release|Win32.Build.0 = Release|Win32 25 | {475DE074-DA8E-3E95-929A-5D73E659170A}.Release|x64.ActiveCfg = Release|x64 26 | {475DE074-DA8E-3E95-929A-5D73E659170A}.Release|x64.Build.0 = Release|x64 27 | {2C18D160-302B-3D88-BD12-F0714E0C1263}.Debug|Win32.ActiveCfg = Debug|Win32 28 | {2C18D160-302B-3D88-BD12-F0714E0C1263}.Debug|Win32.Build.0 = Debug|Win32 29 | {2C18D160-302B-3D88-BD12-F0714E0C1263}.Debug|x64.ActiveCfg = Debug|x64 30 | {2C18D160-302B-3D88-BD12-F0714E0C1263}.Debug|x64.Build.0 = Debug|x64 31 | {2C18D160-302B-3D88-BD12-F0714E0C1263}.Release|Win32.ActiveCfg = Release|Win32 32 | {2C18D160-302B-3D88-BD12-F0714E0C1263}.Release|Win32.Build.0 = Release|Win32 33 | {2C18D160-302B-3D88-BD12-F0714E0C1263}.Release|x64.ActiveCfg = Release|x64 34 | {2C18D160-302B-3D88-BD12-F0714E0C1263}.Release|x64.Build.0 = Release|x64 35 | EndGlobalSection 36 | GlobalSection(SolutionProperties) = preSolution 37 | HideSolutionNode = FALSE 38 | EndGlobalSection 39 | GlobalSection(ExtensibilityGlobals) = postSolution 40 | SolutionGuid = {1EE6F933-1850-3500-9B1E-4D9F18FDC00F} 41 | EndGlobalSection 42 | EndGlobal 43 | -------------------------------------------------------------------------------- /msvc/cstl.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source Files 6 | 7 | 8 | Source Files 9 | 10 | 11 | Source Files 12 | 13 | 14 | Source Files 15 | 16 | 17 | Source Files 18 | 19 | 20 | Source Files 21 | 22 | 23 | Source Files 24 | 25 | 26 | Source Files 27 | 28 | 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | 62 | 63 | {C29B761F-DB53-36CC-B42D-1B208811B37A} 64 | 65 | 66 | {B4B10EE7-BF3F-325B-8FBB-8B1F07CCB69E} 67 | 68 | 69 | -------------------------------------------------------------------------------- /inc/c_set.h: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #ifndef __C_STL_SET_H__ 26 | #define __C_STL_SET_H__ 27 | 28 | #include "c_stl_lib.h" 29 | 30 | struct cstl_set; 31 | 32 | extern struct cstl_set* cstl_set_new(cstl_compare fn_c, cstl_destroy fn_d); 33 | extern cstl_error cstl_set_insert(struct cstl_set* pSet, void* key, 34 | size_t key_size); 35 | extern int cstl_set_is_key_exists(struct cstl_set* pSet, void* key); 36 | extern cstl_error cstl_set_remove(struct cstl_set* pSet, void* key); 37 | extern const void* cstl_set_find(struct cstl_set* pSet, const void* key); 38 | extern cstl_error cstl_set_delete(struct cstl_set* pSet); 39 | 40 | extern struct cstl_iterator* cstl_set_new_iterator(struct cstl_set* pSet); 41 | extern void cstl_set_delete_iterator(struct cstl_iterator* pItr); 42 | 43 | typedef void (*fn_cstl_set_iter)(struct cstl_set* set, const void* obj, 44 | int* stop, void* p); 45 | extern void cstl_set_container_traverse(struct cstl_set* set, 46 | fn_cstl_set_iter fn, void* p); 47 | extern void cstl_set_container_add(struct cstl_set* set, void* obj); 48 | extern void cstl_set_container_remove(struct cstl_set* set, void* obj); 49 | 50 | #endif /* __C_STL_SET_H__ */ 51 | -------------------------------------------------------------------------------- /inc/c_list.h: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #ifndef __C_STL_LIST_H__ 26 | #define __C_STL_LIST_H__ 27 | 28 | struct cstl_list; 29 | 30 | extern struct cstl_list* cstl_list_new(cstl_destroy fn_d, cstl_compare fn_c); 31 | extern size_t cstl_list_count(struct cstl_list* pList); 32 | extern void cstl_list_destroy(struct cstl_list* pList); 33 | extern void cstl_list_clear(struct cstl_list* pList); 34 | extern cstl_error cstl_list_insert(struct cstl_list* pList, size_t pos, 35 | void* elem, size_t elem_size); 36 | extern cstl_error cstl_list_push_back(struct cstl_list* pList, void* elem, 37 | size_t elem_size); 38 | extern void cstl_list_remove(struct cstl_list* pList, size_t pos); 39 | extern void cstl_list_for_each(struct cstl_list* pList, 40 | void (*fn)(const void* elem, void* p), void* p); 41 | extern const void* cstl_list_find(struct cstl_list* pList, void* find_value); 42 | extern const void* cstl_list_element_at(struct cstl_list* pList, size_t pos); 43 | extern size_t cstl_list_size(struct cstl_list* pList); 44 | 45 | extern struct cstl_iterator* cstl_list_new_iterator(struct cstl_list* pSlit); 46 | extern void cstl_list_delete_iterator(struct cstl_iterator* pItr); 47 | 48 | #endif /* __C_STL_LIST_H__ */ 49 | -------------------------------------------------------------------------------- /inc/c_deque.h: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #ifndef __C_STL_DEQUE_H__ 26 | #define __C_STL_DEQUE_H__ 27 | 28 | struct cstl_deque; 29 | 30 | extern struct cstl_deque* cstl_deque_new(size_t deq_size, cstl_compare fn_c, 31 | cstl_destroy fn_d); 32 | extern size_t cstl_deque_count(struct cstl_deque* deque); 33 | extern cstl_error cstl_deque_push_back(struct cstl_deque* pDeq, void* elem, 34 | size_t elem_size); 35 | extern cstl_error cstl_deque_push_front(struct cstl_deque* pDeq, void* elem, 36 | size_t elem_size); 37 | 38 | extern const void* cstl_deque_front(struct cstl_deque* pDeq); 39 | extern const void* cstl_deque_back(struct cstl_deque* pDeq); 40 | extern cstl_error cstl_deque_pop_back(struct cstl_deque* pDeq); 41 | extern cstl_error cstl_deque_pop_front(struct cstl_deque* pDeq); 42 | extern int cstl_deque_is_empty(struct cstl_deque* pDeq); 43 | extern size_t cstl_deque_size(struct cstl_deque* pDeq); 44 | extern cstl_error cstl_deque_delete(struct cstl_deque* pDeq); 45 | extern const void* cstl_deque_element_at(struct cstl_deque* pDeq, size_t index); 46 | 47 | extern struct cstl_iterator* cstl_deque_new_iterator(struct cstl_deque* pDeq); 48 | extern void cstl_deque_delete_iterator(struct cstl_iterator* pItr); 49 | 50 | #endif /* __C_STL_DEQUE_H__ */ 51 | -------------------------------------------------------------------------------- /inc/c_errors.h: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #ifndef __C_STL_ERRORS_H__ 26 | #define __C_STL_ERRORS_H__ 27 | 28 | typedef enum { 29 | 30 | /* ------------------------------------------------------------------------*/ 31 | /* C O M M O N E R R O R C O D E */ 32 | /* ------------------------------------------------------------------------*/ 33 | CSTL_ERROR_SUCCESS = 0, 34 | CSTL_ERROR_MEMORY = -1, 35 | CSTL_RBTREE_KEY_DUPLICATE = -2, 36 | CSTL_RBTREE_KEY_NOT_FOUND = -3, 37 | 38 | CSTL_ERROR_ERROR = -10, 39 | CSTL_ELEMENT_RETURN_ERROR = -11, 40 | 41 | /* ------------------------------------------------------------------------*/ 42 | /* D Y N A M I C A R R A Y E R R O R C O D E S */ 43 | /* ------------------------------------------------------------------------*/ 44 | CSTL_ARRAY_NOT_INITIALIZED = -101, 45 | CSTL_ARRAY_INDEX_OUT_OF_BOUND = -102, 46 | CSTL_ARRAY_INSERT_FAILED = -103, 47 | 48 | CSTL_DEQUE_NOT_INITIALIZED = -201, 49 | CSTL_DEQUE_INDEX_OUT_OF_BOUND = -202, 50 | 51 | CSTL_RBTREE_NOT_INITIALIZED = -401, 52 | 53 | CSTL_SET_NOT_INITIALIZED = -501, 54 | CSTL_SET_INVALID_INPUT = -502, 55 | 56 | CSTL_MAP_NOT_INITIALIZED = -501, 57 | CSTL_MAP_INVALID_INPUT = -502, 58 | 59 | CSTL_SLIST_INSERT_FAILED = -601 60 | } cstl_error; 61 | 62 | #endif /* __C_STL_ERRORS_H__ */ 63 | -------------------------------------------------------------------------------- /inc/c_array.h: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #ifndef __C_STL_ARRAY_H__ 26 | #define __C_STL_ARRAY_H__ 27 | 28 | struct cstl_array; 29 | 30 | extern struct cstl_array* cstl_array_new(size_t init_size, cstl_compare fn_c, 31 | cstl_destroy fn_d); 32 | extern cstl_error cstl_array_push_back(struct cstl_array* pArray, void* elem, 33 | size_t elem_size); 34 | extern const void* cstl_array_element_at(struct cstl_array* pArray, 35 | size_t index); 36 | extern cstl_error cstl_array_insert_at(struct cstl_array* pArray, size_t index, 37 | void* elem, size_t elem_size); 38 | extern size_t cstl_array_size(struct cstl_array* pArray); 39 | extern size_t cstl_array_capacity(struct cstl_array* pArray); 40 | extern int cstl_array_is_empty(struct cstl_array* pArray); 41 | extern cstl_error cstl_array_reserve(struct cstl_array* pArray, size_t pos); 42 | extern const void* cstl_array_front(struct cstl_array* pArray); 43 | extern const void* cstl_array_back(struct cstl_array* pArray); 44 | extern cstl_error cstl_array_remove_from(struct cstl_array*, size_t pos); 45 | extern cstl_error cstl_array_delete(struct cstl_array* pArray); 46 | 47 | extern struct cstl_iterator* cstl_array_new_iterator(struct cstl_array* pArray); 48 | extern void cstl_array_delete_iterator(struct cstl_iterator* pItr); 49 | 50 | extern void cstl_array_quick_sort(struct cstl_array* pArray); 51 | 52 | #endif /* __C_STL_ARRAY_H__ */ 53 | -------------------------------------------------------------------------------- /inc/c_map.h: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #ifndef __C_STL_MAP_H__ 26 | #define __C_STL_MAP_H__ 27 | 28 | struct cstl_map; 29 | 30 | extern struct cstl_map* cstl_map_new(cstl_compare fn_c_k, cstl_destroy fn_k_d, 31 | cstl_destroy fn_v_d); 32 | extern cstl_error cstl_map_insert(struct cstl_map* pMap, const void* key, 33 | size_t key_size, const void* value, 34 | size_t value_size); 35 | extern int cstl_map_is_key_exists(struct cstl_map* pMap, const void* key); 36 | extern cstl_error cstl_map_replace(struct cstl_map* pMap, const void* key, 37 | const void* value, size_t value_size); 38 | extern cstl_error cstl_map_remove(struct cstl_map* pMap, const void* key); 39 | extern const void* cstl_map_find(struct cstl_map* pMap, const void* key); 40 | extern cstl_error cstl_map_delete(struct cstl_map* pMap); 41 | 42 | extern struct cstl_iterator* cstl_map_new_iterator(struct cstl_map* pMap); 43 | extern void cstl_map_delete_iterator(struct cstl_iterator* pItr); 44 | 45 | typedef void (*map_iter_callback)(struct cstl_map* map, const void* key, 46 | const void* value, int* stop, void* p); 47 | extern void cstl_map_traverse(struct cstl_map* map, map_iter_callback cb, 48 | void* p); 49 | 50 | typedef void (*fn_map_walker)(const void* key, const void* value, int* stop, 51 | void* p); 52 | void cstl_map_const_traverse(struct cstl_map* map, fn_map_walker fn, void* p); 53 | 54 | #endif /* __C_STL_MAP_H__ */ 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | .idea/ 4 | cmake-build-* 5 | Makefile 6 | test_cstl 7 | tstclib 8 | CMakeCache.txt 9 | CMakeFiles/ 10 | cmake_install.cmake 11 | *.cbp 12 | 13 | .vscode/ 14 | 15 | ################# 16 | ## Eclipse 17 | ################# 18 | 19 | *.pydevproject 20 | .project 21 | .metadata 22 | bin/ 23 | tmp/ 24 | *.tmp 25 | *.bak 26 | *.swp 27 | *~.nib 28 | local.properties 29 | .classpath 30 | .settings/ 31 | .loadpath 32 | 33 | # External tool builders 34 | .externalToolBuilders/ 35 | 36 | # Locally stored "Eclipse launch configurations" 37 | *.launch 38 | 39 | # CDT-specific 40 | .cproject 41 | 42 | # PDT-specific 43 | .buildpath 44 | 45 | 46 | ################# 47 | ## Visual Studio 48 | ################# 49 | 50 | .vscode/ 51 | .vs/ 52 | 53 | ## Ignore Visual Studio temporary files, build results, and 54 | ## files generated by popular Visual Studio add-ons. 55 | 56 | # User-specific files 57 | *.suo 58 | *.user 59 | *.sln.docstates 60 | 61 | # Build results 62 | [Dd]ebug/ 63 | [Rr]elease/ 64 | *_i.c 65 | *_p.c 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.pch 70 | *.pdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.vspscc 80 | .builds 81 | *.dotCover 82 | 83 | UpgradeLog.htm 84 | *.VC.opendb 85 | win/clib_Debug/ 86 | win/tclib_Debug/ 87 | 88 | 89 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 90 | #packages/ 91 | 92 | # Visual C++ cache files 93 | ipch/ 94 | *.aps 95 | *.ncb 96 | *.opensdf 97 | *.sdf 98 | 99 | # Visual Studio profiler 100 | *.psess 101 | *.vsp 102 | 103 | # ReSharper is a .NET coding add-in 104 | _ReSharper* 105 | 106 | # Installshield output folder 107 | [Ee]xpress 108 | 109 | # DocProject is a documentation generator add-in 110 | DocProject/buildhelp/ 111 | DocProject/Help/*.HxT 112 | DocProject/Help/*.HxC 113 | DocProject/Help/*.hhc 114 | DocProject/Help/*.hhk 115 | DocProject/Help/*.hhp 116 | DocProject/Help/Html2 117 | DocProject/Help/html 118 | 119 | # Click-Once directory 120 | publish 121 | 122 | # Others 123 | [Bb]in 124 | [Oo]bj 125 | sql 126 | TestResults 127 | *.Cache 128 | ClientBin 129 | stylecop.* 130 | ~$* 131 | *.dbmdl 132 | Generated_Code #added for RIA/Silverlight projects 133 | 134 | # Backup & report files from converting an old project file to a newer 135 | # Visual Studio version. Backup files are not needed, because we have git ;-) 136 | _UpgradeReport_Files/ 137 | Backup*/ 138 | UpgradeLog*.XML 139 | 140 | 141 | 142 | ############ 143 | ## Windows 144 | ############ 145 | 146 | # Windows image file caches 147 | Thumbs.db 148 | 149 | # Folder config file 150 | Desktop.ini 151 | 152 | 153 | ############# 154 | ## Python 155 | ############# 156 | 157 | *.py[co] 158 | 159 | # Packages 160 | *.egg 161 | *.egg-info 162 | dist 163 | build 164 | eggs 165 | parts 166 | bin 167 | var 168 | sdist 169 | develop-eggs 170 | .installed.cfg 171 | 172 | # Installer logs 173 | pip-log.txt 174 | 175 | # Unit test / coverage reports 176 | .coverage 177 | .tox 178 | 179 | #Translations 180 | *.mo 181 | 182 | #Mr Developer 183 | .mr.developer.cfg 184 | 185 | # Mac crap 186 | .DS_Store 187 | -------------------------------------------------------------------------------- /src/c_util.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include 26 | #include 27 | #include 28 | #include "c_stl_lib.h" 29 | 30 | void cstl_copy(void* destination, void* source, size_t size) 31 | { 32 | memcpy((char*)destination, source, size); 33 | } 34 | 35 | void cstl_get(void* destination, void* source, size_t size) 36 | { 37 | memcpy(destination, (char*)source, size); 38 | } 39 | 40 | struct cstl_object { 41 | void* raw_data; 42 | size_t size; 43 | }; 44 | 45 | struct cstl_object* cstl_object_new(const void* inObject, size_t obj_size) 46 | { 47 | struct cstl_object* tmp = 48 | (struct cstl_object*)calloc(1, sizeof(struct cstl_object)); 49 | void* raw_data = (void*)0; 50 | if (!tmp) { 51 | return (struct cstl_object*)0; 52 | } 53 | tmp->size = obj_size; 54 | raw_data = (void*)calloc(obj_size, sizeof(char)); 55 | if (!raw_data) { 56 | free(tmp); 57 | return (struct cstl_object*)0; 58 | } 59 | memcpy(raw_data, inObject, obj_size); 60 | tmp->raw_data = raw_data; 61 | return tmp; 62 | } 63 | 64 | const void* cstl_object_get_data(struct cstl_object* inObject) 65 | { 66 | return inObject->raw_data; 67 | } 68 | 69 | void cstl_object_replace_raw(struct cstl_object* current_object, 70 | const void* elem, size_t elem_size) 71 | { 72 | assert(current_object); 73 | free(current_object->raw_data); 74 | current_object->raw_data = (void*)calloc(elem_size, sizeof(char)); 75 | if (current_object->raw_data) { 76 | memcpy(current_object->raw_data, elem, elem_size); 77 | } 78 | } 79 | 80 | void cstl_object_delete(struct cstl_object* inObject) 81 | { 82 | if (inObject) { 83 | free(inObject->raw_data); 84 | free(inObject); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /inc/c_stl_lib.h: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #ifndef __C_STL_LIB_H__ 26 | #define __C_STL_LIB_H__ 27 | 28 | #include 29 | 30 | #include "c_errors.h" 31 | 32 | /* ------------------------------------------------------------------------*/ 33 | /* C O M M O N D E F I N I T O N S */ 34 | /* ------------------------------------------------------------------------*/ 35 | 36 | typedef void (*cstl_destroy)(void*); 37 | typedef int (*cstl_compare)(const void*, const void*); 38 | typedef void (*cstl_traversal)(void*); 39 | 40 | /* ------------------------------------------------------------------------*/ 41 | /* P A I R */ 42 | /* ------------------------------------------------------------------------*/ 43 | 44 | struct cstl_iterator { 45 | const void* (*next)(struct cstl_iterator* pIterator); 46 | void (*replace_current_value)(struct cstl_iterator* pIterator, 47 | void* new_value, size_t size); 48 | const void* (*current_key)(struct cstl_iterator* pIterator); 49 | const void* (*current_value)(struct cstl_iterator* pIterator); 50 | void* pContainer; 51 | size_t current_index; 52 | void* current_element; 53 | }; 54 | 55 | #include "c_algorithms.h" 56 | #include "c_array.h" 57 | #include "c_deque.h" 58 | #include "c_list.h" 59 | #include "c_map.h" 60 | #include "c_set.h" 61 | 62 | /* ------------------------------------------------------------------------*/ 63 | /* H E L P E R F U N C T I O N S */ 64 | /* ------------------------------------------------------------------------*/ 65 | 66 | extern void cstl_copy(void* destination, void* source, size_t size); 67 | extern void cstl_get(void* destination, void* source, size_t size); 68 | 69 | struct cstl_object; 70 | 71 | extern struct cstl_object* cstl_object_new(const void* inObject, 72 | size_t obj_size); 73 | extern const void* cstl_object_get_data(struct cstl_object* inObject); 74 | extern void cstl_object_delete(struct cstl_object* inObject); 75 | extern void cstl_object_replace_raw(struct cstl_object* current_object, 76 | const void* elem, size_t elem_size); 77 | 78 | #endif /* __C_STL_LIB_H__ */ 79 | -------------------------------------------------------------------------------- /test/t_clib.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | extern void test_c_array(); 30 | extern void test_c_deque(); 31 | extern void test_c_rb(); 32 | extern void test_c_rb2(void); 33 | void test_c_rb2_alloc(void); 34 | void test_rbt_string(void); 35 | void test_rbt_string2(void); 36 | 37 | extern void test_c_set(); 38 | extern void test_c_map(); 39 | extern void test_c_slist(); 40 | extern void test_c_map(); 41 | extern void test_c_algorithms(); 42 | 43 | #if defined(_MSC_VER) 44 | #if !defined(_CRTDBG_MAP_ALLOC) 45 | #define _CRTDBG_MAP_ALLOC 46 | #endif 47 | #include 48 | #include 49 | 50 | #define MEM_CHECK_BEGIN() \ 51 | do { \ 52 | _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); \ 53 | } while (0) 54 | #define MEM_CHECK_BREAK_ALLOC(x) \ 55 | do { \ 56 | _CrtSetBreakAlloc(x); \ 57 | } while (0) 58 | #define MEM_CHECK_DUMP_LEAKS() \ 59 | do { \ 60 | _CrtDumpMemoryLeaks(); \ 61 | } while (0) 62 | #else 63 | #define MEM_CHECK_BEGIN() \ 64 | do { \ 65 | } while (0) 66 | #define MEM_CHECK_BREAK_ALLOC(x) \ 67 | do { \ 68 | (void)x; \ 69 | } while (0) 70 | #define MEM_CHECK_DUMP_LEAKS() \ 71 | do { \ 72 | } while (0) 73 | #endif 74 | 75 | void on_atexit(void) 76 | { 77 | MEM_CHECK_DUMP_LEAKS(); 78 | } 79 | 80 | int main(int argc, char** argv) 81 | { 82 | clock_t t = clock(); 83 | (void)argc; 84 | (void)argv; 85 | MEM_CHECK_BEGIN(); 86 | atexit(on_atexit); 87 | { 88 | printf("Performing test for red-black tree\n"); 89 | test_c_rb(); 90 | test_c_rb2(); 91 | test_c_rb2_alloc(); 92 | test_rbt_string(); 93 | test_rbt_string2(); 94 | 95 | printf("Performing test for dynamic array\n"); 96 | test_c_array(); 97 | printf("Performing test for deque\n"); 98 | test_c_deque(); 99 | printf("Performing test for sets\n"); 100 | test_c_set(); 101 | printf("Performing test for map\n"); 102 | test_c_map(); 103 | printf("Performing test for slist\n"); 104 | test_c_slist(); 105 | printf("Performing algorithms tests\n"); 106 | test_c_algorithms(); 107 | } 108 | { 109 | /* in seconds */ 110 | double time_taken = (((double)clock() - (double)t)) / CLOCKS_PER_SEC; 111 | printf("tests took %f seconds to execute \n", time_taken); 112 | } 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # 4 | # usage: find . -regex '.*\.\(c\|h\|cpp\|hpp\|cc\|cxx\)' -exec clang-format -style=file -i {} \; 5 | # ref link: https://freebug.top/blog/2021/08/23/%E5%A4%9A%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83%E4%B8%8B%E7%9A%84clang-format%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/ 6 | # 7 | 8 | AccessModifierOffset: -4 9 | AlignAfterOpenBracket: Align 10 | AlignConsecutiveAssignments: false 11 | AlignConsecutiveDeclarations: false 12 | AlignConsecutiveMacros: true 13 | AlignEscapedNewlines: true 14 | AlignOperands: true 15 | AlignTrailingComments: true 16 | AllowAllArgumentsOnNextLine: true 17 | AllowAllConstructorInitializersOnNextLine: true 18 | AllowAllParametersOfDeclarationOnNextLine: true 19 | AllowShortCaseLabelsOnASingleLine: false 20 | AllowShortFunctionsOnASingleLine: false 21 | AllowShortBlocksOnASingleLine: true 22 | AllowShortIfStatementsOnASingleLine: false 23 | AllowShortLambdasOnASingleLine: true 24 | AllowShortLoopsOnASingleLine: false 25 | AllowShortFunctionsOnASingleLine: None 26 | AllowShortIfStatementsOnASingleLine: false 27 | AlwaysBreakAfterDefinitionReturnType: None 28 | AlwaysBreakAfterReturnType: None 29 | AlwaysBreakBeforeMultilineStrings: false 30 | AlwaysBreakTemplateDeclarations: false 31 | BinPackArguments: true 32 | BinPackParameters: true 33 | 34 | BreakBeforeBraces: Stroustrup 35 | BraceWrapping: 36 | AfterCaseLabel: false 37 | AfterClass: true 38 | AfterControlStatement: false 39 | AfterEnum: false 40 | AfterFunction: true 41 | AfterNamespace: true 42 | AfterObjCDeclaration: false 43 | AfterStruct: false 44 | AfterUnion: false 45 | AfterExternBlock: false 46 | BeforeCatch: false 47 | BeforeElse: false 48 | IndentBraces: false 49 | SplitEmptyFunction: true 50 | SplitEmptyRecord: true 51 | SplitEmptyNamespace: true 52 | 53 | BreakBeforeBinaryOperators: None 54 | BreakBeforeInheritanceComma: false 55 | BreakBeforeTernaryOperators: false 56 | BreakConstructorInitializersBeforeComma: false 57 | BreakConstructorInitializers: BeforeColon 58 | BreakAfterJavaFieldAnnotations: false 59 | BreakStringLiterals: false 60 | ColumnLimit: 80 61 | CommentPragmas: '^ IWYU pragma:' 62 | CompactNamespaces: false 63 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 64 | ConstructorInitializerIndentWidth: 4 65 | ContinuationIndentWidth: 4 66 | Cpp11BracedListStyle: false 67 | DerivePointerAlignment: false 68 | DisableFormat: false 69 | ExperimentalAutoDetectBinPacking: false 70 | FixNamespaceComments: false 71 | 72 | IncludeBlocks: Preserve 73 | IncludeCategories: 74 | - Regex: '"config\.h"' 75 | Priority: 1 76 | SortPriority: 1 77 | - Regex: '<^(glib).*>' 78 | Priority: 2 79 | SortPriority: 2 80 | - Regex: '' 81 | Priority: 3 82 | SortPriority: 3 83 | - Regex: '' 84 | Priority: 4 85 | SortPriority: 4 86 | - Regex: '[\<\"]zbar\.h[\>\"]' 87 | Priority: 5 88 | SortPriority: 6 89 | - Regex: '[\<\"]zbar.*' 90 | Priority: 6 91 | SortPriority: 7 92 | - Regex: '<.*>' 93 | Priority: 7 94 | SortPriority: 5 95 | - Regex: '.*' 96 | Priority: 8 97 | SortPriority: 8 98 | SortIncludes: true 99 | 100 | IndentCaseLabels: false 101 | IndentPPDirectives: None 102 | IndentWidth: 4 103 | IndentWrappedFunctionNames: false 104 | JavaScriptQuotes: Leave 105 | JavaScriptWrapImports: true 106 | KeepEmptyLinesAtTheStartOfBlocks: false 107 | MacroBlockBegin: '' 108 | MacroBlockEnd: '' 109 | MaxEmptyLinesToKeep: 1 110 | NamespaceIndentation: None 111 | ObjCBinPackProtocolList: Auto 112 | ObjCBlockIndentWidth: 4 113 | ObjCSpaceAfterProperty: true 114 | ObjCSpaceBeforeProtocolList: true 115 | 116 | PenaltyBreakAssignment: 10 117 | PenaltyBreakBeforeFirstCallParameter: 50 118 | PenaltyBreakComment: 10 119 | PenaltyBreakFirstLessLess: 0 120 | PenaltyBreakString: 10 121 | PenaltyExcessCharacter: 100 122 | PenaltyReturnTypeOnItsOwnLine: 60 123 | 124 | PointerAlignment: Left 125 | ReflowComments: false 126 | SortUsingDeclarations: true 127 | SpaceAfterCStyleCast: false 128 | SpaceAfterTemplateKeyword: true 129 | SpaceBeforeAssignmentOperators: true 130 | SpaceBeforeCtorInitializerColon: true 131 | SpaceBeforeInheritanceColon: true 132 | SpaceBeforeParens: ControlStatements 133 | SpaceBeforeRangeBasedForLoopColon: true 134 | SpaceInEmptyParentheses: false 135 | SpacesBeforeTrailingComments: 1 136 | SpacesInAngles: false 137 | SpacesInContainerLiterals: false 138 | SpacesInCStyleCastParentheses: false 139 | SpacesInParentheses: false 140 | SpacesInSquareBrackets: false 141 | Standard: Cpp03 142 | TabWidth: 4 143 | UseTab: Never 144 | ... 145 | 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSTL - STL like container support in C language 2 | 3 | ## Dynamic Array 4 | ```cpp 5 | struct cstl_array { 6 | size_t capacity; /* Number of maximum elements array can hold without reallocation */ 7 | size_t count; /* Number of current elements in the array */ 8 | struct cstl_object** pElements; /* actual storage area */ 9 | cstl_compare compare_fn; /* Compare function pointer*/ 10 | cstl_destroy destruct_fn; /* Destructor function pointer*/ 11 | }; 12 | 13 | struct cstl_array* cstl_array_new ( size_t init_size, cstl_compare fn_c, cstl_destroy fn_d); 14 | cstl_error cstl_array_push_back ( struct cstl_array* pArray, void* elem, size_t elem_size); 15 | const void * cstl_array_element_at(struct cstl_array* pArray, size_t index); 16 | cstl_error cstl_array_insert_at ( struct cstl_array* pArray, size_t index, void* elem, size_t elem_size); 17 | size_t cstl_array_size( struct cstl_array* pArray); 18 | size_t cstl_array_capacity( struct cstl_array* pArray ); 19 | cstl_bool cstl_array_empty( struct cstl_array* pArray); 20 | cstl_error cstl_array_reserve( struct cstl_array* pArray, size_t pos); 21 | const void * cstl_array_front(struct cstl_array* pArray); 22 | const void * cstl_array_back(struct cstl_array* pArray); 23 | cstl_error cstl_array_remove_from ( struct cstl_array*, size_t pos); 24 | cstl_error cstl_array_delete( struct cstl_array* pArray); 25 | 26 | struct cstl_iterator* cstl_array_new_iterator(struct cstl_array* pArray); 27 | void cstl_array_delete_iterator ( struct cstl_iterator* pItr); 28 | ``` 29 | 30 | ## deque 31 | ```cpp 32 | struct cstl_deque { 33 | struct cstl_object**pElements; 34 | size_t capacity; 35 | size_t head; 36 | size_t tail; 37 | size_t count; 38 | cstl_compare compare_fn; 39 | cstl_destroy destruct_fn; 40 | }; 41 | 42 | struct cstl_deque* cstl_deque_new( size_t deq_size , cstl_compare fn_c, cstl_destroy fn_d); 43 | cstl_error cstl_deque_push_back (struct cstl_deque* pDeq, void* elem, size_t elem_size); 44 | cstl_error cstl_deque_push_front(struct cstl_deque* pDeq, void* elem,size_t elem_size); 45 | 46 | const void * cstl_deque_front(struct cstl_deque* pDeq); 47 | const void * cstl_deque_back(struct cstl_deque* pDeq); 48 | cstl_error cstl_deque_pop_back (struct cstl_deque* pDeq); 49 | cstl_error cstl_deque_pop_front (struct cstl_deque* pDeq); 50 | cstl_bool cstl_deque_empty (struct cstl_deque* pDeq); 51 | size_t cstl_deque_size ( struct cstl_deque* pDeq); 52 | cstl_error cstl_deque_delete ( struct cstl_deque* pDeq); 53 | const void * cstl_deque_element_at(struct cstl_deque* pDeq, size_t index); 54 | 55 | struct cstl_iterator* cstl_deque_new_iterator(struct cstl_deque* pDeq); 56 | void cstl_deque_delete_iterator ( struct cstl_iterator* pItr); 57 | ``` 58 | 59 | ## list 60 | ```cpp 61 | struct cstl_list_node { 62 | struct cstl_object* elem; 63 | struct cstl_list_node *next; 64 | }; 65 | struct cstl_list { 66 | struct cstl_list_node* head; 67 | cstl_destroy destruct_fn; 68 | cstl_compare compare_key_fn; 69 | size_t size; 70 | }; 71 | struct cstl_list* cstl_list_new(cstl_destroy fn_d, cstl_compare fn_c); 72 | void cstl_list_destroy(struct cstl_list* pList); 73 | void cstl_list_clear(struct cstl_list* pList); 74 | cstl_error cstl_list_insert (struct cstl_list* pList, size_t pos, void* elem, size_t elem_size); 75 | cstl_error cstl_list_push_back(struct cstl_list* pList, void* elem, size_t elem_size); 76 | void cstl_list_remove (struct cstl_list* pList, size_t pos); 77 | void cstl_list_for_each(struct cstl_list* pList, void(*fn)(const void *elem, void *p), void *p); 78 | const void * cstl_list_find(struct cstl_list* pList, void* find_value); 79 | 80 | 81 | struct cstl_iterator* cstl_list_new_iterator(struct cstl_list* pSlit); 82 | void cstl_list_delete_iterator ( struct cstl_iterator* pItr); 83 | ``` 84 | ## set 85 | ```cpp 86 | struct cstl_set { 87 | struct cstl_rb* root; 88 | }; 89 | struct cstl_set* cstl_set_new( cstl_compare fn_c, cstl_destroy fn_d); 90 | cstl_error cstl_set_insert ( struct cstl_set* pSet, void* key, size_t key_size); 91 | cstl_bool cstl_set_exists ( struct cstl_set* pSet, void* key); 92 | cstl_error cstl_set_remove ( struct cstl_set* pSet, void* key); 93 | const void * cstl_set_find(struct cstl_set* pSet, const void* key); 94 | cstl_error cstl_set_delete ( struct cstl_set* pSet); 95 | 96 | struct cstl_iterator* cstl_set_new_iterator(struct cstl_set* pSet); 97 | void cstl_set_delete_iterator ( struct cstl_iterator* pItr); 98 | ``` 99 | 100 | ## map 101 | ```cpp 102 | struct cstl_map { 103 | struct cstl_rb* root; 104 | }; 105 | 106 | struct cstl_map* cstl_map_new ( cstl_compare fn_c_k, cstl_destroy fn_k_d, cstl_destroy fn_v_d); 107 | cstl_error cstl_map_insert ( struct cstl_map* pMap, const void* key, size_t key_size, const void* value, size_t value_size); 108 | cstl_bool cstl_map_exists ( struct cstl_map* pMap, const void* key); 109 | cstl_error cstl_map_remove ( struct cstl_map* pMap, const void* key); 110 | const void * cstl_map_find(struct cstl_map* pMap, const void* key); 111 | cstl_error cstl_map_delete ( struct cstl_map* pMap); 112 | 113 | struct cstl_iterator* cstl_map_new_iterator(struct cstl_map* pMap); 114 | void cstl_map_delete_iterator ( struct cstl_iterator* pItr); 115 | ``` 116 | 117 | ## clang-format 118 | ``` 119 | find . -regex '.*\.\(c\|h\|cpp\|hpp\|cc\|cxx\)' -exec clang-format -style=file -i {} \; 120 | ``` -------------------------------------------------------------------------------- /test/t_c_deque.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include "c_stl_lib.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | static int compare_e(const void* left, const void* right) 33 | { 34 | int* l = (int*)left; 35 | int* r = (int*)right; 36 | return (*l - *r); 37 | } 38 | 39 | static int compare_e_ptr(const void* left, const void* right) 40 | { 41 | int* l = *((int**)left); 42 | int* r = *((int**)right); 43 | return (*l - *r); 44 | } 45 | 46 | static void free_e(void* ptr) 47 | { 48 | if (ptr) { 49 | void* p = *((void**)ptr); 50 | if (p) { 51 | free(p); 52 | } 53 | } 54 | } 55 | 56 | static void replace_values_using_iterators(struct cstl_deque* myDeq) 57 | { 58 | struct cstl_iterator* myItr; 59 | const void* pElement; 60 | 61 | myItr = cstl_deque_new_iterator(myDeq); 62 | while ((pElement = myItr->next(myItr)) != NULL) { 63 | const void* old_value = myItr->current_value(myItr); 64 | int new_value = *(int*)old_value; 65 | new_value = new_value * 2; 66 | myItr->replace_current_value(myItr, &new_value, sizeof(new_value)); 67 | } 68 | cstl_deque_delete_iterator(myItr); 69 | } 70 | static struct cstl_deque* create_deque() 71 | { 72 | int flip = 1; 73 | int i = 0; 74 | int limit = 20; 75 | struct cstl_deque* myDeq = cstl_deque_new(10, compare_e, NULL); 76 | assert((struct cstl_deque*)0 != myDeq); 77 | 78 | for (i = 0; i <= limit; i++) { 79 | if (flip) { 80 | cstl_deque_push_back(myDeq, &i, sizeof(int)); 81 | flip = 0; 82 | } 83 | else { 84 | cstl_deque_push_front(myDeq, &i, sizeof(int)); 85 | flip = 1; 86 | } 87 | } 88 | return myDeq; 89 | } 90 | static void print_using_iterator(struct cstl_deque* myDeq) 91 | { 92 | struct cstl_iterator* myItr; 93 | const void* pElement; 94 | 95 | printf("------------------------------------------------\n"); 96 | myItr = cstl_deque_new_iterator(myDeq); 97 | while ((pElement = myItr->next(myItr)) != NULL) { 98 | const void* value = myItr->current_value(myItr); 99 | printf("%d\n", *(int*)value); 100 | } 101 | cstl_deque_delete_iterator(myItr); 102 | } 103 | 104 | static void test_with_deque_iterator() 105 | { 106 | struct cstl_deque* myDeq = create_deque(); 107 | print_using_iterator(myDeq); 108 | replace_values_using_iterators(myDeq); 109 | print_using_iterator(myDeq); 110 | cstl_deque_delete(myDeq); 111 | } 112 | 113 | void test_c_deque() 114 | { 115 | int flip = 1; 116 | size_t i = 0; 117 | size_t limit = 20; 118 | const void* element = NULL; 119 | int j = 0; 120 | 121 | struct cstl_deque* myDeq = cstl_deque_new(10, compare_e, NULL); 122 | assert((struct cstl_deque*)0 != myDeq); 123 | 124 | for (i = 0; i <= limit; i++) { 125 | if (flip) { 126 | cstl_deque_push_back(myDeq, &i, sizeof(int)); 127 | flip = 0; 128 | } 129 | else { 130 | cstl_deque_push_front(myDeq, &i, sizeof(int)); 131 | flip = 1; 132 | } 133 | } 134 | element = cstl_deque_front(myDeq); 135 | assert(*(int*)element == (int)limit - 1); 136 | 137 | element = cstl_deque_back(myDeq); 138 | assert(*(int*)element == (int)limit); 139 | 140 | while (cstl_deque_is_empty(myDeq) == 0) { 141 | cstl_deque_pop_front(myDeq); 142 | } 143 | cstl_deque_delete(myDeq); 144 | 145 | myDeq = cstl_deque_new(10, compare_e_ptr, free_e); 146 | for (i = 0; i <= limit; i++) { 147 | int* v = (int*)calloc(1, sizeof(int)); 148 | *v = (int)i; 149 | cstl_deque_push_back(myDeq, &v, sizeof(int*)); 150 | } 151 | for (i = 0; i < cstl_deque_count(myDeq); i++) { 152 | int* elem = *(int**)cstl_deque_element_at(myDeq, i); 153 | if (elem) { 154 | assert(*elem == j++); 155 | } 156 | } 157 | cstl_deque_delete(myDeq); 158 | test_with_deque_iterator(); 159 | (void)element; 160 | (void)j; 161 | } 162 | -------------------------------------------------------------------------------- /test/t_c_set.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include "c_stl_lib.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | static void delete_e(void* ptr) 33 | { 34 | if (ptr) { 35 | char* str = *((char**)ptr); 36 | if (str) { 37 | free(str); 38 | } 39 | } 40 | } 41 | static int compare_e(const void* left, const void* right) 42 | { 43 | char* l = *((char**)left); 44 | char* r = *((char**)right); 45 | return strcmp((const char*)l, (const char*)r); 46 | } 47 | static int compare_int(const void* left, const void* right) 48 | { 49 | int* l = (int*)left; 50 | int* r = (int*)right; 51 | 52 | return (*l - *r); 53 | } 54 | 55 | static void test_with_iterators() 56 | { 57 | int test[] = { 13, 8, 17, 1, 11, 15, 25, 6, 22, 27 }; 58 | int index = 0; 59 | int size = sizeof(test) / sizeof(test[0]); 60 | struct cstl_iterator* myItr; 61 | const void* pElement; 62 | 63 | struct cstl_set* pSet = cstl_set_new(compare_int, NULL); 64 | 65 | for (index = 0; index < size; index++) { 66 | int v = test[index]; 67 | cstl_set_insert(pSet, &v, sizeof(int)); 68 | } 69 | for (index = 0; index < size; index++) { 70 | int v = test[index]; 71 | assert(0 != cstl_set_is_key_exists(pSet, &v)); 72 | (void)v; 73 | } 74 | printf("------------------------------------------------\n"); 75 | myItr = cstl_set_new_iterator(pSet); 76 | while ((pElement = myItr->next(myItr)) != NULL) { 77 | const void* value = myItr->current_value(myItr); 78 | printf("%d\n", *(int*)value); 79 | } 80 | cstl_set_delete_iterator(myItr); 81 | cstl_set_delete(pSet); 82 | } 83 | 84 | void test_c_set() 85 | { 86 | { 87 | int test[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 88 | int index = 0; 89 | int size = sizeof(test) / sizeof(test[0]); 90 | const void* outKey = NULL; 91 | 92 | struct cstl_set* pSet = cstl_set_new(compare_int, NULL); 93 | 94 | for (index = 0; index < size; index++) { 95 | int v = test[index]; 96 | cstl_set_insert(pSet, &v, sizeof(int)); 97 | } 98 | for (index = 0; index < size; index++) { 99 | int v = test[index]; 100 | assert(0 != cstl_set_is_key_exists(pSet, &v)); 101 | (void)v; 102 | } 103 | 104 | index = 9; 105 | outKey = cstl_set_find(pSet, &index); 106 | assert(9 == *(int*)outKey); 107 | cstl_set_delete(pSet); 108 | (void)outKey; 109 | } 110 | { 111 | typedef struct test { 112 | char* string; 113 | } TEST_INPUT; 114 | 115 | int index = 0; 116 | int size = 0; 117 | char* v; 118 | 119 | TEST_INPUT ti[] = { 120 | { "A for APPLE" }, { "B for BALL" }, { "C for CAT" }, 121 | { "D for DOG" }, { "E for ELEPHANT" }, { "F for FISH" }, 122 | { "G for GOAT" }, { "H for HORSE" }, { "I for ICECREAM" }, 123 | { "J for JOKER" }, { "K for KITE" }, { "L for LAMB" }, 124 | { "M for MONKEY" }, { "N for NEST" }, { "O for ORANGE" }, 125 | { "P for POT" }, { "Q for QUEEN" }, { "R for RAT" }, 126 | { "S for SHEEP" }, { "T for TABLE" }, { "U for UMBRELLA" }, 127 | { "V for VIOLIN" }, { "W for WAX" }, { "X for XEROX" }, 128 | { "Y for YUMMY" }, { "Z for ZEBRA" }, 129 | }; 130 | struct cstl_set* pSet = cstl_set_new(compare_e, delete_e); 131 | size = sizeof(ti) / sizeof(ti[0]); 132 | 133 | for (index = 0; index < size; index++) { 134 | char* temp = strdup(ti[index].string); 135 | cstl_set_insert(pSet, &temp, sizeof(char*)); 136 | } 137 | for (index = 0; index < size; index++) { 138 | v = ti[index].string; 139 | assert(0 != cstl_set_is_key_exists(pSet, &v)); 140 | /* cstl_set_remove(pSet, &v); */ 141 | } 142 | { 143 | const void* pElement; 144 | struct cstl_iterator* myItr = cstl_set_new_iterator(pSet); 145 | while ((pElement = myItr->next(myItr))) { 146 | const void* value = myItr->current_value(myItr); 147 | printf("%s\n", *((char**)value)); 148 | } 149 | cstl_set_delete_iterator(myItr); 150 | } 151 | cstl_set_delete(pSet); 152 | (void)v; 153 | } 154 | test_with_iterators(); 155 | } 156 | -------------------------------------------------------------------------------- /test/t_c_slist.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include "c_stl_lib.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | static void free_element(void* ptr) 33 | { 34 | if (ptr) { 35 | void* p = *((void**)ptr); 36 | if (p) { 37 | free(p); 38 | } 39 | } 40 | } 41 | 42 | void add_elements_to_list(struct cstl_list* ll, int x, int y) 43 | { 44 | int i = 0; 45 | for (i = x; i <= y; i++) { 46 | int* v = (int*)calloc(1, sizeof(int)); 47 | memcpy(v, &i, sizeof(int)); 48 | cstl_list_push_back(ll, &v, sizeof(int*)); 49 | } 50 | } 51 | void print_e(const void* ptr, void* p) 52 | { 53 | (void)p; 54 | if (ptr) { 55 | printf("%d\n", **((int**)ptr)); 56 | } 57 | } 58 | 59 | static int compare_element(const void* left, const void* right) 60 | { 61 | int* l = *((int**)left); 62 | int* r = *((int**)right); 63 | return (*l - *r); 64 | } 65 | static void print_using_iterators(struct cstl_list* pList) 66 | { 67 | struct cstl_iterator* myItr; 68 | const void* pElement; 69 | printf("------------------------------------------------\n"); 70 | myItr = cstl_list_new_iterator(pList); 71 | while ((pElement = myItr->next(myItr)) != NULL) { 72 | const void* value = myItr->current_value(myItr); 73 | printf("%d\n", **((int**)value)); 74 | } 75 | cstl_list_delete_iterator(myItr); 76 | } 77 | 78 | static void replace_values_using_iterators(struct cstl_list* pList) 79 | { 80 | struct cstl_iterator* myItr; 81 | const void* pElement; 82 | printf("------------------------------------------------\n"); 83 | myItr = cstl_list_new_iterator(pList); 84 | while ((pElement = myItr->next(myItr)) != NULL) { 85 | int* v; 86 | const void* old_value = myItr->current_value(myItr); 87 | int new_value = **((int**)old_value); 88 | new_value = new_value * 2; 89 | 90 | v = (int*)calloc(1, sizeof(int)); 91 | *v = new_value; 92 | myItr->replace_current_value(myItr, &v, sizeof(int*)); 93 | } 94 | cstl_list_delete_iterator(myItr); 95 | } 96 | 97 | static void test_with_iterators() 98 | { 99 | struct cstl_list* pList = cstl_list_new(free_element, compare_element); 100 | add_elements_to_list(pList, 1, 10); 101 | print_using_iterators(pList); 102 | replace_values_using_iterators(pList); 103 | print_using_iterators(pList); 104 | cstl_list_destroy(pList); 105 | } 106 | 107 | void test_c_slist() 108 | { 109 | int* tmp; 110 | int i = 0; 111 | int* v; 112 | const void* outValue; 113 | struct cstl_list* list = cstl_list_new(free_element, compare_element); 114 | 115 | add_elements_to_list(list, 1, 10); 116 | cstl_list_for_each(list, print_e, NULL); 117 | 118 | i = 55; 119 | v = (int*)calloc(1, sizeof(int)); 120 | *v = i; 121 | cstl_list_insert(list, 4, &v, sizeof(int*)); 122 | cstl_list_for_each(list, print_e, NULL); 123 | 124 | cstl_list_remove(list, 4); 125 | cstl_list_for_each(list, print_e, NULL); 126 | 127 | cstl_list_remove(list, 0); 128 | cstl_list_for_each(list, print_e, NULL); 129 | 130 | cstl_list_remove(list, 100); 131 | cstl_list_for_each(list, print_e, NULL); 132 | 133 | i = 1; 134 | v = (int*)calloc(1, sizeof(int)); 135 | *v = i; 136 | cstl_list_insert(list, 0, &v, sizeof(int*)); 137 | cstl_list_for_each(list, print_e, NULL); 138 | 139 | i = 11; 140 | v = (int*)calloc(1, sizeof(int)); 141 | memcpy(v, &i, sizeof(int)); 142 | cstl_list_insert(list, 10, &v, sizeof(int*)); 143 | cstl_list_for_each(list, print_e, NULL); 144 | 145 | i = 12; 146 | v = (int*)calloc(1, sizeof(int)); 147 | memcpy(v, &i, sizeof(int)); 148 | cstl_list_insert(list, 200, &v, sizeof(int*)); 149 | cstl_list_for_each(list, print_e, NULL); 150 | 151 | cstl_list_remove(list, cstl_list_count(list) - 1); 152 | cstl_list_for_each(list, print_e, NULL); 153 | 154 | tmp = (int*)calloc(1, sizeof(int)); 155 | *tmp = 10; 156 | if ((outValue = cstl_list_find(list, &tmp))) { 157 | assert(*tmp == **((int**)outValue)); 158 | } 159 | 160 | *tmp = 100; 161 | outValue = cstl_list_find(list, &tmp); 162 | assert(outValue == NULL); 163 | free(tmp); 164 | 165 | outValue = cstl_list_element_at(list, 7); 166 | assert(**((int**)outValue) == 8); 167 | 168 | assert(cstl_list_size(list) == 11); 169 | 170 | cstl_list_destroy(list); 171 | 172 | test_with_iterators(); 173 | } 174 | -------------------------------------------------------------------------------- /test/t_c_algorithms.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "c_stl_lib.h" 5 | 6 | void print_integers(const void* value, const void* key, void* p) 7 | { 8 | (void)key; 9 | (void)p; 10 | if (value) { 11 | printf("%d\n", *(int*)value); 12 | } 13 | } 14 | 15 | void print_integers_ptr(const void* value, const void* key, void* p) 16 | { 17 | (void)key; 18 | (void)p; 19 | if (value) { 20 | printf("%d\n", **((int**)value)); 21 | } 22 | } 23 | 24 | static void free_element(void* ptr) 25 | { 26 | if (ptr) { 27 | void* p = *((void**)ptr); 28 | if (p) { 29 | free(p); 30 | } 31 | } 32 | } 33 | 34 | static int compare_strings(const void* left, const void* right) 35 | { 36 | return strcmp((const char*)left, (const char*)right); 37 | } 38 | 39 | static int compare_integers(const void* left, const void* right) 40 | { 41 | int* l = (int*)left; 42 | int* r = (int*)right; 43 | 44 | return (*l - *r); 45 | } 46 | 47 | static int compare_integers_ptr(const void* left, const void* right) 48 | { 49 | int* l = *((int**)left); 50 | int* r = *((int**)right); 51 | return (*l - *r); 52 | } 53 | 54 | static struct cstl_array* create_c_array() 55 | { 56 | int size = 10; 57 | int i = 0; 58 | void* p_rv = (void*)0; 59 | int rv = 0; 60 | 61 | struct cstl_array* myArray = cstl_array_new(8, compare_integers, NULL); 62 | assert(0 != cstl_array_is_empty(myArray)); 63 | 64 | for (i = 0; i < size; i++) { 65 | cstl_array_push_back(myArray, &i, sizeof(int)); 66 | } 67 | assert(0 == cstl_array_is_empty(myArray)); 68 | assert((size_t)size == cstl_array_size(myArray)); 69 | for (i = 0; i < size; i++) { 70 | p_rv = (void*)cstl_array_element_at(myArray, i); 71 | rv = *(int*)p_rv; 72 | assert(rv == i); 73 | (void)rv; 74 | } 75 | return myArray; 76 | } 77 | 78 | static struct cstl_deque* create_deque() 79 | { 80 | int flip = 1; 81 | int i = 0; 82 | int limit = 20; 83 | struct cstl_deque* myDeq = cstl_deque_new(10, compare_integers, NULL); 84 | assert((struct cstl_deque*)0 != myDeq); 85 | 86 | for (i = 0; i <= limit; i++) { 87 | if (flip) { 88 | cstl_deque_push_back(myDeq, &i, sizeof(int)); 89 | flip = 0; 90 | } 91 | else { 92 | cstl_deque_push_front(myDeq, &i, sizeof(int)); 93 | flip = 1; 94 | } 95 | } 96 | return myDeq; 97 | } 98 | 99 | static struct cstl_set* create_set() 100 | { 101 | int test[] = { 13, 8, 17, 1, 11, 15, 25, 6, 22, 27 }; 102 | int index = 0; 103 | int size = sizeof(test) / sizeof(test[0]); 104 | struct cstl_set* pSet = cstl_set_new(compare_integers, NULL); 105 | 106 | for (index = 0; index < size; index++) { 107 | int v = test[index]; 108 | cstl_set_insert(pSet, &v, sizeof(int)); 109 | } 110 | return pSet; 111 | } 112 | 113 | static struct cstl_map* create_map() 114 | { 115 | char* char_value[] = { 116 | "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 117 | "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", 118 | }; 119 | int int_value[] = { 120 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 121 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 122 | }; 123 | int size = sizeof(char_value) / sizeof(char_value[0]); 124 | int i = 0; 125 | struct cstl_map* pMap = cstl_map_new(compare_strings, NULL, NULL); 126 | for (i = 0; i < size; i++) { 127 | char* key = char_value[i]; 128 | int key_length = (int)strlen(key) + 1; 129 | int value = int_value[i]; 130 | cstl_map_insert(pMap, key, key_length, &value, sizeof(int)); 131 | } 132 | return pMap; 133 | } 134 | 135 | static struct cstl_list* create_slist() 136 | { 137 | struct cstl_list* pList = cstl_list_new(free_element, compare_integers_ptr); 138 | int i = 0; 139 | for (i = 0; i <= 10; i++) { 140 | int* v = (int*)calloc(1, sizeof(int)); 141 | *v = i; /* memcpy ( v, &i, sizeof ( int )); */ 142 | cstl_list_push_back(pList, &v, sizeof(int*)); 143 | } 144 | return pList; 145 | } 146 | 147 | static void t_cstl_for_each(void) 148 | { 149 | struct cstl_array* pArray; 150 | struct cstl_deque* pDeq; 151 | struct cstl_set* pSet; 152 | struct cstl_map* pMap; 153 | struct cstl_list* pList; 154 | struct cstl_iterator* pArrayIterator; 155 | struct cstl_iterator* pDequeIterator; 156 | struct cstl_iterator* pSetIterator; 157 | struct cstl_iterator* pMapIterator; 158 | struct cstl_iterator* pListIterator; 159 | 160 | printf("Performing for_each for array\n"); 161 | pArray = create_c_array(); 162 | pArrayIterator = cstl_array_new_iterator(pArray); 163 | cstl_for_each(pArrayIterator, print_integers, NULL); 164 | cstl_array_delete(pArray); 165 | cstl_array_delete_iterator(pArrayIterator); 166 | 167 | printf("Performing for_each for deque\n"); 168 | pDeq = create_deque(); 169 | pDequeIterator = cstl_deque_new_iterator(pDeq); 170 | cstl_for_each(pDequeIterator, print_integers, NULL); 171 | cstl_deque_delete(pDeq); 172 | cstl_deque_delete_iterator(pDequeIterator); 173 | 174 | printf("Performing for_each for set\n"); 175 | pSet = create_set(); 176 | pSetIterator = cstl_set_new_iterator(pSet); 177 | cstl_for_each(pSetIterator, print_integers, NULL); 178 | cstl_set_delete(pSet); 179 | cstl_set_delete_iterator(pSetIterator); 180 | 181 | printf("Performing for_each for map\n"); 182 | pMap = create_map(); 183 | pMapIterator = cstl_map_new_iterator(pMap); 184 | cstl_for_each(pMapIterator, print_integers, NULL); 185 | cstl_map_delete(pMap); 186 | cstl_map_delete_iterator(pMapIterator); 187 | 188 | printf("Performing for_each for list\n"); 189 | pList = create_slist(); 190 | pListIterator = cstl_list_new_iterator(pList); 191 | cstl_for_each(pListIterator, print_integers_ptr, NULL); 192 | cstl_list_destroy(pList); 193 | cstl_list_delete_iterator(pListIterator); 194 | } 195 | 196 | void test_c_algorithms() 197 | { 198 | t_cstl_for_each(); 199 | } 200 | -------------------------------------------------------------------------------- /src/c_set.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include "c_set.h" 26 | #include 27 | #include 28 | #include "c_stl_lib.h" 29 | #include "rb-tree.h" 30 | 31 | struct cstl_set { 32 | struct rbt_tree* tree; 33 | }; 34 | 35 | struct cstl_set* cstl_set_new(cstl_compare fn_c, cstl_destroy fn_d) 36 | { 37 | struct cstl_set* s = (struct cstl_set*)calloc(1, sizeof(struct cstl_set)); 38 | if (s == (struct cstl_set*)0) { 39 | return (struct cstl_set*)0; 40 | } 41 | s->tree = rbt_tree_create(malloc, free, 0, fn_c, fn_d); 42 | if (s->tree == (struct rbt_tree*)0) { 43 | free(s); 44 | return (struct cstl_set*)0; 45 | } 46 | return s; 47 | } 48 | 49 | cstl_error cstl_set_insert(struct cstl_set* pSet, void* key, size_t key_size) 50 | { 51 | rbt_status e; 52 | if (pSet == (struct cstl_set*)0) { 53 | return CSTL_SET_NOT_INITIALIZED; 54 | } 55 | e = rbt_tree_insert(pSet->tree, key, key_size); 56 | return e == rbt_status_success ? CSTL_ERROR_SUCCESS : CSTL_ERROR_ERROR; 57 | } 58 | 59 | int cstl_set_is_key_exists(struct cstl_set* pSet, void* key) 60 | { 61 | int found = 0; 62 | struct rbt_node* node; 63 | 64 | if (pSet == (struct cstl_set*)0) { 65 | return 0; 66 | } 67 | node = rbt_tree_find(pSet->tree, key); 68 | if (rbt_node_is_valid(node)) { 69 | return 1; 70 | } 71 | return found; 72 | } 73 | 74 | cstl_error cstl_set_remove(struct cstl_set* pSet, void* key) 75 | { 76 | if (pSet == (struct cstl_set*)0) { 77 | return CSTL_SET_NOT_INITIALIZED; 78 | } 79 | return (cstl_error)rbt_tree_remove_node(pSet->tree, key); 80 | } 81 | 82 | const void* cstl_set_find(struct cstl_set* pSet, const void* key) 83 | { 84 | struct rbt_node* node; 85 | 86 | if (pSet == (struct cstl_set*)0) { 87 | return NULL; 88 | } 89 | node = rbt_tree_find(pSet->tree, key); 90 | if (node == (struct rbt_node*)0) { 91 | return NULL; 92 | } 93 | return rbt_node_get_key(node); 94 | } 95 | 96 | cstl_error cstl_set_delete(struct cstl_set* x) 97 | { 98 | cstl_error rc = CSTL_ERROR_SUCCESS; 99 | if (x != (struct cstl_set*)0) { 100 | rc = (cstl_error)rbt_tree_destroy(x->tree); 101 | free(x); 102 | } 103 | return rc; 104 | } 105 | 106 | static struct rbt_node* cstl_set_minimum(struct cstl_set* x) 107 | { 108 | return rbt_tree_minimum(x->tree, rbt_tree_get_root(x->tree)); 109 | } 110 | 111 | static const void* cstl_set_get_next(struct cstl_iterator* pIterator) 112 | { 113 | struct cstl_set* x = (struct cstl_set*)pIterator->pContainer; 114 | struct rbt_node* ptr = NULL; 115 | if (NULL == pIterator->current_element) { 116 | pIterator->current_element = cstl_set_minimum(x); 117 | } 118 | else { 119 | pIterator->current_element = 120 | rbt_tree_successor(x->tree, 121 | (struct rbt_node*)pIterator->current_element); 122 | } 123 | ptr = (struct rbt_node*)pIterator->current_element; 124 | if (ptr == NULL || rbt_node_get_key(ptr) == NULL) { 125 | return NULL; 126 | } 127 | return ptr; 128 | } 129 | 130 | static const void* cstl_set_get_key(struct cstl_iterator* pIterator) 131 | { 132 | struct rbt_node* current = (struct rbt_node*)pIterator->current_element; 133 | return rbt_node_get_key(current); 134 | } 135 | 136 | static const void* cstl_set_get_value(struct cstl_iterator* pIterator) 137 | { 138 | return cstl_set_get_key(pIterator); 139 | } 140 | 141 | struct cstl_iterator* cstl_set_new_iterator(struct cstl_set* pSet) 142 | { 143 | struct cstl_iterator* itr = 144 | (struct cstl_iterator*)calloc(1, sizeof(struct cstl_iterator)); 145 | if (itr) { 146 | itr->next = cstl_set_get_next; 147 | itr->current_key = cstl_set_get_key; 148 | itr->current_value = cstl_set_get_value; 149 | itr->pContainer = pSet; 150 | itr->current_index = 0; 151 | itr->current_element = (void*)0; 152 | } 153 | return itr; 154 | } 155 | 156 | void cstl_set_delete_iterator(struct cstl_iterator* pItr) 157 | { 158 | free(pItr); 159 | } 160 | 161 | void cstl_set_container_traverse(struct cstl_set* set, fn_cstl_set_iter fn, 162 | void* p) 163 | { 164 | struct cstl_iterator* iterator; 165 | const void* element; 166 | int stop = 0; 167 | if (set == NULL || fn == NULL) { 168 | return; 169 | } 170 | iterator = cstl_set_new_iterator(set); 171 | while ((element = iterator->next(iterator))) { 172 | const void* obj = *((const void**)iterator->current_value(iterator)); 173 | fn(set, obj, &stop, p); 174 | if (stop != 0) { 175 | break; 176 | } 177 | } 178 | cstl_set_delete_iterator(iterator); 179 | } 180 | 181 | void cstl_set_container_add(struct cstl_set* set, void* obj) 182 | { 183 | assert(set && obj); 184 | cstl_set_insert(set, &obj, sizeof(void*)); 185 | } 186 | 187 | void cstl_set_container_remove(struct cstl_set* set, void* obj) 188 | { 189 | assert(0 != cstl_set_is_key_exists(set, &obj)); 190 | cstl_set_remove(set, &obj); 191 | } 192 | -------------------------------------------------------------------------------- /test/t_c_map.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include 26 | #include 27 | #include 28 | #include "c_stl_lib.h" 29 | 30 | static int compare_e(const void* left, const void* right) 31 | { 32 | const char* l = *(const char**)left; 33 | const char* r = *(const char**)right; 34 | return strcmp(l, r); 35 | } 36 | 37 | static void key_destroy(void* key) 38 | { 39 | free(*(char**)key); 40 | } 41 | 42 | char* char_value[] = { 43 | "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 44 | "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", 45 | }; 46 | int int_value[] = { 47 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 48 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 49 | }; 50 | 51 | static void insert_all(struct cstl_map* myMap) 52 | { 53 | int size = sizeof(char_value) / sizeof(char_value[0]); 54 | int i = 0; 55 | for (i = 0; i < size; i++) { 56 | char* key = strdup(char_value[i]); 57 | int value = int_value[i]; 58 | printf("Inserting [%s -> %d]\n", key, value); 59 | cstl_map_insert(myMap, &key, sizeof(char*), &value, sizeof(value)); 60 | } 61 | } 62 | 63 | static void check_exists_all(struct cstl_map* myMap) 64 | { 65 | int size = sizeof(char_value) / sizeof(char_value[0]); 66 | int i = 0; 67 | for (i = 0; i < size; i++) { 68 | char* key = char_value[i]; 69 | int* value; 70 | assert(0 != cstl_map_is_key_exists(myMap, &key)); 71 | value = (int*)cstl_map_find(myMap, &key); 72 | assert(value != NULL); 73 | printf("-----> [%s == %d]\n", key, *value); 74 | assert(*value == int_value[i]); 75 | } 76 | } 77 | 78 | static void remove_some_exist(struct cstl_map* myMap) 79 | { 80 | char* key = "A"; 81 | cstl_error error; 82 | error = cstl_map_remove(myMap, &key); 83 | assert(CSTL_ERROR_SUCCESS == error); 84 | assert(0 == cstl_map_is_key_exists(myMap, &key)); 85 | 86 | key = "X"; 87 | error = cstl_map_remove(myMap, &key); 88 | assert(CSTL_ERROR_SUCCESS == error); 89 | assert(0 == cstl_map_is_key_exists(myMap, &key)); 90 | 91 | key = "Z"; 92 | error = cstl_map_remove(myMap, &key); 93 | assert(CSTL_ERROR_SUCCESS == error); 94 | assert(0 == cstl_map_is_key_exists(myMap, &key)); 95 | 96 | key = "H"; 97 | error = cstl_map_remove(myMap, &key); 98 | assert(CSTL_ERROR_SUCCESS == error); 99 | assert(0 == cstl_map_is_key_exists(myMap, &key)); 100 | (void)error; 101 | } 102 | 103 | static void add_removed_check_all(struct cstl_map* myMap) 104 | { 105 | char* key = strdup("A"); 106 | cstl_map_insert(myMap, &key, sizeof(char*), &int_value[0], sizeof(int)); 107 | 108 | key = strdup("X"); 109 | cstl_map_insert(myMap, &key, sizeof(char*), &int_value[23], sizeof(int)); 110 | 111 | key = strdup("Z"); 112 | cstl_map_insert(myMap, &key, sizeof(char*), &int_value[25], sizeof(int)); 113 | 114 | key = strdup("H"); 115 | cstl_map_insert(myMap, &key, sizeof(char*), &int_value[7], sizeof(int)); 116 | 117 | check_exists_all(myMap); 118 | } 119 | 120 | static void print_using_iterator(struct cstl_map* myMap) 121 | { 122 | struct cstl_iterator* myItr; 123 | const void* pElement; 124 | printf("------------------------------------------------\n"); 125 | myItr = cstl_map_new_iterator(myMap); 126 | 127 | while ((pElement = myItr->next(myItr))) { 128 | int* value = (int*)myItr->current_value(myItr); 129 | char* key = *((char**)myItr->current_key(myItr)); 130 | printf("%s : %d\n", key, *value); 131 | } 132 | cstl_map_delete_iterator(myItr); 133 | } 134 | 135 | static void replace_values_using_iterators(struct cstl_map* myMap) 136 | { 137 | struct cstl_iterator* myItr; 138 | const void* pElement; 139 | printf("------------------------------------------------\n"); 140 | myItr = cstl_map_new_iterator(myMap); 141 | while ((pElement = myItr->next(myItr)) != NULL) { 142 | const void* old_value = myItr->current_value(myItr); 143 | int new_value = *(int*)old_value; 144 | new_value = new_value * 2; 145 | myItr->replace_current_value(myItr, &new_value, sizeof(new_value)); 146 | } 147 | cstl_map_delete_iterator(myItr); 148 | } 149 | 150 | static void test_with_iterators() 151 | { 152 | struct cstl_map* myMap = cstl_map_new(compare_e, key_destroy, NULL); 153 | insert_all(myMap); 154 | print_using_iterator(myMap); 155 | replace_values_using_iterators(myMap); 156 | print_using_iterator(myMap); 157 | cstl_map_delete(myMap); 158 | } 159 | 160 | void iter_fn(struct cstl_map* map, const void* key, const void* value, 161 | int* stop, void* p) 162 | { 163 | (void)value; 164 | (void)stop; 165 | (void)p; 166 | cstl_map_remove(map, key); 167 | } 168 | 169 | void test_c_map() 170 | { 171 | struct cstl_map* myMap = cstl_map_new(compare_e, key_destroy, NULL); 172 | insert_all(myMap); 173 | check_exists_all(myMap); 174 | remove_some_exist(myMap); 175 | add_removed_check_all(myMap); 176 | cstl_map_traverse(myMap, iter_fn, NULL); 177 | cstl_map_delete(myMap); 178 | test_with_iterators(); 179 | } 180 | -------------------------------------------------------------------------------- /src/c_list.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include "c_stl_lib.h" 26 | 27 | struct cstl_list_node { 28 | struct cstl_object* elem; 29 | struct cstl_list_node* next; 30 | }; 31 | 32 | struct cstl_list { 33 | struct cstl_list_node* head; 34 | cstl_destroy destruct_fn; 35 | cstl_compare compare_key_fn; 36 | size_t size; 37 | }; 38 | 39 | struct cstl_list* cstl_list_new(cstl_destroy fn_d, cstl_compare fn_c) 40 | { 41 | struct cstl_list* pList = 42 | (struct cstl_list*)calloc(1, sizeof(struct cstl_list)); 43 | pList->head = (struct cstl_list_node*)0; 44 | pList->destruct_fn = fn_d; 45 | pList->compare_key_fn = fn_c; 46 | pList->size = 0; 47 | return pList; 48 | } 49 | 50 | size_t cstl_list_count(struct cstl_list* pList) 51 | { 52 | return pList->size; 53 | } 54 | 55 | void cstl_list_destroy(struct cstl_list* pList) 56 | { 57 | cstl_list_clear(pList); 58 | free(pList); 59 | } 60 | 61 | void cstl_list_clear(struct cstl_list* pList) 62 | { 63 | while (pList->size != 0) { 64 | cstl_list_remove(pList, 0); 65 | } 66 | } 67 | 68 | cstl_error cstl_list_push_back(struct cstl_list* pList, void* elem, 69 | size_t elem_size) 70 | { 71 | return cstl_list_insert(pList, pList->size, elem, elem_size); 72 | } 73 | 74 | static void __cstl_slist_remove(struct cstl_list* pList, 75 | struct cstl_list_node* pSlistNode) 76 | { 77 | if (pList->destruct_fn) { 78 | void* elem = (void*)cstl_object_get_data(pSlistNode->elem); 79 | if (elem) { 80 | pList->destruct_fn(elem); 81 | } 82 | } 83 | cstl_object_delete(pSlistNode->elem); 84 | 85 | free(pSlistNode); 86 | } 87 | 88 | void cstl_list_remove(struct cstl_list* pList, size_t pos) 89 | { 90 | size_t i = 0; 91 | 92 | struct cstl_list_node* current = pList->head; 93 | struct cstl_list_node* previous = (struct cstl_list_node*)0; 94 | 95 | if (pos >= pList->size) { 96 | return; 97 | } 98 | 99 | if (pos == 0) { 100 | pList->head = current->next; 101 | __cstl_slist_remove(pList, current); 102 | pList->size--; 103 | return; 104 | } 105 | for (i = 0; i < pos; ++i) { 106 | previous = current; 107 | current = current->next; 108 | } 109 | previous->next = current->next; 110 | __cstl_slist_remove(pList, current); 111 | 112 | pList->size--; 113 | } 114 | 115 | cstl_error cstl_list_insert(struct cstl_list* pList, size_t pos, void* elem, 116 | size_t elem_size) 117 | { 118 | size_t i = 0; 119 | struct cstl_list_node* current = pList->head; 120 | struct cstl_list_node* new_node = (struct cstl_list_node*)0; 121 | struct cstl_list_node* previous = (struct cstl_list_node*)0; 122 | 123 | if (pos > pList->size) { 124 | pos = pList->size; 125 | } 126 | 127 | new_node = (struct cstl_list_node*)calloc(1, sizeof(struct cstl_list_node)); 128 | new_node->next = (struct cstl_list_node*)0; 129 | new_node->elem = cstl_object_new(elem, elem_size); 130 | if (!new_node->elem) { 131 | free(new_node); 132 | return CSTL_SLIST_INSERT_FAILED; 133 | } 134 | 135 | if (pos == 0) { 136 | new_node->next = pList->head; 137 | pList->head = new_node; 138 | pList->size++; 139 | return CSTL_ERROR_SUCCESS; 140 | } 141 | 142 | for (i = 0; i < pos; ++i) { 143 | previous = current; 144 | current = current->next; 145 | } 146 | 147 | previous->next = new_node; 148 | new_node->next = current; 149 | pList->size++; 150 | 151 | return CSTL_ERROR_SUCCESS; 152 | } 153 | 154 | void cstl_list_for_each(struct cstl_list* pList, 155 | void (*fn)(const void* elem, void* p), void* p) 156 | { 157 | struct cstl_list_node* current = pList->head; 158 | if (fn == NULL) { 159 | return; 160 | } 161 | while (current != (struct cstl_list_node*)0) { 162 | fn(cstl_object_get_data(current->elem), p); 163 | current = current->next; 164 | } 165 | } 166 | 167 | const void* cstl_list_find(struct cstl_list* pList, void* find_value) 168 | { 169 | struct cstl_list_node* current = pList->head; 170 | while (current != (struct cstl_list_node*)0) { 171 | const void* tmp = cstl_object_get_data(current->elem); 172 | if (pList->compare_key_fn(find_value, tmp) == 0) { 173 | return tmp; 174 | } 175 | current = current->next; 176 | } 177 | return NULL; 178 | } 179 | 180 | const void* cstl_list_element_at(struct cstl_list* pList, size_t pos) 181 | { 182 | struct cstl_list_node* current = NULL; 183 | size_t index = 0; 184 | if (pList == NULL || pList->size == 0) { 185 | return NULL; 186 | } 187 | if (pos >= pList->size) { 188 | pos = (pList->size - 1); 189 | } 190 | current = pList->head; 191 | for (index = 0; index < pos; ++index) { 192 | current = current->next; 193 | } 194 | return current ? cstl_object_get_data(current->elem) : NULL; 195 | } 196 | 197 | size_t cstl_list_size(struct cstl_list* pList) 198 | { 199 | return pList ? pList->size : 0; 200 | } 201 | 202 | static const void* cstl_list_get_next(struct cstl_iterator* pIterator) 203 | { 204 | struct cstl_list* pList = (struct cstl_list*)pIterator->pContainer; 205 | if (!pIterator->current_element) { 206 | pIterator->current_element = (struct cstl_list_node*)pList->head; 207 | } 208 | else { 209 | pIterator->current_element = 210 | ((struct cstl_list_node*)pIterator->current_element)->next; 211 | } 212 | return pIterator->current_element; 213 | } 214 | 215 | static const void* cstl_list_get_value(struct cstl_iterator* pIterator) 216 | { 217 | struct cstl_object* pObj = 218 | ((struct cstl_list_node*)pIterator->current_element)->elem; 219 | return cstl_object_get_data(pObj); 220 | } 221 | 222 | static void cstl_list_replace_value(struct cstl_iterator* pIterator, void* elem, 223 | size_t elem_size) 224 | { 225 | struct cstl_list* pList = (struct cstl_list*)pIterator->pContainer; 226 | struct cstl_object* pObj = 227 | ((struct cstl_list_node*)pIterator->current_element)->elem; 228 | 229 | if (pList->destruct_fn) { 230 | void* old_element = (void*)cstl_object_get_data(pObj); 231 | if (old_element) { 232 | pList->destruct_fn(old_element); 233 | } 234 | } 235 | cstl_object_replace_raw(pObj, elem, elem_size); 236 | } 237 | 238 | struct cstl_iterator* cstl_list_new_iterator(struct cstl_list* pList) 239 | { 240 | struct cstl_iterator* itr = 241 | (struct cstl_iterator*)calloc(1, sizeof(struct cstl_iterator)); 242 | itr->next = cstl_list_get_next; 243 | itr->current_value = cstl_list_get_value; 244 | itr->replace_current_value = cstl_list_replace_value; 245 | itr->pContainer = pList; 246 | itr->current_element = (void*)0; 247 | itr->current_index = 0; 248 | return itr; 249 | } 250 | 251 | void cstl_list_delete_iterator(struct cstl_iterator* pItr) 252 | { 253 | free(pItr); 254 | } 255 | -------------------------------------------------------------------------------- /src/c_deque.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include 26 | #include "c_stl_lib.h" 27 | 28 | struct cstl_deque { 29 | struct cstl_object** pElements; 30 | size_t capacity; 31 | size_t count; 32 | size_t head; 33 | size_t tail; 34 | cstl_compare compare_fn; 35 | cstl_destroy destruct_fn; 36 | }; 37 | 38 | #define cstl_deque_INDEX(x) \ 39 | ((char*)(pDeq)->pElements + (sizeof(struct cstl_object) * (x))) 40 | 41 | static cstl_error cstl_deque_insert(struct cstl_deque* pDeq, size_t index, 42 | void* elem, size_t elem_size) 43 | { 44 | cstl_error rc = CSTL_ERROR_SUCCESS; 45 | struct cstl_object* pObject = cstl_object_new(elem, elem_size); 46 | if (!pObject) { 47 | return CSTL_ARRAY_INSERT_FAILED; 48 | } 49 | pDeq->pElements[index] = pObject; 50 | pDeq->count++; 51 | return rc; 52 | } 53 | 54 | static struct cstl_deque* cstl_deque_grow(struct cstl_deque* pDeq) 55 | { 56 | size_t size; 57 | pDeq->capacity = pDeq->capacity * 2; 58 | size = pDeq->capacity * sizeof(struct cstl_object*); 59 | pDeq->pElements = (struct cstl_object**)realloc(pDeq->pElements, size); 60 | return pDeq; 61 | } 62 | 63 | struct cstl_deque* cstl_deque_new(size_t deq_size, cstl_compare fn_c, 64 | cstl_destroy fn_d) 65 | { 66 | struct cstl_deque* pDeq = 67 | (struct cstl_deque*)calloc(1, sizeof(struct cstl_deque)); 68 | if (pDeq == (struct cstl_deque*)0) { 69 | return (struct cstl_deque*)0; 70 | } 71 | pDeq->capacity = deq_size < 8 ? 8 : deq_size; 72 | pDeq->pElements = (struct cstl_object**)calloc(pDeq->capacity, 73 | sizeof(struct cstl_object*)); 74 | 75 | if (pDeq == (struct cstl_deque*)0) { 76 | return (struct cstl_deque*)0; 77 | } 78 | pDeq->compare_fn = fn_c; 79 | pDeq->destruct_fn = fn_d; 80 | pDeq->head = pDeq->capacity / 2; 81 | pDeq->tail = pDeq->head + 1; 82 | pDeq->count = 0; 83 | 84 | return pDeq; 85 | } 86 | 87 | size_t cstl_deque_count(struct cstl_deque* deque) 88 | { 89 | return deque->count; 90 | } 91 | 92 | cstl_error cstl_deque_push_back(struct cstl_deque* pDeq, void* elem, 93 | size_t elem_size) 94 | { 95 | if (pDeq == (struct cstl_deque*)0) { 96 | return CSTL_DEQUE_NOT_INITIALIZED; 97 | } 98 | if (pDeq->tail == pDeq->capacity) { 99 | pDeq = cstl_deque_grow(pDeq); 100 | } 101 | cstl_deque_insert(pDeq, pDeq->tail, elem, elem_size); 102 | pDeq->tail++; 103 | 104 | return CSTL_ERROR_SUCCESS; 105 | } 106 | 107 | cstl_error cstl_deque_push_front(struct cstl_deque* pDeq, void* elem, 108 | size_t elem_size) 109 | { 110 | cstl_error rc = CSTL_ERROR_SUCCESS; 111 | size_t to = 0; 112 | size_t from = 0; 113 | size_t count = 0; 114 | 115 | if (pDeq->head == 0) { 116 | pDeq = cstl_deque_grow(pDeq); 117 | to = (pDeq->capacity - pDeq->count) / 2; 118 | from = pDeq->head + 1; 119 | count = pDeq->tail - from; 120 | memmove(&(pDeq->pElements[to]), &(pDeq->pElements[from]), 121 | count * sizeof(struct cstl_object*)); 122 | pDeq->head = to - 1; 123 | pDeq->tail = pDeq->head + count + 1; 124 | } 125 | cstl_deque_insert(pDeq, pDeq->head, elem, elem_size); 126 | pDeq->head--; 127 | return rc; 128 | } 129 | 130 | const void* cstl_deque_front(struct cstl_deque* pDeq) 131 | { 132 | if (pDeq) { 133 | return cstl_deque_element_at(pDeq, 0); 134 | } 135 | return (struct cstl_deque*)0; 136 | } 137 | 138 | const void* cstl_deque_back(struct cstl_deque* pDeq) 139 | { 140 | if (pDeq) { 141 | return cstl_deque_element_at(pDeq, pDeq->count - 1); 142 | } 143 | return (struct cstl_deque*)0; 144 | } 145 | 146 | cstl_error cstl_deque_pop_back(struct cstl_deque* pDeq) 147 | { 148 | if (pDeq == (struct cstl_deque*)0) { 149 | return CSTL_DEQUE_NOT_INITIALIZED; 150 | } 151 | if (pDeq->destruct_fn) { 152 | void* elem = (void*)cstl_deque_element_at(pDeq, pDeq->count - 1); 153 | if (elem) { 154 | pDeq->destruct_fn(elem); 155 | } 156 | } 157 | cstl_object_delete(pDeq->pElements[pDeq->tail - 1]); 158 | pDeq->tail--; 159 | pDeq->count--; 160 | 161 | return CSTL_ERROR_SUCCESS; 162 | } 163 | 164 | cstl_error cstl_deque_pop_front(struct cstl_deque* pDeq) 165 | { 166 | if (pDeq == (struct cstl_deque*)0) { 167 | return CSTL_DEQUE_NOT_INITIALIZED; 168 | } 169 | if (pDeq->destruct_fn) { 170 | void* elem = (void*)cstl_deque_element_at(pDeq, 0); 171 | if (elem) { 172 | pDeq->destruct_fn(elem); 173 | } 174 | } 175 | cstl_object_delete(pDeq->pElements[pDeq->head + 1]); 176 | 177 | pDeq->head++; 178 | pDeq->count--; 179 | 180 | return CSTL_ERROR_SUCCESS; 181 | } 182 | 183 | int cstl_deque_is_empty(struct cstl_deque* pDeq) 184 | { 185 | if (pDeq == (struct cstl_deque*)0) { 186 | return 1; 187 | } 188 | return pDeq->count == 0 ? 1 : 0; 189 | } 190 | 191 | size_t cstl_deque_size(struct cstl_deque* pDeq) 192 | { 193 | if (pDeq == (struct cstl_deque*)0) { 194 | return 0; 195 | } 196 | return pDeq->count; 197 | } 198 | 199 | const void* cstl_deque_element_at(struct cstl_deque* pDeq, size_t index) 200 | { 201 | if ((pDeq == NULL) || (index >= pDeq->count)) { 202 | return NULL; 203 | } 204 | return cstl_object_get_data(pDeq->pElements[(pDeq->head + 1) + index]); 205 | } 206 | 207 | cstl_error cstl_deque_delete(struct cstl_deque* pDeq) 208 | { 209 | size_t i = 0; 210 | 211 | if (pDeq == (struct cstl_deque*)0) { 212 | return CSTL_ERROR_SUCCESS; 213 | } 214 | if (pDeq->destruct_fn) { 215 | for (i = 0; i < pDeq->count; ++i) { 216 | void* elem = (void*)cstl_deque_element_at(pDeq, i); 217 | if (elem) { 218 | pDeq->destruct_fn(elem); 219 | } 220 | } 221 | } 222 | for (i = pDeq->head + 1; i < pDeq->tail; i++) { 223 | cstl_object_delete(pDeq->pElements[i]); 224 | } 225 | free(pDeq->pElements); 226 | free(pDeq); 227 | 228 | return CSTL_ERROR_SUCCESS; 229 | } 230 | 231 | static const void* cstl_deque_get_next(struct cstl_iterator* pIterator) 232 | { 233 | struct cstl_deque* pDeq = (struct cstl_deque*)pIterator->pContainer; 234 | size_t index = pIterator->current_index; 235 | 236 | if (index <= pDeq->head || index >= pDeq->tail) { 237 | return (const void*)0; 238 | } 239 | pIterator->current_element = pDeq->pElements[pIterator->current_index++]; 240 | return pIterator->current_element; 241 | } 242 | 243 | static const void* cstl_deque_get_value(struct cstl_iterator* pIterator) 244 | { 245 | struct cstl_object* element = 246 | (struct cstl_object*)pIterator->current_element; 247 | return cstl_object_get_data(element); 248 | } 249 | 250 | static void cstl_deque_replace_value(struct cstl_iterator* pIterator, 251 | void* elem, size_t elem_size) 252 | { 253 | struct cstl_deque* pDeq = (struct cstl_deque*)pIterator->pContainer; 254 | struct cstl_object* currentElement = 255 | (struct cstl_object*)pIterator->current_element; 256 | if (pDeq->destruct_fn) { 257 | void* old_element = (void*)cstl_object_get_data(currentElement); 258 | if (old_element) { 259 | pDeq->destruct_fn(old_element); 260 | } 261 | } 262 | cstl_object_replace_raw(currentElement, elem, elem_size); 263 | } 264 | 265 | struct cstl_iterator* cstl_deque_new_iterator(struct cstl_deque* pDeq) 266 | { 267 | struct cstl_iterator* itr = 268 | (struct cstl_iterator*)calloc(1, sizeof(struct cstl_iterator)); 269 | itr->next = cstl_deque_get_next; 270 | itr->current_value = cstl_deque_get_value; 271 | itr->replace_current_value = cstl_deque_replace_value; 272 | itr->current_index = pDeq->head + 1; 273 | itr->pContainer = pDeq; 274 | return itr; 275 | } 276 | 277 | void cstl_deque_delete_iterator(struct cstl_iterator* pItr) 278 | { 279 | free(pItr); 280 | } 281 | -------------------------------------------------------------------------------- /msvc/cstl.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {475DE074-DA8E-3E95-929A-5D73E659170A} 23 | Win32Proj 24 | Win32 25 | cstl 26 | 27 | 28 | 29 | StaticLibrary 30 | MultiByte 31 | 32 | 33 | StaticLibrary 34 | MultiByte 35 | 36 | 37 | StaticLibrary 38 | MultiByte 39 | 40 | 41 | StaticLibrary 42 | MultiByte 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ..\inc;%(AdditionalIncludeDirectories) 54 | EnableFastChecks 55 | ProgramDatabase 56 | 57 | 58 | Disabled 59 | Disabled 60 | NotUsing 61 | MultiThreadedDebugDLL 62 | Level3 63 | %(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug" 64 | 65 | 66 | %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\" 67 | ..\inc;%(AdditionalIncludeDirectories) 68 | 69 | 70 | ..\inc;%(AdditionalIncludeDirectories) 71 | $(ProjectDir)/$(IntDir) 72 | %(Filename).h 73 | %(Filename).tlb 74 | %(Filename)_i.c 75 | %(Filename)_p.c 76 | 77 | 78 | 79 | 80 | 81 | ..\inc;%(AdditionalIncludeDirectories) 82 | EnableFastChecks 83 | ProgramDatabase 84 | 85 | 86 | Disabled 87 | Disabled 88 | NotUsing 89 | MultiThreadedDebugDLL 90 | Level3 91 | %(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug" 92 | 93 | 94 | %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\" 95 | ..\inc;%(AdditionalIncludeDirectories) 96 | 97 | 98 | ..\inc;%(AdditionalIncludeDirectories) 99 | $(ProjectDir)/$(IntDir) 100 | %(Filename).h 101 | %(Filename).tlb 102 | %(Filename)_i.c 103 | %(Filename)_p.c 104 | 105 | 106 | 107 | 108 | 109 | ..\inc;%(AdditionalIncludeDirectories) 110 | 111 | 112 | AnySuitable 113 | MaxSpeed 114 | NotUsing 115 | MultiThreadedDLL 116 | Level3 117 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release" 118 | 119 | 120 | 121 | 122 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\" 123 | ..\inc;%(AdditionalIncludeDirectories) 124 | 125 | 126 | ..\inc;%(AdditionalIncludeDirectories) 127 | $(ProjectDir)/$(IntDir) 128 | %(Filename).h 129 | %(Filename).tlb 130 | %(Filename)_i.c 131 | %(Filename)_p.c 132 | 133 | 134 | 135 | 136 | 137 | ..\inc;%(AdditionalIncludeDirectories) 138 | 139 | 140 | AnySuitable 141 | MaxSpeed 142 | NotUsing 143 | MultiThreadedDLL 144 | Level3 145 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release" 146 | 147 | 148 | 149 | 150 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\" 151 | ..\inc;%(AdditionalIncludeDirectories) 152 | 153 | 154 | ..\inc;%(AdditionalIncludeDirectories) 155 | $(ProjectDir)/$(IntDir) 156 | %(Filename).h 157 | %(Filename).tlb 158 | %(Filename)_i.c 159 | %(Filename)_p.c 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /src/c_array.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include 26 | #include 27 | #include 28 | #include "c_stl_lib.h" 29 | 30 | struct cstl_array { 31 | size_t capacity; /* Number of maximum elements array can hold */ 32 | size_t count; /* Number of current elements in the array */ 33 | struct cstl_object** pElements; /* actual storage area */ 34 | cstl_compare compare_fn; /* Compare function pointer*/ 35 | cstl_destroy destruct_fn; /* Destructor function pointer*/ 36 | }; 37 | 38 | static struct cstl_array* cstl_array_check_and_grow(struct cstl_array* pArray, 39 | size_t new_size) 40 | { 41 | if (new_size >= pArray->capacity) { 42 | size_t size; 43 | void* tmp; 44 | while (new_size >= pArray->capacity) { 45 | pArray->capacity = 2 * pArray->capacity; 46 | } 47 | size = pArray->capacity * sizeof(struct cstl_object*); 48 | tmp = realloc(pArray->pElements, size); 49 | if (tmp) { 50 | pArray->pElements = (struct cstl_object**)tmp; 51 | } 52 | else { 53 | assert(!"memory out!!!"); 54 | } 55 | } 56 | return pArray; 57 | } 58 | 59 | struct cstl_array* cstl_array_new(size_t array_size, cstl_compare fn_c, 60 | cstl_destroy fn_d) 61 | { 62 | struct cstl_array* pArray = 63 | (struct cstl_array*)calloc(1, sizeof(struct cstl_array)); 64 | if (!pArray) { 65 | return (struct cstl_array*)0; 66 | } 67 | pArray->capacity = array_size < 8 ? 8 : array_size; 68 | pArray->pElements = 69 | (struct cstl_object**)calloc(pArray->capacity, 70 | sizeof(struct cstl_object*)); 71 | if (!pArray->pElements) { 72 | free(pArray); 73 | return (struct cstl_array*)0; 74 | } 75 | pArray->compare_fn = fn_c; 76 | pArray->destruct_fn = fn_d; 77 | pArray->count = 0; 78 | 79 | return pArray; 80 | } 81 | 82 | static cstl_error cstl_array_insert(struct cstl_array* pArray, size_t index, 83 | void* elem, size_t elem_size) 84 | { 85 | cstl_error rc = CSTL_ERROR_SUCCESS; 86 | struct cstl_object* pObject = cstl_object_new(elem, elem_size); 87 | if (!pObject) { 88 | return CSTL_ARRAY_INSERT_FAILED; 89 | } 90 | pArray->pElements[index] = pObject; 91 | pArray->count++; 92 | return rc; 93 | } 94 | 95 | cstl_error cstl_array_push_back(struct cstl_array* pArray, void* elem, 96 | size_t elem_size) 97 | { 98 | cstl_error rc = CSTL_ERROR_SUCCESS; 99 | 100 | if (!pArray) { 101 | return CSTL_ARRAY_NOT_INITIALIZED; 102 | } 103 | cstl_array_check_and_grow(pArray, pArray->count); 104 | 105 | rc = cstl_array_insert(pArray, pArray->count, elem, elem_size); 106 | 107 | return rc; 108 | } 109 | 110 | const void* cstl_array_element_at(struct cstl_array* pArray, size_t index) 111 | { 112 | if (!pArray) { 113 | return NULL; 114 | } 115 | if (index >= pArray->count) { 116 | return NULL; 117 | } 118 | return cstl_object_get_data(pArray->pElements[index]); 119 | } 120 | 121 | size_t cstl_array_size(struct cstl_array* pArray) 122 | { 123 | if (pArray == (struct cstl_array*)0) { 124 | return 0; 125 | } 126 | return pArray->count; 127 | } 128 | 129 | size_t cstl_array_capacity(struct cstl_array* pArray) 130 | { 131 | if (pArray == (struct cstl_array*)0) { 132 | return 0; 133 | } 134 | return pArray->capacity; 135 | } 136 | 137 | int cstl_array_is_empty(struct cstl_array* pArray) 138 | { 139 | if (pArray == (struct cstl_array*)0) { 140 | return 0; 141 | } 142 | return pArray->count == 0 ? 1 : 0; 143 | } 144 | 145 | cstl_error cstl_array_reserve(struct cstl_array* pArray, size_t new_size) 146 | { 147 | if (pArray == (struct cstl_array*)0) { 148 | return CSTL_ARRAY_NOT_INITIALIZED; 149 | } 150 | if (new_size <= pArray->capacity) { 151 | return CSTL_ERROR_SUCCESS; 152 | } 153 | cstl_array_check_and_grow(pArray, new_size); 154 | return CSTL_ERROR_SUCCESS; 155 | } 156 | 157 | const void* cstl_array_front(struct cstl_array* pArray) 158 | { 159 | return cstl_array_element_at(pArray, 0); 160 | } 161 | 162 | const void* cstl_array_back(struct cstl_array* pArray) 163 | { 164 | return cstl_array_element_at(pArray, pArray->count - 1); 165 | } 166 | 167 | cstl_error cstl_array_insert_at(struct cstl_array* pArray, size_t index, 168 | void* elem, size_t elem_size) 169 | { 170 | cstl_error rc = CSTL_ERROR_SUCCESS; 171 | if (!pArray) { 172 | return CSTL_ARRAY_NOT_INITIALIZED; 173 | } 174 | if (index > pArray->capacity) { 175 | return CSTL_ARRAY_INDEX_OUT_OF_BOUND; 176 | } 177 | assert(index <= pArray->count); 178 | cstl_array_check_and_grow(pArray, pArray->count); 179 | 180 | memmove(&(pArray->pElements[index + 1]), &pArray->pElements[index], 181 | (pArray->count - index) * sizeof(struct cstl_object*)); 182 | 183 | rc = cstl_array_insert(pArray, index, elem, elem_size); 184 | 185 | return rc; 186 | } 187 | 188 | cstl_error cstl_array_remove_from(struct cstl_array* pArray, size_t index) 189 | { 190 | cstl_error rc = CSTL_ERROR_SUCCESS; 191 | 192 | if (!pArray) { 193 | return rc; 194 | } 195 | if (index >= pArray->count) { 196 | return CSTL_ARRAY_INDEX_OUT_OF_BOUND; 197 | } 198 | if (pArray->destruct_fn) { 199 | void* elem = (void*)cstl_array_element_at(pArray, index); 200 | if (elem) { 201 | pArray->destruct_fn(elem); 202 | } 203 | } 204 | cstl_object_delete(pArray->pElements[index]); 205 | 206 | memmove(&(pArray->pElements[index]), &pArray->pElements[index + 1], 207 | (pArray->count - index) * sizeof(struct cstl_object*)); 208 | pArray->count--; 209 | 210 | return rc; 211 | } 212 | 213 | cstl_error cstl_array_delete(struct cstl_array* pArray) 214 | { 215 | cstl_error rc = CSTL_ERROR_SUCCESS; 216 | size_t i = 0; 217 | 218 | if (pArray == (struct cstl_array*)0) { 219 | return CSTL_ARRAY_NOT_INITIALIZED; 220 | } 221 | if (pArray->destruct_fn) { 222 | for (i = 0; i < pArray->count; i++) { 223 | void* elem = (void*)cstl_array_element_at(pArray, i); 224 | if (elem) { 225 | pArray->destruct_fn(elem); 226 | } 227 | } 228 | } 229 | 230 | for (i = 0; i < pArray->count; i++) { 231 | cstl_object_delete(pArray->pElements[i]); 232 | } 233 | free(pArray->pElements); 234 | free(pArray); 235 | return rc; 236 | } 237 | 238 | static const void* cstl_array_get_next(struct cstl_iterator* pIterator) 239 | { 240 | struct cstl_array* pArray = (struct cstl_array*)pIterator->pContainer; 241 | if (pIterator->current_index >= cstl_array_size(pArray)) { 242 | return (const void*)0; 243 | } 244 | pIterator->current_element = pArray->pElements[pIterator->current_index++]; 245 | return pIterator->current_element; 246 | } 247 | 248 | static const void* cstl_array_get_value(struct cstl_iterator* pIterator) 249 | { 250 | struct cstl_object* element = 251 | (struct cstl_object*)pIterator->current_element; 252 | return cstl_object_get_data(element); 253 | } 254 | 255 | static void cstl_array_replace_value(struct cstl_iterator* pIterator, 256 | void* elem, size_t elem_size) 257 | { 258 | struct cstl_array* pArray = (struct cstl_array*)pIterator->pContainer; 259 | struct cstl_object* currentElement = 260 | (struct cstl_object*)pIterator->current_element; 261 | if (pArray->destruct_fn) { 262 | void* old_element = (void*)cstl_object_get_data(currentElement); 263 | if (old_element) { 264 | pArray->destruct_fn(old_element); 265 | } 266 | } 267 | cstl_object_replace_raw(currentElement, elem, elem_size); 268 | } 269 | 270 | struct cstl_iterator* cstl_array_new_iterator(struct cstl_array* pArray) 271 | { 272 | struct cstl_iterator* itr = 273 | (struct cstl_iterator*)calloc(1, sizeof(struct cstl_iterator)); 274 | itr->next = cstl_array_get_next; 275 | itr->current_value = cstl_array_get_value; 276 | itr->replace_current_value = cstl_array_replace_value; 277 | itr->pContainer = pArray; 278 | itr->current_index = 0; 279 | return itr; 280 | } 281 | 282 | void cstl_array_delete_iterator(struct cstl_iterator* pItr) 283 | { 284 | free(pItr); 285 | } 286 | 287 | static void swap(struct cstl_object** a, struct cstl_object** b) 288 | { 289 | if (a != b) { 290 | struct cstl_object* tmp = *a; 291 | *a = *b; 292 | *b = tmp; 293 | } 294 | } 295 | 296 | /* quick sort */ 297 | void _cstl_array_quick_sort(struct cstl_array* pArray, int left, int right) 298 | { 299 | int i = left, j = right; 300 | const void* mid; 301 | assert(left < (int)pArray->count); 302 | assert(right < (int)pArray->count); 303 | mid = cstl_array_element_at(pArray, (left + right) / 2); 304 | while (i <= j) { 305 | while (pArray->compare_fn(cstl_array_element_at(pArray, i), mid) < 0) { 306 | i++; 307 | } 308 | while (pArray->compare_fn(cstl_array_element_at(pArray, j), mid) > 0) { 309 | j--; 310 | } 311 | if (i <= j) { 312 | if (i != j) { 313 | swap(&pArray->pElements[i], &pArray->pElements[j]); 314 | } 315 | i++; 316 | j--; 317 | } 318 | } 319 | if (left < j) { 320 | _cstl_array_quick_sort(pArray, left, j); 321 | } 322 | if (i < right) { 323 | _cstl_array_quick_sort(pArray, i, right); 324 | } 325 | } 326 | 327 | void cstl_array_quick_sort(struct cstl_array* pArray) 328 | { 329 | size_t size = cstl_array_size(pArray); 330 | if (size > 1) { 331 | _cstl_array_quick_sort(pArray, 0, (int)(size - 1)); 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /test/t_c_rb.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include "rb-tree.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static const void* get_key(struct rbt_tree* tree, const struct rbt_node* node) 34 | { 35 | (void)tree; 36 | if (node) 37 | return rbt_node_get_key(node); 38 | return (void*)0; 39 | } 40 | 41 | int compare_rb_e(const void* l, const void* r) 42 | { 43 | int left = *(int*)l; 44 | int right = *(int*)r; 45 | 46 | if (left < right) { 47 | return -1; 48 | } 49 | else if (left == right) { 50 | return 0; 51 | } 52 | else { 53 | return 1; 54 | } 55 | } 56 | 57 | typedef struct test_data_tree { 58 | int element; 59 | int left; 60 | int right; 61 | int parent; 62 | rbt_color color; 63 | } TS; 64 | 65 | static void retrieve_values(const struct rbt_node* v, TS* data, 66 | struct rbt_tree* tree) 67 | { 68 | struct rbt_node* x = NULL; 69 | data->element = *(int*)get_key(tree, v); 70 | data->color = rbt_node_get_color(v); 71 | if ((x = rbt_node_get_left(v)) && rbt_node_is_valid(x)) 72 | data->left = *(int*)get_key(tree, x); 73 | if ((x = rbt_node_get_right(v)) && rbt_node_is_valid(x)) 74 | data->right = *(int*)get_key(tree, x); 75 | if ((x = rbt_node_get_parent(v)) && rbt_node_is_valid(x)) 76 | data->parent = *(int*)get_key(tree, x); 77 | } 78 | 79 | static void test_each_elements(TS* lhs, TS* rhs) 80 | { 81 | assert(lhs->element == rhs->element); 82 | assert(lhs->color == rhs->color); 83 | assert(lhs->left == rhs->left); 84 | assert(lhs->right == rhs->right); 85 | assert(lhs->parent == rhs->parent); 86 | (void)lhs; 87 | (void)rhs; 88 | } 89 | 90 | static void test_all_elements(struct rbt_tree* tree, TS ts[], int size) 91 | { 92 | int i = 0; 93 | for (i = 0; i < size; i++) { 94 | struct test_data_tree data; 95 | const struct rbt_node* v = rbt_tree_find(tree, &ts[i].element); 96 | memset(&data, 0, sizeof(data)); 97 | retrieve_values(v, &data, tree); 98 | test_each_elements(&data, &ts[i]); 99 | } 100 | } 101 | 102 | static struct rbt_tree* create_tree(TS ts[], int size) 103 | { 104 | int i = 0; 105 | struct rbt_tree* tree = 106 | rbt_tree_create(malloc, free, 0, compare_rb_e, NULL); 107 | for (i = 0; i < size; i++) { 108 | rbt_tree_insert(tree, &(ts[i].element), sizeof((ts[i].element))); 109 | } 110 | return tree; 111 | } 112 | 113 | void test_c_rb() 114 | { 115 | int size; 116 | int size_after_delete; 117 | int i = 0; 118 | struct rbt_tree* tree; 119 | rbt_status s; 120 | 121 | TS ts[] = { 122 | { 15, 6, 18, 0, rbt_black }, { 6, 3, 9, 15, rbt_red }, 123 | { 18, 17, 20, 15, rbt_black }, { 3, 2, 4, 6, rbt_black }, 124 | { 7, 0, 0, 9, rbt_red }, { 17, 0, 0, 18, rbt_red }, 125 | { 20, 0, 0, 18, rbt_red }, { 2, 0, 0, 3, rbt_red }, 126 | { 4, 0, 0, 3, rbt_red }, { 13, 0, 0, 9, rbt_red }, 127 | { 9, 7, 13, 6, rbt_black }, 128 | }; 129 | TS ts_delete_leaf_13[] = { 130 | { 15, 6, 18, 0, rbt_black }, { 6, 3, 9, 15, rbt_red }, 131 | { 18, 17, 20, 15, rbt_black }, { 3, 2, 4, 6, rbt_black }, 132 | { 7, 0, 0, 9, rbt_red }, { 17, 0, 0, 18, rbt_red }, 133 | { 20, 0, 0, 18, rbt_red }, { 2, 0, 0, 3, rbt_red }, 134 | { 4, 0, 0, 3, rbt_red }, { 9, 7, 0, 6, rbt_black }, 135 | }; 136 | TS ts_delete_9[] = { 137 | { 15, 6, 18, 0, rbt_black }, { 6, 3, 7, 15, rbt_red }, 138 | { 18, 17, 20, 15, rbt_black }, { 3, 2, 4, 6, rbt_black }, 139 | { 7, 0, 0, 6, rbt_black }, { 17, 0, 0, 18, rbt_red }, 140 | { 20, 0, 0, 18, rbt_red }, { 2, 0, 0, 3, rbt_red }, 141 | { 4, 0, 0, 3, rbt_red }, 142 | }; 143 | TS ts_delete_15[] = { 144 | { 6, 3, 7, 17, rbt_red }, { 18, 0, 20, 17, rbt_black }, 145 | { 3, 2, 4, 6, rbt_black }, { 7, 0, 0, 6, rbt_black }, 146 | { 17, 6, 18, 0, rbt_black }, { 20, 0, 0, 18, rbt_red }, 147 | { 2, 0, 0, 3, rbt_red }, { 4, 0, 0, 3, rbt_red }, 148 | }; 149 | TS ts_insert_1[] = { 150 | { 6, 3, 17, 0, rbt_black }, { 18, 0, 20, 17, rbt_black }, 151 | { 3, 2, 4, 6, rbt_red }, { 7, 0, 0, 17, rbt_black }, 152 | { 17, 7, 18, 6, rbt_red }, { 20, 0, 0, 18, rbt_red }, 153 | { 2, 1, 0, 3, rbt_black }, { 4, 0, 0, 3, rbt_black }, 154 | { 1, 0, 0, 2, rbt_red }, 155 | }; 156 | 157 | size = (sizeof(ts) / sizeof(TS)); 158 | tree = create_tree(ts, size); 159 | test_all_elements(tree, ts, size); 160 | { 161 | i = 13; 162 | size = (sizeof(ts) / sizeof(TS)); 163 | size_after_delete = (sizeof(ts_delete_leaf_13) / sizeof(TS)); 164 | s = rbt_tree_remove_node(tree, &i); 165 | assert(s == rbt_status_success); 166 | test_all_elements(tree, ts_delete_leaf_13, size_after_delete); 167 | } 168 | { 169 | i = 9; 170 | size_after_delete = (sizeof(ts_delete_9) / sizeof(TS)); 171 | s = rbt_tree_remove_node(tree, &i); 172 | assert(s == rbt_status_success); 173 | test_all_elements(tree, ts_delete_9, size_after_delete); 174 | } 175 | { 176 | i = 15; 177 | size_after_delete = (sizeof(ts_delete_15) / sizeof(TS)); 178 | s = rbt_tree_remove_node(tree, &i); 179 | assert(s == rbt_status_success); 180 | test_all_elements(tree, ts_delete_15, size_after_delete); 181 | } 182 | { 183 | int i = 1; 184 | rbt_tree_insert(tree, &i, sizeof(i)); 185 | size_after_delete = (sizeof(ts_insert_1) / sizeof(TS)); 186 | test_all_elements(tree, ts_insert_1, size_after_delete); 187 | } 188 | { 189 | rbt_tree_destroy(tree); 190 | } 191 | (void)s; 192 | } 193 | 194 | void test_c_rb2(void) 195 | { 196 | struct rbt_node* node; 197 | int i; 198 | struct rbt_tree* t = rbt_tree_create(malloc, free, 0, compare_rb_e, NULL); 199 | 200 | srand((unsigned int)time(NULL)); 201 | 202 | assert(rbt_tree_is_empty(t)); 203 | assert(rbt_node_is_valid(rbt_tree_get_root(t)) == 0); 204 | 205 | for (i = 0; i < 5000; i++) { 206 | int x = rand() % 10000; 207 | if (rbt_status_key_duplicate == rbt_tree_insert(t, &x, sizeof(x))) { 208 | continue; 209 | } 210 | node = (struct rbt_node*)rbt_tree_find(t, &x); 211 | assert(*((int*)rbt_node_get_key(node)) == x); 212 | (void)node; 213 | } 214 | for (i = 0; i < 60000; i++) { 215 | int x = rand() % 10000; 216 | rbt_tree_remove_node(t, &x); 217 | } 218 | rbt_tree_destroy(t); 219 | } 220 | 221 | int compare_rb_e_alloc(const void* l, const void* r) 222 | { 223 | int left = **(int**)l; 224 | int right = **(int**)r; 225 | 226 | if (left < right) { 227 | return -1; 228 | } 229 | else if (left == right) { 230 | return 0; 231 | } 232 | else { 233 | return 1; 234 | } 235 | } 236 | 237 | int count = 0; 238 | 239 | void destroy_e_alloc(void* p) 240 | { 241 | int* _p = *(int**)p; 242 | ++count; 243 | free(_p); 244 | } 245 | 246 | void test_c_rb2_alloc(void) 247 | { 248 | struct rbt_node* node; 249 | int i; 250 | struct rbt_tree* t = 251 | rbt_tree_create(malloc, free, 0, compare_rb_e_alloc, destroy_e_alloc); 252 | 253 | srand((unsigned int)time(NULL)); 254 | 255 | for (i = 0; i < 5000; i++) { 256 | int* x = (int*)calloc(1, sizeof(*x)); 257 | *x = rand() % 10000; 258 | if (rbt_status_key_duplicate == rbt_tree_insert(t, &x, sizeof(x))) { 259 | free(x); 260 | continue; 261 | } 262 | node = (struct rbt_node*)rbt_tree_find(t, &x); 263 | assert(**((int**)rbt_node_get_key(node)) == *x); 264 | (void)node; 265 | } 266 | for (i = 0; i < 60000; i++) { 267 | int x = rand() % 10000; 268 | int* p = &x; 269 | rbt_tree_remove_node(t, &p); 270 | } 271 | rbt_tree_destroy(t); 272 | printf("==== delete count %d ====\n", count); 273 | } 274 | 275 | char* strArr[] = { 276 | "abcd1234", 277 | "good_idea", 278 | "just", 279 | "ding", 280 | }; 281 | 282 | int str_ptr_compare(const void* lhs, const void* rhs) 283 | { 284 | char* left = *(char**)lhs; 285 | char* right = *(char**)rhs; 286 | return strcmp(left, right); 287 | } 288 | 289 | void string_ptr_destroy(void* p) 290 | { 291 | char* _p = *(char**)p; 292 | free(_p); 293 | } 294 | 295 | void node_walk_cb3(struct rbt_node* node, void* p) 296 | { 297 | char* str = *(char**)rbt_node_get_key(node); 298 | printf("%s\n", str); 299 | (void)p; 300 | } 301 | 302 | void test_rbt_string(void) 303 | { 304 | const struct rbt_node* node; 305 | size_t i; 306 | struct rbt_tree* t = 307 | rbt_tree_create(malloc, free, 0, str_ptr_compare, string_ptr_destroy); 308 | for (i = 0; i < sizeof(strArr) / sizeof(strArr[0]); i++) { 309 | char* y; 310 | char* p = strdup(strArr[i]); 311 | if (0 != rbt_tree_insert(t, &p, sizeof(p))) { 312 | continue; 313 | } 314 | node = rbt_tree_find(t, &strArr[i]); 315 | y = *(char**)rbt_node_get_key(node); 316 | assert(strcmp(y, strArr[i]) == 0); 317 | (void)y; 318 | } 319 | 320 | printf("\n==== test_rbt_string ====\n"); 321 | rbt_inorder_walk(t, node_walk_cb3, NULL); 322 | 323 | rbt_tree_destroy(t); 324 | } 325 | 326 | int string_ptr_compare2(const void* lhs, const void* rhs) 327 | { 328 | return strcmp((char*)lhs, (char*)rhs); 329 | } 330 | 331 | void node_walk_cb4(struct rbt_node* node, void* p) 332 | { 333 | char* str = (char*)rbt_node_get_key(node); 334 | printf("%s\n", str); 335 | (void)p; 336 | } 337 | 338 | void test_rbt_string2(void) 339 | { 340 | const struct rbt_node* node; 341 | rbt_status s; 342 | size_t i; 343 | struct rbt_tree* t = 344 | rbt_tree_create(malloc, free, 0, string_ptr_compare2, NULL); 345 | for (i = 0; i < sizeof(strArr) / sizeof(strArr[0]); i++) { 346 | char* y; 347 | char* p = strArr[i]; 348 | if (rbt_status_success != rbt_tree_insert(t, p, strlen(p) + 1)) { 349 | continue; 350 | } 351 | node = rbt_tree_find(t, strArr[i]); 352 | y = (char*)rbt_node_get_key(node); 353 | assert(strcmp(y, strArr[i]) == 0); 354 | (void)y; 355 | } 356 | 357 | s = rbt_tree_remove_node(t, strArr[0]); 358 | assert(s == rbt_status_success); 359 | (void)s; 360 | 361 | printf("\n==== test_rbt_string2 ====\n"); 362 | rbt_inorder_walk(t, node_walk_cb4, NULL); 363 | 364 | rbt_tree_destroy(t); 365 | } 366 | -------------------------------------------------------------------------------- /src/c_map.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include 26 | #include 27 | #include 28 | #include "c_stl_lib.h" 29 | #include "rb-tree.h" 30 | 31 | struct cstl_map { 32 | struct rbt_tree* tree; 33 | int map_changed; 34 | cstl_compare fn_c_k; 35 | cstl_destroy fn_k_d; 36 | cstl_destroy fn_v_d; 37 | }; 38 | 39 | struct cstl_map_item { 40 | struct cstl_map* pMap; 41 | void* key; 42 | void* value; 43 | }; 44 | 45 | static void __map_item_destruct(struct cstl_map_item* item); 46 | 47 | static void _item_destruct(void* p) 48 | { 49 | struct cstl_map_item* item = (struct cstl_map_item*)p; 50 | assert(item); 51 | __map_item_destruct(item); 52 | } 53 | 54 | static int _item_compare(const void* lhs, const void* rhs) 55 | { 56 | struct cstl_map* pMap; 57 | struct cstl_map_item* item_lhs = (struct cstl_map_item*)lhs; 58 | struct cstl_map_item* item_rhs = (struct cstl_map_item*)rhs; 59 | assert(item_lhs); 60 | assert(item_rhs); 61 | pMap = item_lhs->pMap; 62 | assert(pMap == item_rhs->pMap); 63 | assert(pMap->fn_c_k); 64 | return pMap->fn_c_k(item_lhs->key, item_rhs->key); 65 | } 66 | 67 | struct cstl_map* cstl_map_new(cstl_compare fn_c_k, cstl_destroy fn_k_d, 68 | cstl_destroy fn_v_d) 69 | { 70 | struct cstl_map* pMap = (struct cstl_map*)calloc(1, sizeof(*pMap)); 71 | if (pMap) { 72 | pMap->map_changed = 0; 73 | pMap->fn_c_k = fn_c_k; 74 | pMap->fn_k_d = fn_k_d; 75 | pMap->fn_v_d = fn_v_d; 76 | pMap->tree = 77 | rbt_tree_create(malloc, free, 0, _item_compare, _item_destruct); 78 | if (pMap->tree == (struct rbt_tree*)NULL) { 79 | free(pMap); 80 | pMap = NULL; 81 | } 82 | } 83 | return pMap; 84 | } 85 | 86 | static void _map_item_value_destroy(struct cstl_map_item* item) 87 | { 88 | struct cstl_map* pMap = item->pMap; 89 | if (pMap->fn_v_d) { 90 | pMap->fn_v_d(item->value); 91 | } 92 | free(item->value); 93 | item->value = NULL; 94 | } 95 | 96 | static void _map_item_set_value(struct cstl_map_item* item, const void* value, 97 | size_t value_size) 98 | { 99 | if (item->value) { 100 | _map_item_value_destroy(item); 101 | } 102 | if (value && value_size) { 103 | item->value = calloc(value_size, sizeof(char)); 104 | assert(item->value); 105 | memcpy(item->value, value, value_size); 106 | } 107 | } 108 | 109 | static void map_item_init(struct cstl_map* pMap, struct cstl_map_item* item, 110 | const void* key, size_t key_size, const void* value, 111 | size_t value_size) 112 | { 113 | assert(pMap); 114 | assert(key && key_size); 115 | item->pMap = pMap; 116 | item->key = calloc(key_size, sizeof(char)); 117 | assert(item->key); 118 | memcpy(item->key, key, key_size); 119 | _map_item_set_value(item, value, value_size); 120 | } 121 | 122 | static void __map_item_destruct(struct cstl_map_item* item) 123 | { 124 | if (item) { 125 | struct cstl_map* pMap = item->pMap; 126 | assert(pMap); 127 | 128 | if (pMap->fn_k_d) { 129 | pMap->fn_k_d(item->key); 130 | } 131 | free(item->key); 132 | item->key = NULL; 133 | 134 | _map_item_value_destroy(item); 135 | } 136 | } 137 | 138 | cstl_error cstl_map_insert(struct cstl_map* pMap, const void* key, 139 | size_t key_size, const void* value, 140 | size_t value_size) 141 | { 142 | cstl_error rc = CSTL_ERROR_SUCCESS; 143 | rbt_status rcrb; 144 | struct cstl_map_item dummy; 145 | if (pMap == (struct cstl_map*)NULL) { 146 | return CSTL_MAP_NOT_INITIALIZED; 147 | } 148 | if (cstl_map_is_key_exists(pMap, key)) { 149 | return CSTL_RBTREE_KEY_DUPLICATE; 150 | } 151 | memset(&dummy, 0, sizeof(dummy)); 152 | map_item_init(pMap, &dummy, key, key_size, value, value_size); 153 | 154 | rcrb = rbt_tree_insert(pMap->tree, &dummy, sizeof(dummy)); 155 | if (rcrb == rbt_status_success) { 156 | pMap->map_changed = 1; 157 | } 158 | else { 159 | assert(0); 160 | } 161 | return rc; 162 | } 163 | 164 | int cstl_map_is_key_exists(struct cstl_map* pMap, const void* key) 165 | { 166 | struct rbt_node* node; 167 | 168 | struct cstl_map_item dummy; 169 | dummy.pMap = pMap; 170 | dummy.key = (void*)key; 171 | 172 | if (pMap == (struct cstl_map*)0) { 173 | return 0; 174 | } 175 | node = rbt_tree_find(pMap->tree, &dummy); 176 | return rbt_node_is_valid(node); 177 | } 178 | 179 | cstl_error cstl_map_replace(struct cstl_map* pMap, const void* key, 180 | const void* value, size_t value_size) 181 | { 182 | struct rbt_node* node; 183 | struct cstl_map_item* data; 184 | 185 | struct cstl_map_item dummy; 186 | dummy.pMap = pMap; 187 | dummy.key = (void*)key; 188 | 189 | if (pMap == (struct cstl_map*)0) { 190 | return CSTL_MAP_NOT_INITIALIZED; 191 | } 192 | node = rbt_tree_find(pMap->tree, &dummy); 193 | if (!rbt_node_is_valid(node)) { 194 | return CSTL_RBTREE_KEY_NOT_FOUND; 195 | } 196 | 197 | data = (struct cstl_map_item*)rbt_node_get_key(node); 198 | _map_item_set_value(data, value, value_size); 199 | return CSTL_ERROR_SUCCESS; 200 | } 201 | 202 | cstl_error cstl_map_remove(struct cstl_map* pMap, const void* key) 203 | { 204 | cstl_error rc = CSTL_ERROR_SUCCESS; 205 | rbt_status rcrb; 206 | 207 | struct cstl_map_item dummy; 208 | dummy.pMap = pMap; 209 | dummy.key = (void*)key; 210 | 211 | if (pMap == (struct cstl_map*)0) { 212 | return CSTL_MAP_NOT_INITIALIZED; 213 | } 214 | rcrb = rbt_tree_remove_node(pMap->tree, &dummy); 215 | if (rbt_status_success == rcrb) { 216 | pMap->map_changed = 1; 217 | } 218 | return rc; 219 | } 220 | 221 | const void* cstl_map_find(struct cstl_map* pMap, const void* key) 222 | { 223 | struct rbt_node* node; 224 | struct cstl_map_item* data; 225 | 226 | struct cstl_map_item dummy; 227 | dummy.pMap = pMap; 228 | dummy.key = (void*)key; 229 | 230 | if (pMap == (struct cstl_map*)0) { 231 | return (void*)0; 232 | } 233 | node = rbt_tree_find(pMap->tree, (void*)&dummy); 234 | if (0 == rbt_node_is_valid(node)) { 235 | return (void*)0; 236 | } 237 | data = (struct cstl_map_item*)rbt_node_get_key(node); 238 | return data->value; 239 | } 240 | 241 | cstl_error cstl_map_delete(struct cstl_map* x) 242 | { 243 | cstl_error rc = CSTL_ERROR_SUCCESS; 244 | if (x != (struct cstl_map*)0) { 245 | rbt_tree_destroy(x->tree); 246 | free(x); 247 | } 248 | return rc; 249 | } 250 | 251 | static struct rbt_node* cstl_map_minimum(struct cstl_map* x) 252 | { 253 | return rbt_tree_minimum(x->tree, rbt_tree_get_root(x->tree)); 254 | } 255 | 256 | static const void* cstl_map_iter_get_next(struct cstl_iterator* pIterator) 257 | { 258 | struct cstl_map* x = (struct cstl_map*)pIterator->pContainer; 259 | struct rbt_node* ptr = NULL; 260 | if (NULL == pIterator->current_element) { 261 | pIterator->current_element = cstl_map_minimum(x); 262 | } 263 | else { 264 | pIterator->current_element = 265 | rbt_tree_successor(x->tree, 266 | (struct rbt_node*)pIterator->current_element); 267 | } 268 | ptr = (struct rbt_node*)pIterator->current_element; 269 | if (ptr == NULL || rbt_node_get_key(ptr) == NULL) { 270 | return NULL; 271 | } 272 | return ptr; 273 | } 274 | 275 | static const void* cstl_map_iter_get_key(struct cstl_iterator* pIterator) 276 | { 277 | struct rbt_node* current = (struct rbt_node*)pIterator->current_element; 278 | struct cstl_map_item* d = (struct cstl_map_item*)rbt_node_get_key(current); 279 | return d->key; 280 | } 281 | 282 | static const void* cstl_map_iter_get_value(struct cstl_iterator* pIterator) 283 | { 284 | struct rbt_node* current = (struct rbt_node*)pIterator->current_element; 285 | struct cstl_map_item* d = (struct cstl_map_item*)rbt_node_get_key(current); 286 | return d->value; 287 | } 288 | 289 | static void cstl_map_iter_replace_value(struct cstl_iterator* pIterator, 290 | void* elem, size_t elem_size) 291 | { 292 | /* struct cstl_map *pMap = (struct cstl_map *)pIterator->pContainer; */ 293 | struct rbt_node* current = (struct rbt_node*)pIterator->current_element; 294 | struct cstl_map_item* d = (struct cstl_map_item*)rbt_node_get_key(current); 295 | _map_item_set_value(d, elem, elem_size); 296 | } 297 | 298 | struct cstl_iterator* cstl_map_new_iterator(struct cstl_map* pMap) 299 | { 300 | struct cstl_iterator* itr = 301 | (struct cstl_iterator*)calloc(1, sizeof(struct cstl_iterator)); 302 | if (itr) { 303 | itr->next = cstl_map_iter_get_next; 304 | itr->current_key = cstl_map_iter_get_key; 305 | itr->current_value = cstl_map_iter_get_value; 306 | itr->replace_current_value = cstl_map_iter_replace_value; 307 | itr->pContainer = pMap; 308 | itr->current_index = 0; 309 | itr->current_element = (void*)0; 310 | pMap->map_changed = 0; 311 | } 312 | return itr; 313 | } 314 | 315 | void cstl_map_delete_iterator(struct cstl_iterator* pItr) 316 | { 317 | free(pItr); 318 | } 319 | 320 | void cstl_map_traverse(struct cstl_map* map, map_iter_callback cb, void* p) 321 | { 322 | struct cstl_iterator* iterator; 323 | const void* element; 324 | int stop = 0; 325 | if (map == NULL || cb == NULL) { 326 | return; 327 | } 328 | iterator = cstl_map_new_iterator(map); 329 | while ((element = iterator->next(iterator))) { 330 | const void* key = iterator->current_key(iterator); 331 | const void* value = iterator->current_value(iterator); 332 | cb(map, key, value, &stop, p); 333 | if (stop != 0) { 334 | break; 335 | } 336 | if (map->map_changed) { 337 | cstl_map_delete_iterator(iterator); 338 | iterator = cstl_map_new_iterator(map); 339 | } 340 | } 341 | cstl_map_delete_iterator(iterator); 342 | } 343 | 344 | void cstl_map_const_traverse(struct cstl_map* map, fn_map_walker fn, void* p) 345 | { 346 | struct cstl_iterator* iterator; 347 | int stop = 0; 348 | const void* element; 349 | if (map == NULL || fn == NULL) { 350 | return; 351 | } 352 | iterator = cstl_map_new_iterator(map); 353 | while ((element = iterator->next(iterator))) { 354 | const void* key = iterator->current_key(iterator); 355 | const void* value = iterator->current_value(iterator); 356 | fn(key, value, &stop, p); 357 | if (stop != 0) { 358 | break; 359 | } 360 | } 361 | cstl_map_delete_iterator(iterator); 362 | } 363 | -------------------------------------------------------------------------------- /test/t_c_array.c: -------------------------------------------------------------------------------- 1 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 2 | * This file is part of cstl library 3 | * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com ) 4 | * Copyright (C) 2018 ssrlive ( ssrlivebox@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ 24 | 25 | #include "c_stl_lib.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static int compare_e(const void* left, const void* right) 34 | { 35 | if (left != right) { 36 | int* l = (int*)left; 37 | int* r = (int*)right; 38 | return (*l - *r); 39 | } 40 | return 0; 41 | } 42 | 43 | static int compare_e_ptr(const void* left, const void* right) 44 | { 45 | if (left != right) { 46 | int* l = *((int**)left); 47 | int* r = *((int**)right); 48 | return (*l - *r); 49 | } 50 | return 0; 51 | } 52 | 53 | static int compare_e_str(const void* left, const void* right) 54 | { 55 | if (left != right) { 56 | char* l = *((char**)left); 57 | char* r = *((char**)right); 58 | return strcmp(l, r); 59 | } 60 | return 0; 61 | } 62 | 63 | static void free_e(void* ptr) 64 | { 65 | if (ptr) { 66 | void* p = *((void**)ptr); 67 | if (p) { 68 | free(p); 69 | } 70 | } 71 | } 72 | 73 | static void print_e(int* ptr) 74 | { 75 | if (ptr) { 76 | printf("%d\n", *(int*)ptr); 77 | } 78 | } 79 | 80 | static void test_with_int() 81 | { 82 | size_t size = 10; 83 | int i = 0; 84 | int* p_rv = (int*)0; 85 | int rv = 0; 86 | struct cstl_array* myArray = cstl_array_new(8, compare_e, NULL); 87 | assert(0 != cstl_array_is_empty(myArray)); 88 | 89 | for (i = 0; i < (int)size; i++) { 90 | cstl_array_push_back(myArray, &i, sizeof(int)); 91 | } 92 | assert(0 == cstl_array_is_empty(myArray)); 93 | assert(size == cstl_array_size(myArray)); 94 | for (i = 0; i < (int)size; i++) { 95 | p_rv = (int*)cstl_array_element_at(myArray, i); 96 | rv = *(int*)p_rv; 97 | assert(rv == i); 98 | } 99 | p_rv = (int*)cstl_array_front(myArray); 100 | rv = *(int*)p_rv; 101 | assert(rv == 0); 102 | 103 | p_rv = (int*)cstl_array_back(myArray); 104 | rv = *(int*)p_rv; 105 | assert(rv == (int)(size - 1)); 106 | 107 | cstl_array_remove_from(myArray, 0); 108 | assert(size - 1 == cstl_array_size(myArray)); 109 | p_rv = (int*)cstl_array_element_at(myArray, 0); 110 | rv = *(int*)p_rv; 111 | assert(rv == 1); 112 | 113 | size = cstl_array_size(myArray); 114 | cstl_array_remove_from(myArray, size / 2); 115 | assert(size - 1 == cstl_array_size(myArray)); 116 | p_rv = (int*)cstl_array_element_at(myArray, size / 2); 117 | rv = *(int*)p_rv; 118 | assert((size_t)rv == size / 2 + 2); 119 | 120 | size = cstl_array_size(myArray); 121 | cstl_array_remove_from(myArray, size - 1); 122 | assert(size - 1 == cstl_array_size(myArray)); 123 | size = cstl_array_size(myArray); 124 | p_rv = (int*)cstl_array_element_at(myArray, size - 1); 125 | rv = *(int*)p_rv; 126 | assert(rv == 8); 127 | 128 | i = 900; 129 | cstl_array_insert_at(myArray, 5, &i, sizeof(int)); 130 | p_rv = (int*)cstl_array_element_at(myArray, 5); 131 | rv = *(int*)p_rv; 132 | assert(rv == i); 133 | 134 | p_rv = (int*)cstl_array_element_at(myArray, 6); 135 | rv = *(int*)p_rv; 136 | assert(rv == 7); 137 | 138 | for (i = 0; i < (int)cstl_array_size(myArray); i++) { 139 | p_rv = (int*)cstl_array_element_at(myArray, (size_t)i); 140 | print_e(p_rv); 141 | } 142 | 143 | cstl_array_delete(myArray); 144 | (void)rv; 145 | } 146 | 147 | static void test_with_int2() 148 | { 149 | struct cstl_array* myArray = cstl_array_new(8, compare_e, NULL); 150 | int i; 151 | size_t size; 152 | srand((unsigned int)time(NULL)); 153 | for (i = 0; i < 30; i++) { 154 | int x = rand() % 10000; 155 | cstl_array_push_back(myArray, &x, sizeof(int)); 156 | } 157 | size = cstl_array_size(myArray); 158 | 159 | cstl_array_quick_sort(myArray); 160 | 161 | printf("--------------- test_with_int2 ---------------\n"); 162 | for (i = 0; i < (int)size; i++) { 163 | int* p_rv = (int*)cstl_array_element_at(myArray, (size_t)i); 164 | print_e(p_rv); 165 | } 166 | cstl_array_delete(myArray); 167 | } 168 | 169 | static void test_with_pointers() 170 | { 171 | size_t size = 10; 172 | int i = 0; 173 | int* rv; 174 | int** p_rv = (int**)0; 175 | struct cstl_array* myArray = cstl_array_new(8, compare_e_ptr, free_e); 176 | assert(0 != cstl_array_is_empty(myArray)); 177 | 178 | for (i = 0; i < (int)size; i++) { 179 | int* v = (int*)calloc(1, sizeof(int)); 180 | *v = i; 181 | cstl_array_push_back(myArray, &v, sizeof(int*)); 182 | } 183 | assert(0 == cstl_array_is_empty(myArray)); 184 | assert(size == cstl_array_size(myArray)); 185 | for (i = 0; i < (int)size; i++) { 186 | p_rv = (int**)cstl_array_element_at(myArray, i); 187 | rv = *((int**)p_rv); 188 | assert(*rv == i); 189 | } 190 | p_rv = (int**)cstl_array_front(myArray); 191 | rv = *((int**)p_rv); 192 | assert(*rv == 0); 193 | 194 | p_rv = (int**)cstl_array_back(myArray); 195 | rv = *((int**)p_rv); 196 | assert(*rv == (int)size - 1); 197 | 198 | cstl_array_remove_from(myArray, 0); 199 | assert(size - 1 == cstl_array_size(myArray)); 200 | 201 | p_rv = (int**)cstl_array_element_at(myArray, 0); 202 | rv = *((int**)p_rv); 203 | assert(*rv == 1); 204 | 205 | size = cstl_array_size(myArray); 206 | cstl_array_remove_from(myArray, size / 2); 207 | assert(size - 1 == cstl_array_size(myArray)); 208 | p_rv = (int**)cstl_array_element_at(myArray, size / 2); 209 | rv = *((int**)p_rv); 210 | assert((size_t)*rv == size / 2 + 2); 211 | 212 | size = cstl_array_size(myArray); 213 | cstl_array_remove_from(myArray, size - 1); 214 | assert(size - 1 == cstl_array_size(myArray)); 215 | 216 | size = cstl_array_size(myArray); 217 | 218 | p_rv = (int**)cstl_array_element_at(myArray, size - 1); 219 | rv = *((int**)p_rv); 220 | assert(*rv == 8); 221 | 222 | cstl_array_delete(myArray); 223 | (void)rv; 224 | } 225 | 226 | static void print_string_with_iterators(struct cstl_array* myArray) 227 | { 228 | struct cstl_iterator* myItr; 229 | const void* pElement; 230 | printf("--------------- print_string_with_iterators ---------------\n"); 231 | myItr = cstl_array_new_iterator(myArray); 232 | while ((pElement = myItr->next(myItr)) != NULL) { 233 | char** value = (char**)myItr->current_value(myItr); 234 | printf("%s\n", *value); 235 | } 236 | cstl_array_delete_iterator(myItr); 237 | } 238 | 239 | static void test_with_strings() 240 | { 241 | size_t size = 10; 242 | char* input_array[11]; 243 | int i = 0; 244 | char* rv; 245 | char** p_rv = (char**)0; 246 | struct cstl_array* myArray = cstl_array_new(8, compare_e_str, free_e); 247 | assert(0 != cstl_array_is_empty(myArray)); 248 | 249 | input_array[0] = "STRING_050"; 250 | input_array[1] = "STRING_030"; 251 | input_array[2] = "STRING_040"; 252 | input_array[3] = "STRING_090"; 253 | input_array[4] = "STRING_100"; 254 | input_array[5] = "STRING_010"; 255 | input_array[6] = "STRING_005"; 256 | input_array[7] = "STRING_400"; 257 | input_array[8] = "STRING_123"; 258 | input_array[9] = "STRING_080"; 259 | input_array[10] = "STRING_10"; 260 | 261 | for (i = 0; i < (int)size; i++) { 262 | char* v = strdup(input_array[i]); 263 | cstl_array_push_back(myArray, &v, sizeof(char*)); 264 | } 265 | assert(0 == cstl_array_is_empty(myArray)); 266 | assert(size == cstl_array_size(myArray)); 267 | for (i = 0; i < (int)size; i++) { 268 | p_rv = (char**)cstl_array_element_at(myArray, i); 269 | rv = *((char**)p_rv); 270 | assert(strcmp(rv, input_array[i]) == 0); 271 | } 272 | p_rv = (char**)cstl_array_front(myArray); 273 | rv = *((char**)p_rv); 274 | assert(strcmp(rv, input_array[0]) == 0); 275 | 276 | p_rv = (char**)cstl_array_back(myArray); 277 | rv = *((char**)p_rv); 278 | assert(strcmp(rv, input_array[size - 1]) == 0); 279 | 280 | cstl_array_remove_from(myArray, 0); 281 | assert(size - 1 == cstl_array_size(myArray)); 282 | 283 | p_rv = (char**)cstl_array_element_at(myArray, 0); 284 | rv = *((char**)p_rv); 285 | assert(strcmp(rv, input_array[1]) == 0); 286 | 287 | size = cstl_array_size(myArray); 288 | cstl_array_remove_from(myArray, size / 2); 289 | 290 | p_rv = (char**)cstl_array_element_at(myArray, size / 2); 291 | rv = *((char**)p_rv); 292 | assert(strcmp(rv, input_array[size / 2 + 2]) == 0); 293 | 294 | size = cstl_array_size(myArray); 295 | cstl_array_remove_from(myArray, size - 1); 296 | assert(size - 1 == cstl_array_size(myArray)); 297 | size = cstl_array_size(myArray); 298 | 299 | p_rv = (char**)cstl_array_element_at(myArray, size - 1); 300 | rv = *((char**)p_rv); 301 | assert(strcmp(rv, input_array[8]) == 0); 302 | 303 | size = cstl_array_size(myArray); 304 | cstl_array_quick_sort(myArray); 305 | print_string_with_iterators(myArray); 306 | 307 | cstl_array_delete(myArray); 308 | (void)rv; 309 | } 310 | 311 | static void print_using_iterators(struct cstl_array* myArray) 312 | { 313 | struct cstl_iterator* myItr; 314 | const void* pElement; 315 | printf("------------------------------------------------\n"); 316 | myItr = cstl_array_new_iterator(myArray); 317 | while ((pElement = myItr->next(myItr)) != NULL) { 318 | int* value = (int*)myItr->current_value(myItr); 319 | printf("%d\n", *value); 320 | } 321 | cstl_array_delete_iterator(myItr); 322 | } 323 | 324 | static void replace_values_using_iterators(struct cstl_array* myArray) 325 | { 326 | struct cstl_iterator* myItr; 327 | const void* pElement; 328 | printf("------------------------------------------------\n"); 329 | myItr = cstl_array_new_iterator(myArray); 330 | while ((pElement = myItr->next(myItr)) != NULL) { 331 | int* old_value = (int*)myItr->current_value(myItr); 332 | int new_value = *old_value; 333 | new_value = new_value * 2; 334 | myItr->replace_current_value(myItr, &new_value, sizeof(new_value)); 335 | } 336 | cstl_array_delete_iterator(myItr); 337 | } 338 | 339 | static struct cstl_array* create_array() 340 | { 341 | int size = 10; 342 | int i = 0; 343 | int* p_rv = (int*)0; 344 | int rv = 0; 345 | 346 | struct cstl_array* myArray = cstl_array_new(8, compare_e, NULL); 347 | assert(0 != cstl_array_is_empty(myArray)); 348 | 349 | for (i = 0; i < size; i++) { 350 | cstl_array_push_back(myArray, &i, sizeof(int)); 351 | } 352 | assert(0 == cstl_array_is_empty(myArray)); 353 | assert((size_t)size == cstl_array_size(myArray)); 354 | for (i = 0; i < size; i++) { 355 | p_rv = (int*)cstl_array_element_at(myArray, i); 356 | rv = *(int*)p_rv; 357 | assert(rv == i); 358 | } 359 | (void)rv; 360 | return myArray; 361 | } 362 | 363 | void test_with_iterator_function() 364 | { 365 | struct cstl_array* myArray = create_array(); 366 | print_using_iterators(myArray); 367 | replace_values_using_iterators(myArray); 368 | print_using_iterators(myArray); 369 | cstl_array_delete(myArray); 370 | } 371 | 372 | void test_c_array() 373 | { 374 | test_with_int(); 375 | test_with_int2(); 376 | test_with_pointers(); 377 | test_with_strings(); 378 | test_with_iterator_function(); 379 | } 380 | -------------------------------------------------------------------------------- /msvc/test-cstl.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {2C18D160-302B-3D88-BD12-F0714E0C1263} 23 | Win32Proj 24 | Win32 25 | test-cstl 26 | 27 | 28 | 29 | Application 30 | MultiByte 31 | 32 | 33 | Application 34 | MultiByte 35 | 36 | 37 | Application 38 | MultiByte 39 | 40 | 41 | Application 42 | MultiByte 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | <_ProjectFileVersion>10.0.20506.1 53 | true 54 | true 55 | true 56 | true 57 | false 58 | false 59 | true 60 | true 61 | 62 | 63 | 64 | ..\inc;%(AdditionalIncludeDirectories) 65 | EnableFastChecks 66 | ProgramDatabase 67 | 68 | 69 | Disabled 70 | Disabled 71 | NotUsing 72 | MultiThreadedDebugDLL 73 | Level3 74 | %(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug" 75 | 4996;%(DisableSpecificWarnings) 76 | 77 | 78 | %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\" 79 | ..\inc;%(AdditionalIncludeDirectories) 80 | 81 | 82 | ..\inc;%(AdditionalIncludeDirectories) 83 | $(ProjectDir)/$(IntDir) 84 | %(Filename).h 85 | %(Filename).tlb 86 | %(Filename)_i.c 87 | %(Filename)_p.c 88 | 89 | 90 | cstl.lib;%(AdditionalDependencies) 91 | $(OutDir);%(AdditionalLibraryDirectories) 92 | true 93 | %(IgnoreSpecificDefaultLibraries) 94 | Console 95 | 96 | 97 | false 98 | 99 | 100 | 101 | 102 | ..\inc;%(AdditionalIncludeDirectories) 103 | EnableFastChecks 104 | ProgramDatabase 105 | 106 | 107 | Disabled 108 | Disabled 109 | NotUsing 110 | MultiThreadedDebugDLL 111 | Level3 112 | %(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug" 113 | 4996;%(DisableSpecificWarnings) 114 | 115 | 116 | %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\" 117 | ..\inc;%(AdditionalIncludeDirectories) 118 | 119 | 120 | ..\inc;%(AdditionalIncludeDirectories) 121 | $(ProjectDir)/$(IntDir) 122 | %(Filename).h 123 | %(Filename).tlb 124 | %(Filename)_i.c 125 | %(Filename)_p.c 126 | 127 | 128 | cstl.lib;%(AdditionalDependencies) 129 | $(OutDir);%(AdditionalLibraryDirectories) 130 | true 131 | %(IgnoreSpecificDefaultLibraries) 132 | Console 133 | 134 | 135 | false 136 | 137 | 138 | 139 | 140 | ..\inc;%(AdditionalIncludeDirectories) 141 | 142 | 143 | AnySuitable 144 | MaxSpeed 145 | NotUsing 146 | MultiThreadedDLL 147 | Level3 148 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release" 149 | 150 | 151 | 4996;%(DisableSpecificWarnings) 152 | 153 | 154 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\" 155 | ..\inc;%(AdditionalIncludeDirectories) 156 | 157 | 158 | ..\inc;%(AdditionalIncludeDirectories) 159 | $(ProjectDir)/$(IntDir) 160 | %(Filename).h 161 | %(Filename).tlb 162 | %(Filename)_i.c 163 | %(Filename)_p.c 164 | 165 | 166 | cstl.lib;%(AdditionalDependencies) 167 | $(OutDir);%(AdditionalLibraryDirectories) 168 | false 169 | %(IgnoreSpecificDefaultLibraries) 170 | Console 171 | 172 | 173 | false 174 | 175 | 176 | 177 | 178 | ..\inc;%(AdditionalIncludeDirectories) 179 | 180 | 181 | AnySuitable 182 | MaxSpeed 183 | NotUsing 184 | MultiThreadedDLL 185 | Level3 186 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release" 187 | 188 | 189 | 4996;%(DisableSpecificWarnings) 190 | 191 | 192 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\" 193 | ..\inc;%(AdditionalIncludeDirectories) 194 | 195 | 196 | ..\inc;%(AdditionalIncludeDirectories) 197 | $(ProjectDir)/$(IntDir) 198 | %(Filename).h 199 | %(Filename).tlb 200 | %(Filename)_i.c 201 | %(Filename)_p.c 202 | 203 | 204 | cstl.lib;%(AdditionalDependencies) 205 | $(OutDir);%(AdditionalLibraryDirectories) 206 | false 207 | %(IgnoreSpecificDefaultLibraries) 208 | Console 209 | 210 | 211 | false 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | {475DE074-DA8E-3E95-929A-5D73E659170A} 227 | cstl 228 | 229 | 230 | 231 | 232 | 233 | -------------------------------------------------------------------------------- /src/rb-tree.c: -------------------------------------------------------------------------------- 1 | #include "rb-tree.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct rbt_tree; 10 | 11 | struct rbt_node { 12 | struct rbt_node* left; 13 | struct rbt_node* right; 14 | struct rbt_node* parent; 15 | rbt_color color; 16 | void* key; 17 | struct rbt_tree* tree; 18 | }; 19 | 20 | struct rbt_tree { 21 | struct rbt_node* root; 22 | struct rbt_node* nil; 23 | struct rbt_node sentinel; 24 | int allow_dup; 25 | rbt_node_destruct node_destruct; 26 | rbt_node_compare node_compare; 27 | rbt_mem_allocate allocator; 28 | rbt_mem_release releaser; 29 | }; 30 | 31 | static void debug_verify_properties(struct rbt_tree*); 32 | static void debug_verify_property_1(struct rbt_tree*, struct rbt_node*); 33 | static void debug_verify_property_2(struct rbt_tree*, struct rbt_node*); 34 | static int debug_node_color(struct rbt_tree*, struct rbt_node* n); 35 | static void debug_verify_property_4(struct rbt_tree*, struct rbt_node*); 36 | static void debug_verify_property_5(struct rbt_tree*, struct rbt_node*); 37 | static void debug_verify_property_5_helper(struct rbt_tree*, struct rbt_node*, 38 | int, int*); 39 | 40 | int rbt_node_is_valid(const struct rbt_node* node) 41 | { 42 | assert(node); 43 | assert(node->tree); 44 | return node && node != node->tree->nil; 45 | } 46 | 47 | rbt_color rbt_node_get_color(const struct rbt_node* node) 48 | { 49 | assert(node); 50 | return node->color; 51 | } 52 | 53 | struct rbt_node* rbt_node_get_left(const struct rbt_node* node) 54 | { 55 | assert(node); 56 | return node->left; 57 | } 58 | 59 | struct rbt_node* rbt_node_get_right(const struct rbt_node* node) 60 | { 61 | assert(node); 62 | return node->right; 63 | } 64 | 65 | struct rbt_node* rbt_node_get_parent(const struct rbt_node* node) 66 | { 67 | assert(node); 68 | return node->parent; 69 | } 70 | 71 | const void* rbt_node_get_key(const struct rbt_node* node) 72 | { 73 | struct rbt_tree* tree; 74 | assert(node); 75 | tree = node->tree; 76 | assert(tree); 77 | return (node != tree->nil) ? node->key : (void*)0; 78 | } 79 | 80 | static void _do_node_destruct(struct rbt_node* node) 81 | { 82 | struct rbt_tree* tree; 83 | assert(node); 84 | tree = node->tree; 85 | assert(tree); 86 | if (node != tree->nil) { 87 | if (tree->node_destruct) { 88 | tree->node_destruct(node->key); 89 | } 90 | } 91 | else { 92 | assert(0); 93 | } 94 | } 95 | 96 | static void __left_rotate(struct rbt_tree* T, struct rbt_node* x) 97 | { 98 | struct rbt_node* y = x->right; 99 | x->right = y->left; 100 | if (y->left != T->nil) { 101 | y->left->parent = x; 102 | } 103 | y->parent = x->parent; 104 | if (x->parent == T->nil) { 105 | T->root = y; 106 | } 107 | else if (x == x->parent->left) { 108 | x->parent->left = y; 109 | } 110 | else { 111 | x->parent->right = y; 112 | } 113 | y->left = x; 114 | x->parent = y; 115 | } 116 | 117 | static void __right_rotate(struct rbt_tree* T, struct rbt_node* x) 118 | { 119 | struct rbt_node* y = x->left; 120 | x->left = y->right; 121 | if (y->right != T->nil) { 122 | y->right->parent = x; 123 | } 124 | y->parent = x->parent; 125 | if (x->parent == T->nil) { 126 | T->root = y; 127 | } 128 | else if (x == x->parent->right) { 129 | x->parent->right = y; 130 | } 131 | else { 132 | x->parent->left = y; 133 | } 134 | y->right = x; 135 | x->parent = y; 136 | } 137 | 138 | #define rb_sentinel(tree) &(tree)->sentinel 139 | 140 | struct rbt_tree* rbt_tree_create(rbt_mem_allocate allocator, 141 | rbt_mem_release releaser, int allow_dup, 142 | rbt_node_compare cmp, rbt_node_destruct dest) 143 | { 144 | struct rbt_tree* tree; 145 | assert(allocator); 146 | assert(releaser); 147 | tree = (struct rbt_tree*)allocator(sizeof(*tree)); 148 | if (tree != (struct rbt_tree*)0) { 149 | tree->allocator = allocator; 150 | tree->releaser = releaser; 151 | tree->node_compare = cmp; 152 | tree->node_destruct = dest; 153 | tree->nil = rb_sentinel(tree); 154 | tree->root = tree->nil; 155 | tree->sentinel.left = tree->nil; 156 | tree->sentinel.right = tree->nil; 157 | tree->sentinel.parent = tree->nil; 158 | tree->sentinel.tree = tree; 159 | tree->sentinel.color = rbt_black; 160 | tree->allow_dup = allow_dup; 161 | 162 | /* make code checker happy */ 163 | debug_verify_properties(tree); 164 | } 165 | 166 | return tree; 167 | } 168 | 169 | struct rbt_node* rbt_tree_get_root(struct rbt_tree* tree) 170 | { 171 | assert(tree); 172 | return tree->root; 173 | } 174 | 175 | static void __rb_insert_fixup(struct rbt_tree* T, struct rbt_node* z) 176 | { 177 | while (z->parent->color == rbt_red) { 178 | if (z->parent == z->parent->parent->left) { 179 | struct rbt_node* y = z->parent->parent->right; 180 | if (y->color == rbt_red) { 181 | z->parent->color = rbt_black; 182 | y->color = rbt_black; 183 | z->parent->parent->color = rbt_red; 184 | z = z->parent->parent; 185 | } 186 | else { 187 | if (z == z->parent->right) { 188 | z = z->parent; 189 | __left_rotate(T, z); 190 | } 191 | z->parent->color = rbt_black; 192 | z->parent->parent->color = rbt_red; 193 | __right_rotate(T, z->parent->parent); 194 | } 195 | } 196 | else { 197 | struct rbt_node* y = z->parent->parent->left; 198 | if (y->color == rbt_red) { 199 | z->parent->color = rbt_black; 200 | y->color = rbt_black; 201 | z->parent->parent->color = rbt_red; 202 | z = z->parent->parent; 203 | } 204 | else { 205 | if (z == z->parent->left) { 206 | z = z->parent; 207 | __right_rotate(T, z); 208 | } 209 | z->parent->color = rbt_black; 210 | z->parent->parent->color = rbt_red; 211 | __left_rotate(T, z->parent->parent); 212 | } 213 | } 214 | } 215 | T->root->color = rbt_black; 216 | } 217 | 218 | #if 1 219 | 220 | struct rbt_node* rbt_tree_find(struct rbt_tree* tree, const void* key) 221 | { 222 | struct rbt_node* x; 223 | int c = 0; 224 | assert(tree); 225 | assert(key); 226 | x = tree->root; 227 | while ((x != tree->nil) && (c = tree->node_compare(key, x->key)) != 0) { 228 | x = (c < 0) ? x->left : x->right; 229 | } 230 | return x; 231 | } 232 | 233 | #else 234 | 235 | static struct rbt_node* __tree_search(struct rbt_node* x, const void* k) 236 | { 237 | struct rbt_tree* tree; 238 | int cmp; 239 | assert(x); 240 | assert(k); 241 | tree = x->tree; 242 | assert(tree->node_compare); 243 | if (x == tree->nil || (cmp = tree->node_compare(k, x->key)) == 0) { 244 | return x; 245 | } 246 | if (cmp < 0) { 247 | return __tree_search(x->left, k); 248 | } 249 | else { 250 | return __tree_search(x->right, k); 251 | } 252 | } 253 | 254 | struct rbt_node* rbt_tree_find(struct rbt_tree* tree, const void* key) 255 | { 256 | assert(tree); 257 | assert(key); 258 | return __tree_search(tree->root, key); 259 | } 260 | 261 | #endif 262 | 263 | static struct rbt_node* _create_node(struct rbt_tree* tree, void* key, size_t s) 264 | { 265 | struct rbt_node* node = (struct rbt_node*)tree->allocator(sizeof(*node)); 266 | if (node) { 267 | node->left = tree->nil; 268 | node->right = tree->nil; 269 | node->color = rbt_red; 270 | node->parent = tree->nil; 271 | node->tree = tree; 272 | 273 | assert(key && s); 274 | node->key = tree->allocator(s * sizeof(char)); 275 | if (node->key == NULL) { 276 | tree->releaser(node); 277 | node = NULL; 278 | } 279 | else { 280 | memcpy(node->key, key, s); 281 | } 282 | } 283 | assert(node); 284 | return node; 285 | } 286 | 287 | static void _node_destroy(struct rbt_node* node) 288 | { 289 | assert(node); 290 | if (node) { 291 | struct rbt_tree* tree = node->tree; 292 | _do_node_destruct(node); 293 | tree->releaser(node->key); 294 | node->key = NULL; 295 | tree->releaser(node); 296 | } 297 | } 298 | 299 | static int _rb_node_compare(struct rbt_node* lhs, struct rbt_node* rhs) 300 | { 301 | struct rbt_tree* tree = lhs->tree; 302 | assert(tree == rhs->tree); 303 | return tree->node_compare(lhs->key, rhs->key); 304 | } 305 | 306 | static void __rb_insert(struct rbt_tree* T, struct rbt_node* z) 307 | { 308 | struct rbt_node* y = T->nil; 309 | struct rbt_node* x = T->root; 310 | while (x != T->nil) { 311 | y = x; 312 | if (_rb_node_compare(z, x) < 0) { 313 | x = x->left; 314 | } 315 | else { 316 | x = x->right; 317 | } 318 | } 319 | z->parent = y; 320 | if (y == T->nil) { 321 | T->root = z; 322 | } 323 | else if (_rb_node_compare(z, y) < 0) { 324 | y->left = z; 325 | } 326 | else { 327 | y->right = z; 328 | } 329 | z->left = T->nil; 330 | z->right = T->nil; 331 | z->color = rbt_red; 332 | __rb_insert_fixup(T, z); 333 | } 334 | 335 | rbt_status rbt_tree_insert(struct rbt_tree* tree, void* key, size_t size) 336 | { 337 | struct rbt_node* x; 338 | if (tree->allow_dup == 0) { 339 | if (rbt_tree_find(tree, key) != tree->nil) { 340 | return rbt_status_key_duplicate; 341 | } 342 | } 343 | x = _create_node(tree, key, size); 344 | if (x == (struct rbt_node*)NULL) { 345 | return rbt_status_memory_out; 346 | } 347 | __rb_insert(tree, x); 348 | 349 | #ifndef NDEBUG 350 | debug_verify_properties(tree); 351 | #endif 352 | return rbt_status_success; 353 | } 354 | 355 | static void __rb_delete_fixup(struct rbt_tree* T, struct rbt_node* x) 356 | { 357 | while (x != T->root && x->color == rbt_black) { 358 | if (x == x->parent->left) { 359 | struct rbt_node* w = x->parent->right; 360 | if (w->color == rbt_red) { 361 | w->color = rbt_black; 362 | x->parent->color = rbt_red; 363 | __left_rotate(T, x->parent); 364 | w = x->parent->right; 365 | } 366 | if (w->left->color == rbt_black && w->right->color == rbt_black) { 367 | w->color = rbt_red; 368 | x = x->parent; 369 | } 370 | else { 371 | if (w->right->color == rbt_black) { 372 | w->left->color = rbt_black; 373 | w->color = rbt_red; 374 | __right_rotate(T, w); 375 | w = x->parent->right; 376 | } 377 | w->color = x->parent->color; 378 | x->parent->color = rbt_black; 379 | w->right->color = rbt_black; 380 | __left_rotate(T, x->parent); 381 | x = T->root; 382 | } 383 | } 384 | else { 385 | struct rbt_node* w = x->parent->left; 386 | if (w->color == rbt_red) { 387 | w->color = rbt_black; 388 | x->parent->color = rbt_red; 389 | __right_rotate(T, x->parent); 390 | w = x->parent->left; 391 | } 392 | if (w->right->color == rbt_black && w->left->color == rbt_black) { 393 | w->color = rbt_red; 394 | x = x->parent; 395 | } 396 | else { 397 | if (w->left->color == rbt_black) { 398 | w->right->color = rbt_black; 399 | w->color = rbt_red; 400 | __left_rotate(T, w); 401 | w = x->parent->left; 402 | } 403 | w->color = x->parent->color; 404 | x->parent->color = rbt_black; 405 | w->left->color = rbt_black; 406 | __right_rotate(T, x->parent); 407 | x = T->root; 408 | } 409 | } 410 | } 411 | x->color = rbt_black; 412 | } 413 | 414 | static void __rb_transplant(struct rbt_tree* T, struct rbt_node* u, 415 | struct rbt_node* v) 416 | { 417 | if (u->parent == T->nil) { 418 | T->root = v; 419 | } 420 | else if (u == u->parent->left) { 421 | u->parent->left = v; 422 | } 423 | else { 424 | u->parent->right = v; 425 | } 426 | v->parent = u->parent; 427 | } 428 | 429 | struct rbt_node* __tree_minimum(struct rbt_node* x) 430 | { 431 | struct rbt_tree* T; 432 | assert(x); 433 | T = x->tree; 434 | assert(T); 435 | while (x->left != T->nil) { 436 | x = x->left; 437 | } 438 | return x; 439 | } 440 | 441 | static void __rb_delete(struct rbt_tree* T, struct rbt_node* z) 442 | { 443 | struct rbt_node *x, *y = z; 444 | rbt_color y_original_color = y->color; 445 | if (z->left == T->nil) { 446 | x = z->right; 447 | __rb_transplant(T, z, z->right); 448 | } 449 | else if (z->right == T->nil) { 450 | x = z->left; 451 | __rb_transplant(T, z, z->left); 452 | } 453 | else { 454 | y = __tree_minimum(z->right); 455 | y_original_color = y->color; 456 | x = y->right; 457 | if (y->parent == z) { 458 | x->parent = y; 459 | } 460 | else { 461 | __rb_transplant(T, y, y->right); 462 | y->right = z->right; 463 | y->right->parent = y; 464 | } 465 | __rb_transplant(T, z, y); 466 | y->left = z->left; 467 | y->left->parent = y; 468 | y->color = z->color; 469 | } 470 | if (y_original_color == rbt_black) { 471 | __rb_delete_fixup(T, x); 472 | } 473 | } 474 | 475 | rbt_status rbt_tree_remove_node(struct rbt_tree* tree, const void* key) 476 | { 477 | struct rbt_node* z = rbt_tree_find(tree, key); 478 | if (z == tree->nil) { 479 | return rbt_status_key_not_exist; 480 | } 481 | __rb_delete(tree, z); 482 | _node_destroy(z); 483 | 484 | #ifndef NDEBUG 485 | debug_verify_properties(tree); 486 | #endif 487 | return rbt_status_success; 488 | } 489 | 490 | #if 1 491 | 492 | rbt_status rbt_tree_destroy(struct rbt_tree* tree) 493 | { 494 | rbt_status rc = rbt_status_success; 495 | struct rbt_node* z = tree->root; 496 | 497 | while (z != tree->nil) { 498 | if (z->left != tree->nil) { 499 | z = z->left; 500 | } 501 | else if (z->right != tree->nil) { 502 | z = z->right; 503 | } 504 | else { 505 | if (z->parent != tree->nil) { 506 | z = z->parent; 507 | if (z->left != tree->nil) { 508 | _node_destroy(z->left); 509 | z->left = tree->nil; 510 | } 511 | else if (z->right != tree->nil) { 512 | _node_destroy(z->right); 513 | z->right = tree->nil; 514 | } 515 | } 516 | else { 517 | _node_destroy(z); 518 | z = tree->nil; 519 | } 520 | } 521 | } 522 | tree->releaser(tree); 523 | return rc; 524 | } 525 | 526 | #else 527 | 528 | void _rbt_node_destroy_recurse(struct rbt_node* node) 529 | { 530 | struct rbt_tree* tree = node->tree; 531 | if (node != tree->nil) { 532 | if (node->left != tree->nil) { 533 | _rbt_node_destroy_recurse(node->left); 534 | } 535 | if (node->right != tree->nil) { 536 | _rbt_node_destroy_recurse(node->right); 537 | } 538 | _node_destroy(node); 539 | } 540 | } 541 | 542 | rbt_status rbt_tree_destroy(struct rbt_tree* tree) 543 | { 544 | if (tree) { 545 | _rbt_node_destroy_recurse(tree->root); 546 | tree->releaser(tree); 547 | } 548 | return rbt_status_success; 549 | } 550 | 551 | #endif 552 | 553 | struct rbt_node* rbt_tree_minimum(struct rbt_tree* tree, struct rbt_node* x) 554 | { 555 | (void)tree; 556 | return __tree_minimum(x); 557 | } 558 | 559 | struct rbt_node* __tree_maximum(struct rbt_node* x) 560 | { 561 | struct rbt_tree* tree; 562 | assert(x); 563 | tree = x->tree; 564 | assert(tree); 565 | if (x == NULL || x == tree->nil) { 566 | return x; 567 | } 568 | while (x->right != tree->nil) { 569 | x = x->right; 570 | } 571 | return x; 572 | } 573 | 574 | struct rbt_node* rbt_tree_maximum(struct rbt_tree* tree, struct rbt_node* x) 575 | { 576 | (void)tree; 577 | return __tree_maximum(x); 578 | } 579 | 580 | int rbt_tree_is_empty(struct rbt_tree* tree) 581 | { 582 | assert(tree); 583 | return (tree->root == tree->nil) ? 1 : 0; 584 | } 585 | 586 | struct rbt_node* rbt_tree_successor(struct rbt_tree* tree, struct rbt_node* x) 587 | { 588 | struct rbt_node* y; 589 | assert(tree); 590 | assert(x); 591 | y = tree->nil; 592 | if (x->right != tree->nil) { 593 | return __tree_minimum(x->right); 594 | } 595 | if (x == __tree_maximum(tree->root)) { 596 | return tree->nil; 597 | } 598 | y = x->parent; 599 | while ((y != tree->nil) && (x == y->right)) { 600 | x = y; 601 | y = y->parent; 602 | } 603 | return y; 604 | } 605 | 606 | static void _inorder_tree_walk(struct rbt_node* x, rbt_node_walk_cb cb, void* p) 607 | { 608 | struct rbt_tree* tree; 609 | assert(x); 610 | tree = x->tree; 611 | assert(tree); 612 | if (x != tree->nil) { 613 | _inorder_tree_walk(x->left, cb, p); 614 | if (cb) { 615 | cb(x, p); 616 | } 617 | _inorder_tree_walk(x->right, cb, p); 618 | } 619 | } 620 | 621 | void rbt_inorder_walk(struct rbt_tree* tree, rbt_node_walk_cb cb, void* p) 622 | { 623 | assert(tree); 624 | assert(cb); 625 | _inorder_tree_walk(tree->root, cb, p); 626 | } 627 | 628 | /* 629 | struct rbt_node * 630 | cstl_rb_get_next(struct rbt_tree* tree, struct rbt_node**current, struct rbt_node**pre) { 631 | struct rbt_node* prev_current; 632 | assert(tree); 633 | assert(current); 634 | assert(pre); 635 | while ((*current) != tree->nil) { 636 | if ((*current)->left == tree->nil) { 637 | prev_current = (*current); 638 | (*current) = (*current)->right; 639 | return prev_current; 640 | } else { 641 | (*pre) = (*current)->left; 642 | while (((*pre)->right != tree->nil) && (*pre)->right != (*current)) 643 | (*pre) = (*pre)->right; 644 | if ((*pre)->right != tree->nil) { 645 | (*pre)->right = (*current); 646 | (*current) = (*current)->left; 647 | } else { 648 | (*pre)->right = tree->nil; 649 | prev_current = (*current); 650 | (*current) = (*current)->right; 651 | return prev_current; 652 | } 653 | } 654 | } 655 | return tree->nil; 656 | } */ 657 | 658 | void debug_verify_properties(struct rbt_tree* t) 659 | { 660 | debug_verify_property_1(t, t->root); 661 | debug_verify_property_2(t, t->root); 662 | debug_verify_property_4(t, t->root); 663 | debug_verify_property_5(t, t->root); 664 | } 665 | 666 | void debug_verify_property_1(struct rbt_tree* tree, struct rbt_node* n) 667 | { 668 | if (n == tree->nil) { 669 | return; 670 | } 671 | assert(debug_node_color(tree, n) == rbt_red || 672 | debug_node_color(tree, n) == rbt_black); 673 | debug_verify_property_1(tree, n->left); 674 | debug_verify_property_1(tree, n->right); 675 | } 676 | 677 | void debug_verify_property_2(struct rbt_tree* tree, struct rbt_node* root) 678 | { 679 | (void)tree; 680 | (void)root; 681 | assert(debug_node_color(tree, root) == rbt_black); 682 | } 683 | 684 | int debug_node_color(struct rbt_tree* tree, struct rbt_node* n) 685 | { 686 | (void)tree; 687 | return (n == tree->nil) ? rbt_black : n->color; 688 | } 689 | 690 | void debug_verify_property_4(struct rbt_tree* tree, struct rbt_node* n) 691 | { 692 | if (debug_node_color(tree, n) == rbt_red) { 693 | assert(debug_node_color(tree, n->left) == rbt_black); 694 | assert(debug_node_color(tree, n->right) == rbt_black); 695 | assert(debug_node_color(tree, n->parent) == rbt_black); 696 | } 697 | if (n == tree->nil) { 698 | return; 699 | } 700 | debug_verify_property_4(tree, n->left); 701 | debug_verify_property_4(tree, n->right); 702 | } 703 | 704 | void debug_verify_property_5(struct rbt_tree* tree, struct rbt_node* root) 705 | { 706 | int black_count_path = -1; 707 | debug_verify_property_5_helper(tree, root, 0, &black_count_path); 708 | } 709 | 710 | void debug_verify_property_5_helper(struct rbt_tree* tree, struct rbt_node* n, 711 | int black_count, int* _black_count) 712 | { 713 | if (debug_node_color(tree, n) == rbt_black) { 714 | black_count++; 715 | } 716 | if (n == tree->nil) { 717 | if (*_black_count == -1) { 718 | *_black_count = black_count; 719 | } 720 | else { 721 | assert(black_count == *_black_count); 722 | } 723 | return; 724 | } 725 | debug_verify_property_5_helper(tree, n->left, black_count, _black_count); 726 | debug_verify_property_5_helper(tree, n->right, black_count, _black_count); 727 | } 728 | --------------------------------------------------------------------------------