├── .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 |
--------------------------------------------------------------------------------