├── .clang-format ├── .clang-tidy ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── bin └── .gitignore ├── format.sh ├── include ├── kylestructs.h └── kylestructs │ ├── ks_datacont.h │ ├── ks_hashmap.h │ ├── ks_hashset.h │ ├── ks_iterator.h │ ├── ks_list.h │ ├── ks_listnode.h │ ├── ks_treemap.h │ ├── ks_treemapnode.h │ ├── ks_treeset.h │ ├── ks_treesetnode.h │ └── ks_types.h ├── lint.sh ├── runtests.sh ├── samples ├── demo.c ├── inheritance_graph.png └── project_diagram.dot ├── src ├── ks_datacont.c ├── ks_hashmap.c ├── ks_hashset.c ├── ks_iterator.c ├── ks_list.c ├── ks_listnode.c ├── ks_treemap.c ├── ks_treemapnode.c ├── ks_treeset.c └── ks_treesetnode.c ├── testbin └── .gitignore └── tests ├── datacont_tests.c ├── hashmap_tests.c ├── hashset_tests.c ├── iterator_tests.c ├── list_tests.c ├── listnode_tests.c ├── treemap_tests.c ├── treemapnode_tests.c ├── treeset_tests.c └── treesetnode_tests.c /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Google 4 | AccessModifierOffset: -1 5 | AlignAfterOpenBracket: Align 6 | AlignArrayOfStructures: None 7 | AlignConsecutiveMacros: None 8 | AlignConsecutiveAssignments: None 9 | AlignConsecutiveBitFields: None 10 | AlignConsecutiveDeclarations: None 11 | AlignEscapedNewlines: Left 12 | AlignOperands: Align 13 | AlignTrailingComments: true 14 | AllowAllArgumentsOnNextLine: true 15 | AllowAllParametersOfDeclarationOnNextLine: true 16 | AllowShortEnumsOnASingleLine: true 17 | AllowShortBlocksOnASingleLine: Never 18 | AllowShortCaseLabelsOnASingleLine: false 19 | AllowShortFunctionsOnASingleLine: All 20 | AllowShortLambdasOnASingleLine: All 21 | AllowShortIfStatementsOnASingleLine: WithoutElse 22 | AllowShortLoopsOnASingleLine: true 23 | AlwaysBreakAfterDefinitionReturnType: None 24 | AlwaysBreakAfterReturnType: None 25 | AlwaysBreakBeforeMultilineStrings: true 26 | AlwaysBreakTemplateDeclarations: Yes 27 | AttributeMacros: 28 | - __capability 29 | BinPackArguments: true 30 | BinPackParameters: true 31 | BraceWrapping: 32 | AfterCaseLabel: false 33 | AfterClass: false 34 | AfterControlStatement: Never 35 | AfterEnum: false 36 | AfterFunction: false 37 | AfterNamespace: false 38 | AfterObjCDeclaration: false 39 | AfterStruct: false 40 | AfterUnion: false 41 | AfterExternBlock: false 42 | BeforeCatch: false 43 | BeforeElse: false 44 | BeforeLambdaBody: false 45 | BeforeWhile: false 46 | IndentBraces: false 47 | SplitEmptyFunction: true 48 | SplitEmptyRecord: true 49 | SplitEmptyNamespace: true 50 | BreakBeforeBinaryOperators: None 51 | BreakBeforeConceptDeclarations: true 52 | BreakBeforeBraces: Attach 53 | BreakBeforeInheritanceComma: false 54 | BreakInheritanceList: BeforeColon 55 | BreakBeforeTernaryOperators: true 56 | BreakConstructorInitializersBeforeComma: false 57 | BreakConstructorInitializers: BeforeColon 58 | BreakAfterJavaFieldAnnotations: false 59 | BreakStringLiterals: true 60 | ColumnLimit: 80 61 | CommentPragmas: '^ IWYU pragma:' 62 | QualifierAlignment: Leave 63 | CompactNamespaces: false 64 | ConstructorInitializerIndentWidth: 4 65 | ContinuationIndentWidth: 4 66 | Cpp11BracedListStyle: true 67 | DeriveLineEnding: true 68 | DerivePointerAlignment: true 69 | DisableFormat: false 70 | EmptyLineAfterAccessModifier: Never 71 | EmptyLineBeforeAccessModifier: LogicalBlock 72 | ExperimentalAutoDetectBinPacking: false 73 | PackConstructorInitializers: NextLine 74 | BasedOnStyle: '' 75 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 76 | AllowAllConstructorInitializersOnNextLine: true 77 | FixNamespaceComments: true 78 | ForEachMacros: 79 | - foreach 80 | - Q_FOREACH 81 | - BOOST_FOREACH 82 | IfMacros: 83 | - KJ_IF_MAYBE 84 | IncludeBlocks: Regroup 85 | IncludeCategories: 86 | - Regex: '^' 87 | Priority: 2 88 | SortPriority: 0 89 | CaseSensitive: false 90 | - Regex: '^<.*\.h>' 91 | Priority: 1 92 | SortPriority: 0 93 | CaseSensitive: false 94 | - Regex: '^<.*' 95 | Priority: 2 96 | SortPriority: 0 97 | CaseSensitive: false 98 | - Regex: '.*' 99 | Priority: 3 100 | SortPriority: 0 101 | CaseSensitive: false 102 | IncludeIsMainRegex: '([-_](test|unittest))?$' 103 | IncludeIsMainSourceRegex: '' 104 | IndentAccessModifiers: false 105 | IndentCaseLabels: true 106 | IndentCaseBlocks: false 107 | IndentGotoLabels: true 108 | IndentPPDirectives: None 109 | IndentExternBlock: AfterExternBlock 110 | IndentRequires: false 111 | IndentWidth: 4 112 | IndentWrappedFunctionNames: false 113 | InsertTrailingCommas: None 114 | JavaScriptQuotes: Leave 115 | JavaScriptWrapImports: true 116 | KeepEmptyLinesAtTheStartOfBlocks: false 117 | LambdaBodyIndentation: Signature 118 | MacroBlockBegin: '' 119 | MacroBlockEnd: '' 120 | MaxEmptyLinesToKeep: 1 121 | NamespaceIndentation: None 122 | ObjCBinPackProtocolList: Never 123 | ObjCBlockIndentWidth: 2 124 | ObjCBreakBeforeNestedBlockParam: true 125 | ObjCSpaceAfterProperty: false 126 | ObjCSpaceBeforeProtocolList: true 127 | PenaltyBreakAssignment: 2 128 | PenaltyBreakBeforeFirstCallParameter: 1 129 | PenaltyBreakComment: 300 130 | PenaltyBreakFirstLessLess: 120 131 | PenaltyBreakOpenParenthesis: 0 132 | PenaltyBreakString: 1000 133 | PenaltyBreakTemplateDeclaration: 10 134 | PenaltyExcessCharacter: 1000000 135 | PenaltyReturnTypeOnItsOwnLine: 200 136 | PenaltyIndentedWhitespace: 0 137 | PointerAlignment: Left 138 | PPIndentWidth: -1 139 | RawStringFormats: 140 | - Language: Cpp 141 | Delimiters: 142 | - cc 143 | - CC 144 | - cpp 145 | - Cpp 146 | - CPP 147 | - 'c++' 148 | - 'C++' 149 | CanonicalDelimiter: '' 150 | BasedOnStyle: google 151 | - Language: TextProto 152 | Delimiters: 153 | - pb 154 | - PB 155 | - proto 156 | - PROTO 157 | EnclosingFunctions: 158 | - EqualsProto 159 | - EquivToProto 160 | - PARSE_PARTIAL_TEXT_PROTO 161 | - PARSE_TEST_PROTO 162 | - PARSE_TEXT_PROTO 163 | - ParseTextOrDie 164 | - ParseTextProtoOrDie 165 | - ParseTestProto 166 | - ParsePartialTestProto 167 | CanonicalDelimiter: pb 168 | BasedOnStyle: google 169 | ReferenceAlignment: Pointer 170 | ReflowComments: false 171 | RemoveBracesLLVM: false 172 | SeparateDefinitionBlocks: Leave 173 | ShortNamespaceLines: 1 174 | SortIncludes: CaseSensitive 175 | SortJavaStaticImport: Before 176 | SortUsingDeclarations: true 177 | SpaceAfterCStyleCast: false 178 | SpaceAfterLogicalNot: false 179 | SpaceAfterTemplateKeyword: true 180 | SpaceBeforeAssignmentOperators: true 181 | SpaceBeforeCaseColon: false 182 | SpaceBeforeCpp11BracedList: false 183 | SpaceBeforeCtorInitializerColon: true 184 | SpaceBeforeInheritanceColon: true 185 | SpaceBeforeParens: ControlStatements 186 | SpaceBeforeParensOptions: 187 | AfterControlStatements: true 188 | AfterForeachMacros: true 189 | AfterFunctionDefinitionName: false 190 | AfterFunctionDeclarationName: false 191 | AfterIfMacros: true 192 | AfterOverloadedOperator: false 193 | BeforeNonEmptyParentheses: false 194 | SpaceAroundPointerQualifiers: Default 195 | SpaceBeforeRangeBasedForLoopColon: true 196 | SpaceInEmptyBlock: false 197 | SpaceInEmptyParentheses: false 198 | SpacesBeforeTrailingComments: 2 199 | SpacesInAngles: Never 200 | SpacesInConditionalStatement: false 201 | SpacesInContainerLiterals: true 202 | SpacesInCStyleCastParentheses: false 203 | SpacesInLineCommentPrefix: 204 | Minimum: 1 205 | Maximum: -1 206 | SpacesInParentheses: false 207 | SpacesInSquareBrackets: false 208 | SpaceBeforeSquareBrackets: false 209 | BitFieldColonSpacing: Both 210 | Standard: Auto 211 | StatementAttributeLikeMacros: 212 | - Q_EMIT 213 | StatementMacros: 214 | - Q_UNUSED 215 | - QT_REQUIRE_VERSION 216 | TabWidth: 8 217 | UseCRLF: false 218 | UseTab: Never 219 | WhitespaceSensitiveMacros: 220 | - STRINGIZE 221 | - PP_STRINGIZE 222 | - BOOST_PP_STRINGIZE 223 | - NS_SWIFT_NAME 224 | - CF_SWIFT_NAME 225 | ... 226 | 227 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: 'clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling' 3 | WarningsAsErrors: '' 4 | HeaderFilterRegex: '' 5 | AnalyzeTemporaryDtors: false 6 | FormatStyle: Google 7 | CheckOptions: 8 | - key: llvm-else-after-return.WarnOnConditionVariables 9 | value: 'false' 10 | - key: modernize-loop-convert.MinConfidence 11 | value: reasonable 12 | - key: modernize-replace-auto-ptr.IncludeStyle 13 | value: llvm 14 | - key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons 15 | value: 'false' 16 | - key: google-readability-namespace-comments.ShortNamespaceLines 17 | value: '10' 18 | - key: cert-err33-c.CheckedFunctions 19 | value: '::aligned_alloc;::asctime_s;::at_quick_exit;::atexit;::bsearch;::bsearch_s;::btowc;::c16rtomb;::c32rtomb;::calloc;::clock;::cnd_broadcast;::cnd_init;::cnd_signal;::cnd_timedwait;::cnd_wait;::ctime_s;::fclose;::fflush;::fgetc;::fgetpos;::fgets;::fgetwc;::fopen;::fopen_s;::fprintf;::fprintf_s;::fputc;::fputs;::fputwc;::fputws;::fread;::freopen;::freopen_s;::fscanf;::fscanf_s;::fseek;::fsetpos;::ftell;::fwprintf;::fwprintf_s;::fwrite;::fwscanf;::fwscanf_s;::getc;::getchar;::getenv;::getenv_s;::gets_s;::getwc;::getwchar;::gmtime;::gmtime_s;::localtime;::localtime_s;::malloc;::mbrtoc16;::mbrtoc32;::mbsrtowcs;::mbsrtowcs_s;::mbstowcs;::mbstowcs_s;::memchr;::mktime;::mtx_init;::mtx_lock;::mtx_timedlock;::mtx_trylock;::mtx_unlock;::printf_s;::putc;::putwc;::raise;::realloc;::remove;::rename;::scanf;::scanf_s;::setlocale;::setvbuf;::signal;::snprintf;::snprintf_s;::sprintf;::sprintf_s;::sscanf;::sscanf_s;::strchr;::strerror_s;::strftime;::strpbrk;::strrchr;::strstr;::strtod;::strtof;::strtoimax;::strtok;::strtok_s;::strtol;::strtold;::strtoll;::strtoul;::strtoull;::strtoumax;::strxfrm;::swprintf;::swprintf_s;::swscanf;::swscanf_s;::thrd_create;::thrd_detach;::thrd_join;::thrd_sleep;::time;::timespec_get;::tmpfile;::tmpfile_s;::tmpnam;::tmpnam_s;::tss_create;::tss_get;::tss_set;::ungetc;::ungetwc;::vfprintf;::vfprintf_s;::vfscanf;::vfscanf_s;::vfwprintf;::vfwprintf_s;::vfwscanf;::vfwscanf_s;::vprintf_s;::vscanf;::vscanf_s;::vsnprintf;::vsnprintf_s;::vsprintf;::vsprintf_s;::vsscanf;::vsscanf_s;::vswprintf;::vswprintf_s;::vswscanf;::vswscanf_s;::vwprintf_s;::vwscanf;::vwscanf_s;::wcrtomb;::wcschr;::wcsftime;::wcspbrk;::wcsrchr;::wcsrtombs;::wcsrtombs_s;::wcsstr;::wcstod;::wcstof;::wcstoimax;::wcstok;::wcstok_s;::wcstol;::wcstold;::wcstoll;::wcstombs;::wcstombs_s;::wcstoul;::wcstoull;::wcstoumax;::wcsxfrm;::wctob;::wctrans;::wctype;::wmemchr;::wprintf_s;::wscanf;::wscanf_s;' 20 | - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField 21 | value: 'false' 22 | - key: cert-dcl16-c.NewSuffixes 23 | value: 'L;LL;LU;LLU' 24 | - key: google-readability-braces-around-statements.ShortStatementLines 25 | value: '1' 26 | - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic 27 | value: 'true' 28 | - key: google-readability-namespace-comments.SpacesBeforeComments 29 | value: '2' 30 | - key: modernize-loop-convert.MaxCopySize 31 | value: '16' 32 | - key: modernize-pass-by-value.IncludeStyle 33 | value: llvm 34 | - key: modernize-use-nullptr.NullMacros 35 | value: 'NULL' 36 | - key: llvm-qualified-auto.AddConstToQualified 37 | value: 'false' 38 | - key: modernize-loop-convert.NamingStyle 39 | value: CamelCase 40 | - key: llvm-else-after-return.WarnOnUnfixable 41 | value: 'false' 42 | - key: google-readability-function-size.StatementThreshold 43 | value: '800' 44 | ... 45 | 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.txt 2 | *.o 3 | *.swp 4 | *.gcp 5 | *.out 6 | *.a 7 | *.so 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC := clang 2 | CFLAGS := -Iinclude -fPIC -Wall -Wextra -O2 3 | TESTFLAGS := -Iinclude -g -O0 -fsanitize=address,undefined 4 | 5 | SRC := src 6 | INC := include 7 | SBIN := bin 8 | 9 | TEST := tests 10 | TBIN := testbin 11 | 12 | INCLOC := /usr/include 13 | LIBLOC := /usr/lib 14 | 15 | default: all 16 | 17 | 18 | # compile sources 19 | 20 | DATACONTDEPS := $(SRC)/ks_datacont.c 21 | DATACONTTARG := $(SBIN)/ks_datacont.o 22 | 23 | $(DATACONTTARG): $(DATACONTDEPS) 24 | $(CC) -c $< -o $@ $(CFLAGS) 25 | 26 | 27 | ITERATORDEPS := $(SRC)/ks_iterator.c 28 | ITERATORTARG := $(SBIN)/ks_iterator.o 29 | 30 | $(ITERATORTARG): $(ITERATORDEPS) 31 | $(CC) -c $< -o $@ $(CFLAGS) 32 | 33 | 34 | LISTNODEDEPS := $(SRC)/ks_listnode.c 35 | LISTNODETARG := $(SBIN)/ks_listnode.o 36 | 37 | $(LISTNODETARG): $(LISTNODEDEPS) 38 | $(CC) -c $< -o $@ $(CFLAGS) 39 | 40 | 41 | LISTDEPS := $(SRC)/ks_list.c 42 | LISTTARG := $(SBIN)/ks_list.o 43 | 44 | $(LISTTARG): $(LISTDEPS) 45 | $(CC) -c $< -o $@ $(CFLAGS) 46 | 47 | 48 | TREESETNODEDEPS := $(SRC)/ks_treesetnode.c 49 | TREESETNODETARG := $(SBIN)/ks_treesetnode.o 50 | 51 | $(TREESETNODETARG): $(TREESETNODEDEPS) 52 | $(CC) -c $< -o $@ $(CFLAGS) 53 | 54 | 55 | TREESETDEPS := $(SRC)/ks_treeset.c 56 | TREESETTARG := $(SBIN)/ks_treeset.o 57 | 58 | $(TREESETTARG): $(TREESETDEPS) 59 | $(CC) -c $< -o $@ $(CFLAGS) 60 | 61 | 62 | HASHSETDEPS := $(SRC)/ks_hashset.c 63 | HASHSETTARG := $(SBIN)/ks_hashset.o 64 | 65 | $(HASHSETTARG): $(HASHSETDEPS) 66 | $(CC) -c $< -o $@ $(CFLAGS) 67 | 68 | 69 | TREEMAPNODEDEPS := $(SRC)/ks_treemapnode.c 70 | TREEMAPNODETARG := $(SBIN)/ks_treemapnode.o 71 | 72 | $(TREEMAPNODETARG): $(TREEMAPNODEDEPS) 73 | $(CC) -c $< -o $@ $(CFLAGS) 74 | 75 | 76 | TREEMAPDEPS := $(SRC)/ks_treemap.c 77 | TREEMAPTARG := $(SBIN)/ks_treemap.o 78 | 79 | $(TREEMAPTARG): $(TREEMAPDEPS) 80 | $(CC) -c $< -o $@ $(CFLAGS) 81 | 82 | 83 | HASHMAPDEPS := $(SRC)/ks_hashmap.c 84 | HASHMAPTARG := $(SBIN)/ks_hashmap.o 85 | 86 | $(HASHMAPTARG): $(HASHMAPDEPS) 87 | $(CC) -c $< -o $@ $(CFLAGS) 88 | 89 | 90 | # compile tests 91 | 92 | TESTDEPS := $(DATACONTDEPS) $(ITERATORDEPS) $(LISTNODEDEPS) $(LISTDEPS) $(TREESETNODEDEPS) $(TREESETDEPS)\ 93 | $(HASHSETDEPS) $(TREEMAPNODEDEPS) $(TREEMAPDEPS) $(HASHMAPDEPS) 94 | 95 | 96 | DATACONTTESTTARG := $(TBIN)/datacont_tests.out 97 | 98 | $(DATACONTTESTTARG): $(TEST)/datacont_tests.c $(TESTDEPS) 99 | $(CC) -g $^ -o $@ $(TESTFLAGS) 100 | 101 | 102 | ITERATORTESTTARG := $(TBIN)/iterator_tests.out 103 | 104 | $(ITERATORTESTTARG): $(TEST)/iterator_tests.c $(TESTDEPS) 105 | $(CC) -g $^ -o $@ $(TESTFLAGS) 106 | 107 | 108 | LISTNODETESTTARG := $(TBIN)/listnode_tests.out 109 | 110 | $(LISTNODETESTTARG): $(TEST)/listnode_tests.c $(TESTDEPS) 111 | $(CC) -g $^ -o $@ $(TESTFLAGS) 112 | 113 | 114 | LISTTESTTARG := $(TBIN)/list_tests.out 115 | 116 | $(LISTTESTTARG): $(TEST)/list_tests.c $(TESTDEPS) 117 | $(CC) -g $^ -o $@ $(TESTFLAGS) 118 | 119 | 120 | TREESETNODETESTTARG := $(TBIN)/treesetnode_tests.out 121 | 122 | $(TREESETNODETESTTARG): $(TEST)/treesetnode_tests.c $(TESTDEPS) 123 | $(CC) -g $^ -o $@ $(TESTFLAGS) 124 | 125 | 126 | TREESETTESTTARG := $(TBIN)/treeset_tests.out 127 | 128 | $(TREESETTESTTARG): $(TEST)/treeset_tests.c $(TESTDEPS) 129 | $(CC) -g $^ -o $@ $(TESTFLAGS) 130 | 131 | 132 | HASHSETTESTTARG := $(TBIN)/hashset_tests.out 133 | 134 | $(HASHSETTESTTARG): $(TEST)/hashset_tests.c $(TESTDEPS) 135 | $(CC) -g $^ -o $@ $(TESTFLAGS) 136 | 137 | 138 | TREEMAPNODETESTTARG := $(TBIN)/treemapnode_tests.out 139 | 140 | $(TREEMAPNODETESTTARG): $(TEST)/treemapnode_tests.c $(TESTDEPS) 141 | $(CC) -g $^ -o $@ $(TESTFLAGS) 142 | 143 | 144 | TREEMAPTESTTARG := $(TBIN)/treemap_tests.out 145 | 146 | $(TREEMAPTESTTARG): $(TEST)/treemap_tests.c $(TESTDEPS) 147 | $(CC) -g $^ -o $@ $(TESTFLAGS) 148 | 149 | 150 | HASHMAPTESTTARG := $(TBIN)/hashmap_tests.out 151 | 152 | $(HASHMAPTESTTARG): $(TEST)/hashmap_tests.c $(TESTDEPS) 153 | $(CC) -g $^ -o $@ $(TESTFLAGS) 154 | 155 | 156 | .PHONY: run_tests 157 | run_tests: tests 158 | ./runtests.sh 159 | 160 | 161 | .PHONY: tests 162 | tests: $(DATACONTTESTTARG) $(ITERATORTESTTARG) $(LISTNODETESTTARG) $(LISTTESTTARG) $(TREESETNODETESTTARG)\ 163 | $(TREESETTESTTARG) $(HASHSETTESTTARG) $(TREEMAPNODETESTTARG) $(TREEMAPTESTTARG) $(HASHMAPTESTTARG) 164 | @echo Finished building tests. 165 | 166 | 167 | STATICLIB := libkylestructs.a 168 | $(STATICLIB): $(DATACONTTARG) $(ITERATORTARG) $(LISTNODETARG) $(LISTTARG) $(TREESETNODETARG)\ 169 | $(TREESETTARG) $(HASHSETTARG) $(TREEMAPNODETARG) $(TREEMAPTARG) $(HASHMAPTARG) 170 | ar rcs $(STATICLIB)\ 171 | $(DATACONTTARG)\ 172 | $(ITERATORTARG)\ 173 | $(LISTNODETARG)\ 174 | $(LISTTARG)\ 175 | $(TREESETNODETARG)\ 176 | $(TREESETTARG)\ 177 | $(HASHSETTARG)\ 178 | $(TREEMAPNODETARG)\ 179 | $(TREEMAPTARG)\ 180 | $(HASHMAPTARG) 181 | 182 | 183 | DYNAMICLIB := libkylestructs.so 184 | $(DYNAMICLIB): $(DATACONTTARG) $(ITERATORTARG) $(LISTNODETARG) $(LISTTARG) $(TREESETNODETARG)\ 185 | $(TREESETTARG) $(HASHSETTARG) $(LISTNODETARG) $(TREEMAPNODETARG) $(TREEMAPTARG) $(HASHMAPTARG) 186 | gcc -shared -o $(DYNAMICLIB)\ 187 | $(DATACONTTARG)\ 188 | $(ITERATORTARG)\ 189 | $(LISTNODETARG)\ 190 | $(LISTTARG)\ 191 | $(TREESETNODETARG)\ 192 | $(TREESETTARG)\ 193 | $(HASHSETTARG)\ 194 | $(TREEMAPNODETARG)\ 195 | $(TREEMAPTARG)\ 196 | $(HASHMAPTARG) 197 | 198 | 199 | .PHONY: install 200 | install: $(STATICLIB) $(DYNAMICLIB) 201 | cp -r $(INC)/* $(INCLOC) 202 | cp $(STATICLIB) $(LIBLOC) 203 | cp $(DYNAMICLIB) $(LIBLOC) 204 | 205 | 206 | .PHONY: uninstall 207 | uninstall: 208 | if [ -d $(INCLOC) ]; then rm -r $(INCLOC); fi; 209 | if [ -f $(INCLOC)/../kylestructs.h ]; then rm -r $(INCLOC)/../kylestructs.h ]; fi; 210 | if [ -f $(LIBLOC)/$(STATICLIB) ]; then rm $(LIBLOC)/$(STATICLIB); fi; 211 | if [ -f $(LIBLOC)/$(DYNAMICLIB) ]; then rm $(LIBLOC)/$(DYNAMICLIB); fi; 212 | 213 | 214 | .PHONY: clean 215 | clean: 216 | if [ -f $(STATICLIB) ]; then rm $(STATICLIB); fi; 217 | if [ -f $(DYNAMICLIB) ]; then rm $(DYNAMICLIB); fi; 218 | if [ -f $(DATACONTTARG) ]; then rm $(DATACONTTARG); fi; 219 | if [ -f $(DATACONTTESTTARG) ]; then rm $(DATACONTTESTTARG); fi; 220 | if [ -f $(ITERATORTARG) ]; then rm $(ITERATORTARG); fi; 221 | if [ -f $(ITERATORTESTTARG) ]; then rm $(ITERATORTESTTARG); fi; 222 | if [ -f $(LISTNODETARG) ]; then rm $(LISTNODETARG); fi; 223 | if [ -f $(LISTNODETESTTARG) ]; then rm $(LISTNODETESTTARG); fi; 224 | if [ -f $(LISTTARG) ]; then rm $(LISTTARG); fi; 225 | if [ -f $(LISTTESTTARG) ]; then rm $(LISTTESTTARG); fi; 226 | if [ -f $(TREESETNODETARG) ]; then rm $(TREESETNODETARG); fi; 227 | if [ -f $(TREESETNODETESTTARG) ]; then rm $(TREESETNODETESTTARG); fi; 228 | if [ -f $(TREESETTARG) ]; then rm $(TREESETTARG); fi; 229 | if [ -f $(TREESETTESTTARG) ]; then rm $(TREESETTESTTARG); fi; 230 | if [ -f $(HASHSETTARG) ]; then rm $(HASHSETTARG); fi; 231 | if [ -f $(HASHSETTESTTARG) ]; then rm $(HASHSETTESTTARG); fi; 232 | if [ -f $(TREEMAPNODETARG) ]; then rm $(TREEMAPNODETARG); fi; 233 | if [ -f $(TREEMAPNODETESTTARG) ]; then rm $(TREEMAPNODETESTTARG); fi; 234 | if [ -f $(TREEMAPTARG) ]; then rm $(TREEMAPTARG); fi; 235 | if [ -f $(TREEMAPTESTTARG) ]; then rm $(TREEMAPTESTTARG); fi; 236 | if [ -f $(HASHMAPTARG) ]; then rm $(HASHMAPTARG); fi; 237 | if [ -f $(HASHMAPTESTTARG) ]; then rm $(HASHMAPTESTTARG); fi; 238 | 239 | 240 | .PHONY: all 241 | all: run_tests 242 | @echo "All tests passed." 243 | @echo "Building static libs..." 244 | $(MAKE) $(STATICLIB) 245 | @echo "Done." 246 | @echo "Building shared libs..." 247 | $(MAKE) $(DYNAMICLIB) 248 | @echo "Done." 249 | 250 | 251 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KyleStructs 2 | This is a C library I wrote to satisfy my own curiosity as to how simple data structures like tree sets and hash maps might be implemented. My goal has been to design and write everything as clearly and logically as possible while maintaining effiency. 3 | 4 | The documentation for each data structure is located in its respective header file in `src/include/`. 5 | 6 | ## Demo 7 | Here is a quick example of how KyleStructs might be used: 8 | 9 | ```c 10 | /* gcc main.c -lkylestructs */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | int main() 18 | { 19 | ks_hashmap* phonebook = ks_hashmap_new(KS_CHARP, 10); 20 | const ks_datacont* number_dc; 21 | const ks_datacont* name_dc; 22 | 23 | char number[30] = {0}; 24 | char name[30] = {0}; 25 | 26 | printf("Enter a name followed by a 10-digit phone number:\n"); 27 | 28 | while (scanf("%s %s", name, number) != -1) 29 | { 30 | number_dc = ks_datacont_new(number, KS_CHARP, strlen(number)); 31 | name_dc = ks_datacont_new(name, KS_CHARP, strlen(name)); 32 | 33 | if (ks_hashmap_add(phonebook, number_dc, name_dc) == 1) 34 | printf("Replaced existing number %s.\n", number); 35 | 36 | memset(number, 0, 30); 37 | memset(name, 0, 30); 38 | } 39 | 40 | int count = ks_hashmap_count(phonebook); 41 | 42 | for (int i = 0; i < count; i++) 43 | { 44 | number_dc = ks_hashmap_get_key(phonebook, i); 45 | name_dc = ks_hashmap_get(phonebook, number_dc); 46 | 47 | printf("%s => %s\n", number_dc->cp, name_dc->cp); 48 | } 49 | 50 | ks_hashmap_delete(phonebook); 51 | } 52 | ``` 53 | 54 | ## Library Overview 55 | At the center of all of these different data structures is the `ks_datacont` struct. It is a container that can hold pretty much any primitive data type, and comes with a library for comparison, duplication, hashing, and more. All other structures are built on top of the `ks_datacont` struct so that they in turn can handle most kinds of data. As the design for each structure grows more complex, functionality is borrowed from one or more of those that are less complex. Here is a graph to illustrate the order of "inheritance": 56 | 57 | ![Overview](samples/inheritance_graph.png) 58 | 59 | ## Build and Install 60 | ```sh 61 | $ git clone https://github.com/krglaws/KyleStructs 62 | $ cd KyleStructs 63 | $ make 64 | $ sudo make install 65 | ``` 66 | 67 | ## Contributing 68 | If you would like to contribute, feel free to fork this repository and submit a pull request. Be sure to add to or change the existing tests to reflect your changes. 69 | 70 | _Images generated using [Graphviz](https://www.graphviz.org/)_ 71 | ## To Do: 72 | - write toString functions for each structure 73 | - write toDotFile functions for each structure 74 | - write set operation functions (e.g. union, intersection, difference, comparison, etc.) 75 | 76 | -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | clang-format -i include/kylestructs.h include/kylestructs/*.h src/*.c tests/*.c 3 | exit $? 4 | -------------------------------------------------------------------------------- /include/kylestructs.h: -------------------------------------------------------------------------------- 1 | #ifndef _KYLESTRUCTS_H_ 2 | #define _KYLESTRUCTS_H_ 3 | 4 | /* main header */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/kylestructs/ks_datacont.h: -------------------------------------------------------------------------------- 1 | #ifndef _KS_DATACONT_H_ 2 | #define _KS_DATACONT_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "ks_types.h" 8 | 9 | /* --------------------------- 10 | * ks_datacont_new(): 11 | * Creates a new ks_datacont* containing the data pointed to by 'data'. 12 | * 13 | * Inputs: 14 | * void* data - THE data being stored within the ks_datacont. 15 | * enum ks_datatype dct - the type of the data being stored. See the ks_datatype enum 16 | * defined in ks_types.h to review available types. 17 | * size_t size - the number of bytes that 'data' points to. This value is used to generate 18 | * hash values in ks_datacont_hash() as well as when storing into hashmaps and 19 | * hashsets. 20 | * 21 | * Returns: 22 | * ks_datacont* dc - (NULL) if 'data' is NULL or 'count'== 0. 23 | * - a ks_datacont* containing the data specified. 24 | * 25 | * Notes: 26 | * The data pointed to by 'data' is copied into the new ks_datacont structure. This gives 27 | * the user code the ability to allocate data onto the stack, create a ks_datacont for it, 28 | * and return it. 29 | * 30 | * If the type is KS_CHARP, a null terminating character '\0' is appended to the end of 31 | * the string so that calls like strlen(dc->cp) won't cause a seg fault. 32 | */ 33 | ks_datacont* ks_datacont_new(const void* data, enum ks_datatype type, 34 | size_t size); 35 | 36 | /* --------------------------- 37 | * ks_datacont_delete(): 38 | * Deletes a ks_datacont struct along with any data it contains. 39 | * 40 | * Inputs: 41 | * ks_datacont* dc - the ks_datacont being deleted. 42 | * 43 | * Returns: 44 | * void 45 | * 46 | * Notes: 47 | * ks_datacont_delete() will not call free() on the pointer in KS_VOIDP type 48 | * as it does on the other pointer types. The user code is expected to handle 49 | * whatever memory management is necessary in that case. 50 | */ 51 | void ks_datacont_delete(ks_datacont* dc); 52 | 53 | /* --------------------------- 54 | * ks_datacont_copy(): 55 | * Creates an identical copy of a ks_datacont* struct, including all of the data 56 | * that the original contains. 57 | * 58 | * Inputs: 59 | * ks_datacont* dc - the ks_datacont being copied. 60 | * 61 | * Returns: 62 | * ks_datacont* copy - (NULL) if 'dc' is NULL. 63 | * - a copy of 'dc'. 64 | * 65 | * Notes: 66 | * ks_datacont_copy() will always do deep copies (i.e. it will make a copy of 67 | * the ks_datacont struct itself, as well as any data it points to), 68 | * except on KS_VOIDP types. 69 | */ 70 | ks_datacont* ks_datacont_copy(const ks_datacont* dc); 71 | 72 | /* --------------------------- 73 | * ks_datacont_compare(): 74 | * Compares two ks_datacont structs and returns an enum type that specifies the 75 | * result of the comparison. 76 | * 77 | * Inputs: 78 | * ks_datacont* dca - one of the ks_datacont structs being compared. 79 | * ks_datacont* dcb - the other ks_datacont being compared. 80 | * 81 | * Returns: 82 | * enum ks_comparison result - see the enum ks_comparison definition in the ks_types.h 83 | * header for details. 84 | * 85 | * Notes: 86 | * When used on KS_CHARP type, the strings are compared alphabetically with strcmp(). 87 | * Other supported pointer types are compared with memcmp(). 88 | * 89 | * The following types do not support comparison: KS_VOIDP, KS_LIST, KS_HASHSET, 90 | * KS_HASHMAP, KS_TREESET and KS_TREEMAP. This function will return KS_CANTCOMPARE 91 | * for these types. 92 | */ 93 | enum ks_comparison ks_datacont_compare(const ks_datacont* dca, 94 | const ks_datacont* dcb); 95 | 96 | /* --------------------------- 97 | * ks_datacont_hash(): 98 | * Hashes the data contained within a ks_datacont and returns the result as an unsigned 99 | * 32-bit integer. 100 | * 101 | * Inputs: 102 | * ks_datacont* dc - the ks_datacont being hashed. 103 | * 104 | * Returns: 105 | * uint32_t hash - the hash of the data contained in the ks_datacont. 106 | * 107 | * Notes: 108 | * Pointer types KS_VOIDP, KS_LIST, KS_TREESET, KS_HASHSET, KS_TREEMAP, and KS_HASHMAP 109 | * WILL NOT be hashed. This function will return 0 for those types. 110 | */ 111 | uint32_t ks_datacont_hash(const ks_datacont* dc); 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /include/kylestructs/ks_hashmap.h: -------------------------------------------------------------------------------- 1 | #ifndef _KS_HASHMAP_H_ 2 | #define _KS_HASHMAP_H_ 3 | 4 | #include 5 | 6 | #include "ks_types.h" 7 | 8 | /* ------------------------------------ 9 | * ks_hashmap_new(): 10 | * Creates a new empty ks_hashmap. 11 | * 12 | * Inputs: 13 | * unsigned int num_buckets - the number of buckets this ks_hashmap should contain. 14 | * enum ks_datatype type - the ks_datacont type this ks_hashmap will store. 15 | * 16 | * Returns: 17 | * ks_hashmap* hm - a new empty ks_hashmap. 18 | */ 19 | ks_hashmap* ks_hashmap_new(const enum ks_datatype type, size_t num_buckets); 20 | 21 | /* ---------------------------------- 22 | * ks_hashmap_delete(): 23 | * Deletes a ks_hashmap and all of its contents. 24 | * 25 | * Inputs: 26 | * ks_hashmap* hm - the ks_hashmap to be deleted. 27 | * 28 | * Returns: 29 | * void 30 | */ 31 | void ks_hashmap_delete(ks_hashmap* hm); 32 | 33 | /* ---------------------------------- 34 | * ks_hashmap_copy(): 35 | * Creates a copy of a ks_hashmap and all its contents. 36 | * 37 | * Inputs: 38 | * ks_hashmap* hm - the ks_hashmap to be copied. 39 | * 40 | * Returns: 41 | * ks_hashmap* - a copy of 'hm'. 42 | */ 43 | ks_hashmap* ks_hashmap_copy(const ks_hashmap* hm); 44 | 45 | /* ---------------------------------- 46 | * ks_hashmap_add(): 47 | * Add a key/value pair to a ks_hashmap. 48 | * 49 | * Inputs: 50 | * ks_hashmap* hm - the ks_hashmap to be added to 51 | * ks_datacont* key - the key 52 | * ks_datacont* value - the value that the key maps to 53 | * 54 | * Returns: 55 | * int result - (-1) if any param is NULL, or if 'key's type does not match 'hm's type. 56 | * - (0) pair was added successfully. 57 | * - (1) pair added successfully, old key and value replaced. 58 | * 59 | * Notes: 60 | * - If the key-value pair is successfully added to the ks_hashmap (0), the user code 61 | * must not delete or modify 'key' or 'value', otherwise undefined behavior could 62 | * ensue. If a key with the same value was already present (1), the old key and value 63 | * have been deleted and replaced by the new key and value. If the pair was not added 64 | * to the ks_hashmap (-1), the user code is responsible for deleting both when they are 65 | * no longer needed. 66 | * 67 | * - The following types do not support hashing: KS_VOIDP, KS_LIST, KS_HASHSET, 68 | * KS_HASHMAP, KS_TREESET and KS_TREEMAP. This function will return -1 for these types. 69 | */ 70 | int ks_hashmap_add(ks_hashmap* hm, const ks_datacont* key, 71 | const ks_datacont* value); 72 | 73 | /* --------------------------- 74 | * ks_hashmap_remove(): 75 | * Find key/value pare and delete it. 76 | * 77 | * Inputs: 78 | * ks_hashmap* hm - the ks_hashmap to be operated on 79 | * ks_datacont* key - the key to be removed 80 | * 81 | * Returns: 82 | * int result - (-1) if either param is NULL, or if 'key' could not be found. 83 | * - (0) pair removed successfully. 84 | * 85 | * Notes: 86 | * this procedure does not consume 'key'. It is the client code's responsibility 87 | * to delete 'key' when it is no longer needed. 88 | */ 89 | int ks_hashmap_remove(ks_hashmap* hm, const ks_datacont* key); 90 | 91 | /* --------------------------- 92 | * ks_hashmap_get(): 93 | * Gets a value from a ks_hashmap by key. 94 | * 95 | * Inputs: 96 | * ks_hashmap* hm - the ks_hashmap to be operated on 97 | * ks_datacont* key - the key to use to retrieve a value 98 | * 99 | * Returns: 100 | * ks_datacont* value - (NULL) when the key could not be found. 101 | * - the value mapped to by the key. 102 | * 103 | * Notes: 104 | * The ks_datacont returned by this function is a pointer to the original contained within the ks_hashmap, 105 | * so it should not be deleted or modified by client code. 106 | * See notes on ks_hashmap_remove(). 107 | */ 108 | const ks_datacont* ks_hashmap_get(const ks_hashmap* hm, const ks_datacont* key); 109 | 110 | /* --------------------------- 111 | * ks_hashmap_get_key(): 112 | * Gets a key from a ks_hashmap by index. 113 | * 114 | * Inputs: 115 | * ks_hashmap* hm - the ks_hashmap to be operated on 116 | * int index - the index from which to retrieve a key (supports negative indexing) 117 | * 118 | * Returns: 119 | * ks_datacont* key - (NULL) when index OOB. 120 | * - the value located at 'index'. 121 | * 122 | * Notes: 123 | * The ks_datacont returned by this function is a pointer to the original contained within the ks_hashmap, 124 | * so it should not be deleted or modified by client code. 125 | * See notes on ks_hashmap_remove(). 126 | */ 127 | const ks_datacont* ks_hashmap_get_key(const ks_hashmap* hm, int index); 128 | 129 | /* --------------------------------- 130 | * ks_hashmap_count(): 131 | * Count the number of key/value pairs stored within 132 | * a ks_hashmap. 133 | * 134 | * Inputs: 135 | * ks_hashmap* hm - the ks_hashmap to be operated on 136 | * 137 | * Returns: 138 | * unsigned int count - >= (0) the number of pairs found in the ks_hashmap, (0) if 'hm' is NULL. 139 | */ 140 | unsigned int ks_hashmap_count(const ks_hashmap* hm); 141 | 142 | /* ---------------------------- 143 | * ks_hashmap_optimize(): 144 | * Balances all of the ks_treemap buckets in a ks_hashmap to ensure O(log(N)) search time. 145 | * 146 | * Inputs: 147 | * ks_hashmap* hm - the ks_hashmap being optimized. 148 | * 149 | * Returns: 150 | * void 151 | */ 152 | void ks_hashmap_optimize(ks_hashmap* hm); 153 | 154 | #endif 155 | -------------------------------------------------------------------------------- /include/kylestructs/ks_hashset.h: -------------------------------------------------------------------------------- 1 | #ifndef _KS_HASHSET_H_ 2 | #define _KS_HASHSET_H_ 3 | 4 | #include 5 | 6 | #include "ks_types.h" 7 | 8 | /* ---------------------------------- 9 | * ks_hashset_new(): 10 | * Creates a new empty ks_hashset. 11 | * 12 | * Inputs: 13 | * unsigned int buckets - the number of buckets that the new ks_hashset should contain. 14 | * 15 | * Returns: 16 | * ks_hashset* hs - a new empty ks_hashset. 17 | */ 18 | ks_hashset* ks_hashset_new(enum ks_datatype type, size_t num_buckets); 19 | 20 | /* --------------------------------- 21 | * ks_hashset_delete(): 22 | * Deletes a ks_hashset and all of its contents. 23 | * 24 | * Inputs: 25 | * ks_hashset* hs - the ks_hashset being deleted. 26 | * 27 | * Returns: 28 | * void 29 | */ 30 | void ks_hashset_delete(ks_hashset* hs); 31 | 32 | /* ------------------------------- 33 | * ks_hashset_copy(): 34 | * Creates a copy of a ks_hashset and all of its contents. 35 | * 36 | * Inputs: 37 | * ks_hashset* hs - the ks_hashset being delete. 38 | * 39 | * Returns: 40 | * ks_hashset* - a copy of 'hs'. 41 | */ 42 | ks_hashset* ks_hashset_copy(const ks_hashset* hs); 43 | 44 | /* -------------------------------- 45 | * ks_hashset_add(): 46 | * Adds a ks_datacont to a hashaset. 47 | * 48 | * Inputs: 49 | * ks_hashset* hs - the ks_hashset being added to. 50 | * ks_datacont* dc - the ks_datacont being added to 'hs'. 51 | * 52 | * Returns: 53 | * int result - (-1) if either param is NULL, or if the ks_datatype of 'dc' does not 54 | * match the other ks_dataconts within the ks_hashset. 55 | * - (0) 'dc' was successfully added to the ks_hashset. 56 | * - (1) 'dc' is already stored in the ks_hashset. 57 | * 58 | * Notes: 59 | * If 'dc' is successfully stored into the set, 'dc' should not be deleted by the user code, 60 | * as it will be directly stored into the tree. Otherwise a seg fault is likely to occur. 61 | * In the event that a value matching 'dc' is already present, or if 'hs' is NULL, 'dc' will 62 | * not be stored into the set, and 'dc' must be deleted by the user code. 63 | * 64 | * - The following types do not support hashing: KS_VOIDP, KS_LIST, KS_HASHSET, 65 | * KS_HASHMAP, KS_TREESET and KS_TREEMAP. This function will return -1 for these types. 66 | */ 67 | int ks_hashset_add(ks_hashset* hs, const ks_datacont* dc); 68 | 69 | /* ------------------------- 70 | * ks_hashset_remove(): 71 | * Remove a ks_datacont from a ks_hashset. 72 | * 73 | * Inputs: 74 | * ks_hashset* hs - the ks_hashset being removed from. 75 | * ks_datacont* dc - the ks_datacont to be removed from 'hs'. 76 | * 77 | * Returns: 78 | * int result - (-1) if either param is NULL, or if 'dc' could not be found. 79 | * - (0) on success. 80 | */ 81 | int ks_hashset_remove(ks_hashset* hs, const ks_datacont* dc); 82 | 83 | /* ------------------------ 84 | * ks_hashset_contains(): 85 | * Searches for a specified ks_datacont value within a ks_hashset. 86 | * 87 | * Inputs: 88 | * ks_hashset* hs - the ks_hashset being searched. 89 | * ks_datacont* dc - the ks_datacont being searched for. 90 | * 91 | * Returns: 92 | * unsigned int result - (0) if 'dc' could not be found, or if either param is NULL. 93 | * - (1) 'hs' contains 'dc'. 94 | */ 95 | unsigned int ks_hashset_contains(const ks_hashset* hs, const ks_datacont* dc); 96 | 97 | /* ------------------------ 98 | * ks_hashset_count(): 99 | * Counts the number of ks_dataconts contained within a ks_hashset. 100 | * 101 | * Inputs: 102 | * ks_hashset* hs - the ks_hashset being operated on. 103 | * 104 | * Returns: 105 | * unsigned int count - >= (0) the number of ks_dataconts within 'hs', (0) when 'hs' is NULL. 106 | */ 107 | unsigned int ks_hashset_count(const ks_hashset* hs); 108 | 109 | /* -------------------- 110 | * ks_hashset_get(): 111 | * Retrieves a ks_datacont located at a specified index within a ks_hashset. 112 | * 113 | * Inputs: 114 | * ks_hashet* hs - the ks_hashset being operated on. 115 | * int index - the index from which to retrieve a ks_datacont. (supports negative indexing) 116 | * 117 | * Notes: 118 | * Negative values for 'index' are allowed. 119 | */ 120 | const ks_datacont* ks_hashset_get(const ks_hashset* hs, int index); 121 | 122 | /* -------------------- 123 | * ks_hashset_optimize(): 124 | * Balances all of the ks_treeset buckets in a ks_hashset to ensure O(log(N)) search 125 | * time. 126 | * 127 | * Inputs: 128 | * ks_hashset* hs - the ks_hashset being operated on. 129 | * 130 | * Returns: 131 | * void 132 | */ 133 | void ks_hashset_optimize(ks_hashset* hs); 134 | 135 | #endif 136 | -------------------------------------------------------------------------------- /include/kylestructs/ks_iterator.h: -------------------------------------------------------------------------------- 1 | #ifndef _KS_ITERATOR_H_ 2 | #define _KS_ITERATOR_H_ 3 | 4 | #include "ks_types.h" 5 | 6 | /* ------------------- 7 | * ks_iterator_new(): 8 | * Creates an iterator for a kylestructs object. 9 | * 10 | * Inputs: 11 | * void* ks_obj - the kylestructs object for which to create an iterator. 12 | * enum ks_datatype type - the type of 'ks_obj' 13 | * 14 | * Returns: 15 | * ks_iterator* - an iterator for 'ks_obj' 16 | * 17 | * Notes: 18 | * The 'type' parameter can only be KS_LIST, KS_TREESET, KS_HASHSET, 19 | * KS_TREEMAP, or KS_HASHMAP. 20 | */ 21 | ks_iterator* ks_iterator_new(const void* ks_obj, enum ks_datatype type); 22 | 23 | /* ------------------- 24 | * ks_iterator_delete(): 25 | * deletes a ks_iterator. 26 | * 27 | * Inputs: 28 | * ks_iterator* iter - the iterator to be deleted 29 | * 30 | * Returns: 31 | * void 32 | */ 33 | void ks_iterator_delete(ks_iterator* iter); 34 | 35 | /* ------------------- 36 | * ks_iterator_next(): 37 | * Retreives the current ks_datacont from an iterator, and 38 | * advances to the next. 39 | * 40 | * Inputs: 41 | * ks_iterator* iter - the iterator being operated on. 42 | * 43 | * Returns: 44 | * ks_datacont* - the current ks_datacont being pointed to by 'iter'. 45 | */ 46 | const ks_datacont* ks_iterator_next(ks_iterator* iter); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/kylestructs/ks_list.h: -------------------------------------------------------------------------------- 1 | #ifndef _KS_LIST_H_ 2 | #define _KS_LIST_H_ 3 | 4 | #include "ks_types.h" 5 | 6 | /* ------------------- 7 | * ks_list_new(): 8 | * Creates a new empty ks_list*. 9 | * 10 | * Inputs: 11 | * void 12 | * 13 | * Returns: 14 | * ks_list* ls - a ks_list* 15 | */ 16 | ks_list* ks_list_new(); 17 | 18 | /* -------------------- 19 | * ks_list_delete(ks_list* ln): 20 | * Deletes a ks_list and all of its contents. 21 | * 22 | * Inputs: 23 | * ks_list* ls - the ks_list* being deleted. 24 | * 25 | * Returns: 26 | * void 27 | */ 28 | void ks_list_delete(ks_list* ls); 29 | 30 | /* --------------------- 31 | * ks_list_copy(): 32 | * Creates a copy of a list and all of its contents. 33 | * 34 | * Inputs: 35 | * ks_list* 36 | */ 37 | ks_list* ks_list_copy(const ks_list* ls); 38 | 39 | /* -------------------- 40 | * ks_list_add(): 41 | * Append a ks_datacont* to a ks_list. 42 | * 43 | * Inputs: 44 | * ks_list* ls - the ks_list to be added to. 45 | * ks_datacont* dc - the ks_datacont being added to the ks_list. 46 | * 47 | * Returns: 48 | * int result - (-1) if either param is NULL. 49 | * - (0) on success. 50 | */ 51 | int ks_list_add(ks_list* ls, const ks_datacont* dc); 52 | 53 | /* ----------------------- 54 | * ks_list_merge(): 55 | * Merges two lists into one. 56 | * 57 | * Inputs: 58 | * ks_list* lsa - the ks_list to be merged to. 59 | * ks_list* lsb - the ks_list to be merged with lsa. 60 | * 61 | * Returns: 62 | * ks_list* - the merged list object. 63 | * 64 | * Notes: 65 | * If one of the params is NULL, the non-NULL param will be returned. 66 | * If both are NULL, NULL will be returned. The user code should not 67 | * free either 'lsa' or 'lsb' after calling this. 68 | */ 69 | ks_list* ks_list_merge(ks_list* lsa, ks_list* lsb); 70 | 71 | /* ----------------------- 72 | * ks_list_remove_by(): 73 | * Removes the first occurrence of a ks_datacont found within a ks_list. 74 | * 75 | * Inputs: 76 | * ks_list* ls - the ks_list being operated on. 77 | * ks_datacont* dc - the ks_datacont to be removed from the ks_list. 78 | * 79 | * Returns: 80 | * int result - (-1) if either param is NULL. 81 | * - (0) if the ks_datacont was not found. 82 | * - (1) if the ks_datacont was successfully removed. 83 | */ 84 | int ks_list_remove_by(ks_list* ls, const ks_datacont* dc); 85 | 86 | /* ----------------------------- 87 | * ks_list_remove_at(): 88 | * Removes a ks_datacont at a specified location within a ks_list. 89 | * 90 | * Inputs: 91 | * ks_list* ls - the ks_list being operated on. 92 | * int index - the index at which the removal will take place. Negative 93 | * values will wrap around. 94 | * 95 | * Returns: 96 | * int result - (-1) when 'ls' is NULL, or when 'index' is OOB. 97 | * - (0) on success. 98 | */ 99 | int ks_list_remove_at(ks_list* ls, int index); 100 | 101 | /* ------------------------ 102 | * ks_list_remove_all(): 103 | * Removes all occurrences of a specified ks_datacont value within a ks_list. 104 | * 105 | * Inputs: 106 | * ks_list* ls - the ks_list being operated on. 107 | * ks_datacont* dc - the ks_datacont being removed from the ks_list. 108 | * 109 | * Returns: 110 | * int result - (-1) if either param is NULL. 111 | * - >= (0) the number of items removed from the ks_list. 112 | */ 113 | int ks_list_remove_all(ks_list* ls, const ks_datacont* dc); 114 | 115 | /* ----------------------------- 116 | * ks_list_replace_by(): 117 | * Replaces the first occurrence of a specified ks_datacont value with a new ks_datacont value. 118 | * 119 | * Inputs: 120 | * ks_list* ls - the ks_list being operated on. 121 | * ks_datacont* old_dc - the original ks_datacont to be replaced. 122 | * ks_datacont* new_dc - the new ks_datacont replacing the original. 123 | * 124 | * Returns: 125 | * int result - (-1) when any param is NULL, or when 'old_dc' could not be found. 126 | * - (0) on success. 127 | */ 128 | int ks_list_replace_by(ks_list* ls, const ks_datacont* old_dc, 129 | const ks_datacont* new_dc); 130 | 131 | /* ----------------------------- 132 | * ks_list_replace_at(): 133 | * Replaces a ks_datacont at a specified location within a ks_list. 134 | * 135 | * Inputs: 136 | * ks_list* ls - the ks_list being operated on. 137 | * ks_datacont* dc - the new ks_datacont being added to the ks_list. 138 | * int index - the index at which the replacement will take place. Negative 139 | * values will wrap around. 140 | * 141 | * Returns: 142 | * int result - (-1) when either 'ls' or 'dc' are NULL, or when 'index' is OOB. 143 | * - (0) on success. 144 | */ 145 | int ks_list_replace_at(ks_list* ls, const ks_datacont* dc, int index); 146 | 147 | /* ------------------------------ 148 | * ks_list_replace_all(): 149 | * Replaces all occurrences of a specified ks_datacont value with a new ks_datacont value. 150 | * 151 | * Inputs: 152 | * ks_list* ls - the ks_list being operated on. 153 | * ks_datacont* old_dc - the original ks_datacont to be replaced. 154 | * ks_datacont* new_dc - the new ks_datacont replacing the orignal. 155 | * 156 | * Returns: 157 | * int result - (-1) when any of the params is NULL. 158 | * - >= (0) the number of replacements that occurred. 159 | * 160 | * Notes: 161 | * ks_dataconts that are equal to 'old_dc' are freed. A copy of 'new_dc' is created 162 | * for every replacement. 163 | */ 164 | int ks_list_replace_all(ks_list* ls, const ks_datacont* old_dc, 165 | const ks_datacont* new_dc); 166 | 167 | /* ------------------------- 168 | * ks_list_insert(): 169 | * Inserts a ks_datacont* at a location specified within a ks_list. 170 | * 171 | * Inputs: 172 | * ks_list* ls - the ks_list being operated on. 173 | * ks_datacont* dc - the ks_datacont being inserted. 174 | * int index - the location to insert the ks_datacont. Negative values 175 | * will wrap around. 176 | * 177 | * Returns: 178 | * int result - (-1) when either parameter is NULL, or when 'index' is OOB. 179 | * - (0) on success. 180 | */ 181 | int ks_list_insert(ks_list* ls, const ks_datacont* dc, int index); 182 | 183 | /* -------------------------- 184 | * ks_list_push(): 185 | * Inserts a ks_datacont* at the beginning of a ks_list. 186 | * 187 | * Inputs: 188 | * ks_list* ls - the list being operated on. 189 | * ks_datacont* dc - the ks_datacont being pushed. 190 | * 191 | * Returns: 192 | * int result - (-1) when either parameter is NULL. 193 | * - (0) on success. 194 | */ 195 | int ks_list_push(ks_list* ls, const ks_datacont* dc); 196 | 197 | /* --------------------------- 198 | * ks_list_pop(): 199 | * Removes and returns the ks_datacont located at the beginning of a ks_list. 200 | * 201 | * Inputs: 202 | * ks_list* ls - the list being operated on. 203 | * ks_datacont* dc - the ks_datacont being popped from beginning of ks_list. 204 | * 205 | * Returns: 206 | * ks_datacont* dc - (NULL) if 'ls' is NULL or empty. 207 | * - the ks_datacont located at the beginning of ks_list. 208 | */ 209 | ks_datacont* ks_list_pop(ks_list* ls); 210 | 211 | /* -------------------------- 212 | * ks_list_peek(): 213 | * Returns the ks_datacont located at the beginnning of the list. 214 | * 215 | * Inputs: 216 | * ks_list* ls - the list being operated on. 217 | * 218 | * Returns: 219 | * ks_datacont* dc - (NULL) if 'ls' is NULL or empty. 220 | * - a pointer to the ks_datacont located at the beginning of ks_list. 221 | */ 222 | const ks_datacont* ks_list_peek(const ks_list* ls); 223 | 224 | /* -------------------------- 225 | * ks_list_enqueue(): 226 | * Inserts a ks_datacont* at the beginning of a ks_list. 227 | * 228 | * Inputs: 229 | * ks_list* ls - the ks_list begin operated on. 230 | * ks_datacont* - the ks_datacont being inserted. 231 | * 232 | * Returns: 233 | * int result - (-1) when either parameter is NULL or when 'index' is OOB. 234 | * - (0) on success. 235 | */ 236 | int ks_list_enqueue(ks_list* ls, const ks_datacont* dc); 237 | 238 | /* -------------------------- 239 | * ks_list_dequeue(): 240 | * Removes and returns the ks_datacont located at the end of the ks_list. 241 | * 242 | * Inputs: 243 | * ks_list* ls - the ks_list being operated on. 244 | * 245 | * Returns: 246 | * ks_datacont* dc - (NULL) if 'ls' is NULL or empty. 247 | * - the ks_datacont located at the beginning of ks_list. 248 | */ 249 | ks_datacont* ks_list_dequeue(ks_list* ls); 250 | 251 | /* --------------------------- 252 | * ks_list_index(): 253 | * Returns the index of the first ks_datacont that matches the ks_datacont 'dc' param located within a ks_list. 254 | * 255 | * Inputs: 256 | * ks_list* ls - the ks_list being searched through. 257 | * ks_datacont* dc - the ks_datacont to search for within the ks_list. 258 | * 259 | * Returns: 260 | * int index - (-1) if the ks_datacont could not be found, or either param is NULL. 261 | * - >= (0) the index of the ks_datacont. 262 | * 263 | * Notes: 264 | * This function can also serve as a 'ks_list_contains' function. Example: 265 | * if (ks_list_index(ls, dc) >= 0) puts("Found it!"); 266 | */ 267 | int ks_list_index(const ks_list* ls, const ks_datacont* dc); 268 | 269 | /* ------------------------- 270 | * ks_list_get(): 271 | * Returns a pointer to a ks_datacont contained within a ks_list that is located at 'index'. 272 | * 273 | * Inputs: 274 | * ks_list* ls - the ks_list being operated on. 275 | * int index - the index used to locate the desired ks_datacont. Negative 276 | * values will wrap around. 277 | * 278 | * Returns: 279 | * ks_datacont* dc - (NULL) if the 'index' is OOB, or if either param is NULL. 280 | * - a pointer to the ks_datacont located at 'index'. 281 | * 282 | * Notes: 283 | * The ks_datacont returned by this function is a pointer to the original contained within the ks_list, so it should not 284 | * be deleted or modified by client code. 285 | */ 286 | const ks_datacont* ks_list_get(const ks_list* ls, int index); 287 | 288 | /* ---------------------------- 289 | * ks_list_count(): 290 | * Returns the number of occurrences of a specified ks_datacont value within a ks_list. 291 | * 292 | * Inputs: 293 | * ks_list* ls - the ks_list being operated on. 294 | * ks_datacont* dc - the ks_datacont to look for within the ks_list. 295 | * 296 | * Returns: 297 | * unsigned int num - (-1) when either param is NULL. 298 | * - >= (0) the number of occurrences of the value contained in 'dc'. 299 | */ 300 | unsigned int ks_list_count(const ks_list* ls, const ks_datacont* dc); 301 | 302 | /* ---------------------------- 303 | * ks_list_length(): 304 | * Returns the length of the ks_list. 305 | * 306 | * Inputs: 307 | * ks_list* ls - the ks_list be operated on. 308 | * 309 | * Returns: 310 | * unsigned int length - >= (0) the length of the ks_list. (0) when 'ls' is NULL. 311 | */ 312 | unsigned int ks_list_length(const ks_list* ls); 313 | 314 | #endif 315 | -------------------------------------------------------------------------------- /include/kylestructs/ks_listnode.h: -------------------------------------------------------------------------------- 1 | #ifndef _KS_LISTNODE_H_ 2 | #define _KS_LISTNODE_H_ 3 | 4 | #include "ks_types.h" 5 | 6 | /* ------------------- 7 | * ks_listnode_new(): 8 | * Creates a new ks_listnode* containing a ks_datacont*. 9 | * 10 | * Inputs: 11 | * ks_datacont* dc - the ks_datacont* to be held by the ks_listnode. 12 | * 13 | * Returns: 14 | * ks_listnode* ln - a ks_listnode*, (NULL) if 'dc' is NULL. 15 | */ 16 | ks_listnode* ks_listnode_new(const ks_datacont* dc); 17 | 18 | /* -------------------- 19 | * ks_listnode_delete(): 20 | * Deletes a ks_listnode and its ks_datacont* member. 21 | * 22 | * Inputs: 23 | * ks_listnode* ln - the ks_listnode* being deleted. 24 | * 25 | * Returns: 26 | * void 27 | * 28 | * Notes: 29 | * This function will not touch the other nodes that 'ln' might be connected to. It is 30 | * assumed that the user code has or will disconnect any connected nodes. 31 | */ 32 | void ks_listnode_delete(ks_listnode* ln); 33 | 34 | /* -------------------- 35 | * ks_listnode_copy(): 36 | * Creates a copy of a ks_listnode and its ks_datacont. 37 | * 38 | * Inputs: 39 | * ks_listnode* ln - the ks_listnode being copied. 40 | * 41 | * Returns: 42 | * ks_listnode* - a copy of the ks_listnode. 43 | * 44 | * Notes: 45 | * ks_listnode_copy() only copies 'ln' and its connected ks_datacont*, 46 | * but not any other connected ks_listnodes. 47 | */ 48 | ks_listnode* ks_listnode_copy(const ks_listnode* ln); 49 | 50 | /* ------------------- 51 | * ks_listnode_delete_all(): 52 | * Deletes a ks_listnode and all other connected nodes. 53 | * 54 | * Inputs: 55 | * ks_listnode* ln - the ks_listnode to be deleted. 56 | * 57 | * Returns: 58 | * void 59 | * 60 | * Notes: 61 | * This function will delete 'ln' and all nodes connected to it. If only part of a 62 | * list is to be deleted, it will have to be manually isolated, with it's 'next' 63 | * member set to NULL. 64 | */ 65 | void ks_listnode_delete_all(ks_listnode* ln); 66 | 67 | /* ---------------------- 68 | * ks_listnode_copy_all(): 69 | * Creates a copy of a ks_listnode and all of its connected nodes. 70 | * 71 | * Inputs: 72 | * ks_listnode* ln - the ks_listnode to be copied. 73 | * 74 | * Returns: 75 | * ks_listnode* - a copy of the ks_listnode. 76 | */ 77 | ks_listnode* ks_listnode_copy_all(const ks_listnode* ln); 78 | 79 | /* -------------------- 80 | * ks_listnode_add(): 81 | * Append a ks_datacont* to a ks_listnode chain. 82 | * 83 | * Inputs: 84 | * ks_listnode* ln - the ks_listnode to be added to. 85 | * ks_datacont* dc - the ks_datacont being added to the list. 86 | * 87 | * Returns: 88 | * int result - (-1) if either param is NULL. 89 | * - (0) on success. 90 | */ 91 | int ks_listnode_add(ks_listnode* ln, const ks_datacont* dc); 92 | 93 | /* --------------------- 94 | * ks_listnode_merge(): 95 | * Merges two ks_listnodes. 96 | * 97 | * Inputs: 98 | * ks_listnode* lna - the left half of new ks_listnode* chain. 99 | * ks_listnode* lnb - the right half of new ks_listnode* chain. 100 | * 101 | * Returns: 102 | * ks_listnode* - pointer to beginning of ks_listnode chain. 103 | * 104 | * Notes: 105 | * If one of the params is NULL, the non-NULL param will be returned. 106 | * If both are NULL, NULL will be returned. 107 | */ 108 | ks_listnode* ks_listnode_merge(ks_listnode* lna, ks_listnode* lnb); 109 | 110 | /* ----------------------- 111 | * ks_listnode_remove_by(): 112 | * Removes the first occurrence of a ks_datacont found within a chain of ks_listnodes. 113 | * 114 | * Inputs: 115 | * ks_listnode** ln - the ks_listnode being operated on. 116 | * ks_datacont* dc - the ks_datacont to be removed from the ks_listnode. 117 | * 118 | * Returns: 119 | * int result - (-1) if either param is NULL. 120 | * - (0) if the ks_datacont was not found. 121 | * - (1) if the ks_datacont was successfully removed. 122 | * 123 | * Notes: 124 | * This function may delete the ks_listnode reference passed to 'ln' if it is the node that contains the 125 | * 'dc' value being deleted. Because of this, a nested pointer must be passed into 'ln' so that 126 | * it can be set either to the next node in the list, or NULL if there are no remaining nodes. Also, 127 | * the ks_datacont being passed into this function is assumed to be deleted by the user code. The 'dc' 128 | * parameter will not be modified in any way by this function. 129 | */ 130 | int ks_listnode_remove_by(ks_listnode** ln, const ks_datacont* dc); 131 | 132 | /* ----------------------------- 133 | * ks_listnode_remove_at(): 134 | * Removes a ks_datacont at a specified location within a ks_listnode chain. 135 | * 136 | * Inputs: 137 | * ks_listnode** ln - the ks_listnode being operated on. 138 | * int index - the index at which the removal will take place. Negative 139 | * values will wrap around. 140 | * 141 | * Returns: 142 | * int result - (-1) when 'ln' is NULL, or when 'index' is OOB. 143 | * - (0) on success. 144 | * 145 | * Notes: 146 | * See ks_listnode_remove_by() notes, as they apply to this function as well. 147 | */ 148 | int ks_listnode_remove_at(ks_listnode** ln, int index); 149 | 150 | /* ------------------------ 151 | * ks_listnode_remove_all(): 152 | * Removes all occurrences of a specified ks_datacont value within a chain of ks_listnodes. 153 | * 154 | * Inputs: 155 | * ks_listnode** ln - the ks_listnode being operated on. 156 | * ks_datacont* dc - the ks_datacont being removed from the ks_listnode. 157 | * 158 | * Returns: 159 | * int result - (-1) if either param is NULL. 160 | * - >= (0) the number of nodes removed from the ks_listnode chain. 161 | * 162 | * Notes: 163 | * See ks_listnode_remove_by() notes, as they apply to this function as well. 164 | */ 165 | int ks_listnode_remove_all(ks_listnode** ln, const ks_datacont* dc); 166 | 167 | /* ----------------------------- 168 | * ks_listnode_replace_by(): 169 | * Replaces the first occurrence of a specified ks_datacont value with a new ks_datacont value. 170 | * 171 | * Inputs: 172 | * ks_listnode* ln - the ks_listnode being operated on. 173 | * ks_datacont* old_dc - the original ks_datacont to be replaced. 174 | * ks_datacont* new_dc - the new ks_datacont replacing the original. 175 | * 176 | * Returns: 177 | * int result - (-1) when any param is NULL, or when 'old_dc' could not be found. 178 | * - (0) on success. 179 | * 180 | * Notes: 181 | * The ks_datacont replacement 'new_dc' should not be deleted by the user code 182 | * UNLESS the replacement fails. It will be stored directly into the list. 183 | * The 'old_dc' parameter WILL always need to be deleted by the user code. 184 | */ 185 | int ks_listnode_replace_by(ks_listnode* ln, const ks_datacont* old_dc, 186 | const ks_datacont* new_dc); 187 | 188 | /* ----------------------------- 189 | * ks_listnode_replace_at(): 190 | * Replaces a ks_datacont at a specified location within a ks_listnode chain. 191 | * 192 | * Inputs: 193 | * ks_listnode* ln - the ks_listnode being operated on. 194 | * ks_datacont* dc - the new ks_datacont being added to the ks_listnode chain. 195 | * int index - the index at which the replacement will take place. Negative 196 | * values will wrap around. 197 | * 198 | * Returns: 199 | * int result - (-1) when either 'ln' or 'dc' are NULL, or when 'index' is OOB. 200 | * - (0) on success. 201 | * 202 | * Notes: 203 | * The ks_datacont replacement 'dc' should not be deleted by the user code. It will 204 | * be stored directly into the list. 205 | */ 206 | int ks_listnode_replace_at(ks_listnode* ln, const ks_datacont* dc, int index); 207 | 208 | /* ------------------------------ 209 | * ks_listnode_replace_all(): 210 | * Replaces all occurrences of a specified ks_datacont value with a new ks_datacont value. 211 | * 212 | * Inputs: 213 | * ks_listnode* ln - the ks_listnode being operated on. 214 | * ks_datacont* old_dc - the original ks_datacont to be replaced. 215 | * ks_datacont* new_dc - the new ks_datacont replacing the orignal. 216 | * 217 | * Returns: 218 | * int result - -1 when any of the params is NULL 219 | * - >= (0) the number of replacements that occurred. 220 | * 221 | * Notes: 222 | * See notes on ks_listnode_replace_by(). The same applies here. 223 | */ 224 | int ks_listnode_replace_all(ks_listnode* ln, const ks_datacont* old_dc, 225 | const ks_datacont* new_dc); 226 | 227 | /* ------------------------- 228 | * ks_listnode_insert(): 229 | * Inserts a ks_datacont* at a location specified in a chain of ks_listnodes. 230 | * 231 | * Inputs: 232 | * ks_listnode** ln - the ks_listnode being operated on. 233 | * ks_datacont* dc - the ks_datacont being inserted. 234 | * int index - the location to insert the ks_datacont. Negative values 235 | * will wrap around. 236 | * 237 | * Returns: 238 | * int result - (-1) when either parameter is NULL, or when 'index' is OOB. 239 | * - (0) on success. 240 | * 241 | * Notes: 242 | * In the event that a ks_datacont is being inserted at the beginning of a ks_listnode chain, 243 | * the reference to 'ln' will have to changed to the new 0th ks_listnode, which is why 244 | * 'ln' must be passed in as a nested pointer. 245 | */ 246 | int ks_listnode_insert(ks_listnode** ln, const ks_datacont* dc, int index); 247 | 248 | /* --------------------------- 249 | * ks_listnode_index(): 250 | * Returns the index of the first ks_datacont that matches the ks_datacont 'dc' param located within a group of connected ks_listnodes. 251 | * 252 | * Inputs: 253 | * ks_listnode* ln - the ks_listnode being searched through. 254 | * ks_datacont* dc - the ks_datacont to search for within the connected ks_listnodes. 255 | * 256 | * Returns: 257 | * int index - (-1) if the ks_datacont could not be found, or either param is NULL. 258 | * - >= (0) the index of the ks_datacont. 259 | * 260 | * Notes: 261 | * This function can also serve as a 'ks_listnode_contains' function. Example: 262 | * if (ks_listnode_index(ln, dc) >= 0) puts("Found it!"); 263 | */ 264 | int ks_listnode_index(const ks_listnode* ln, const ks_datacont* dc); 265 | 266 | /* ------------------------- 267 | * ks_listnode_get(): 268 | * Returns a pointer to a ks_datacont contained within a ks_listnode that is a specified number of nodes down the chain from 'ln'. 269 | * 270 | * Inputs: 271 | * ks_listnode* ln - the ks_listnode being operated on. 272 | * int index - the index used to locate the desired ks_datacont. Negative 273 | * values will wrap around. 274 | * 275 | * Returns: 276 | * ks_datacont* dc - (NULL) if the 'index' is OOB, or if either param is NULL. 277 | * - a pointer to the ks_datacont located at 'index'. 278 | * 279 | * Notes: 280 | * The ks_datacont returned by this function is a pointer to the original contained within the list, so it should not 281 | * be deleted or modified by client code. 282 | */ 283 | const ks_datacont* ks_listnode_get(const ks_listnode* ln, int index); 284 | 285 | /* ---------------------------- 286 | * ks_listnode_count(): 287 | * Returns the number of occurrences of a specified ks_datacont value within a ks_listnode chain. 288 | * 289 | * Inputs: 290 | * ks_listnode* ln - the ks_listnode being operated on. 291 | * ks_datacont* dc - the ks_datacont to look for within the list. 292 | * 293 | * Returns: 294 | * unsigned int num - (-1) when either param is NULL. 295 | * - >= (0) the number of ks_listnodes that contain the same value as 'dc'. 296 | */ 297 | unsigned int ks_listnode_count(const ks_listnode* ln, const ks_datacont* dc); 298 | 299 | /* ---------------------------- 300 | * ks_listnode_length(): 301 | * Returns the length of the list. 302 | * 303 | * Inputs: 304 | * ks_listnode* ln - the ks_listnode be operated on. 305 | * 306 | * Returns: 307 | * unsigned int length - >= (0) the length of the list. (0) when 'ln' is NULL. 308 | */ 309 | unsigned int ks_listnode_length(const ks_listnode* ln); 310 | 311 | #endif 312 | -------------------------------------------------------------------------------- /include/kylestructs/ks_treemap.h: -------------------------------------------------------------------------------- 1 | #ifndef _TREEMAP_H_ 2 | #define _TREEMAP_H_ 3 | 4 | #include "ks_types.h" 5 | 6 | /* ------------------------------------ 7 | * ks_treemap_new(): 8 | * Creates a new empty ks_treemap. 9 | * 10 | * Inputs: 11 | * void 12 | * 13 | * Returns: 14 | * ks_treemap* tm - an empty ks_treemap. 15 | */ 16 | ks_treemap* ks_treemap_new(); 17 | 18 | /* ---------------------------------- 19 | * ks_treemap_delete(): 20 | * Deletes a ks_treemap and all of its contents. 21 | * 22 | * Inputs: 23 | * ks_treemap* tm - the ks_treemap to be deleted 24 | * 25 | * Returns: 26 | * void 27 | */ 28 | void ks_treemap_delete(ks_treemap* tm); 29 | 30 | /* --------------------------------- 31 | * ks_treemap_copy(): 32 | * Creats a copy of a ks_treemap*. 33 | * 34 | * Inputs: 35 | * ks_treemap* tm - the ks_treemap to be copied. 36 | * 37 | * Returns: 38 | * ks_treemap* - a copy of 'tm'. 39 | */ 40 | ks_treemap* ks_treemap_copy(const ks_treemap* tm); 41 | 42 | /* ---------------------------------- 43 | * ks_treemap_add(): 44 | * Add a key/value pair to a ks_treemap. 45 | * 46 | * Inputs: 47 | * ks_treemap* tm - the ks_treemap to be added to 48 | * ks_datacont* key - the key 49 | * ks_datacont* value - the value that the key maps to 50 | * 51 | * Returns: 52 | * int result - (-1) if any params are NULL, or if 'key's ks_dataconttype is different from 53 | * the other ks_dataconts in the tree. 54 | * - (0) pair was added successfully. 55 | * - (1) 'key' already present, old key and value replaced. 56 | * 57 | * Notes: 58 | * - If the key-value pair is successfully added to the ks_treemap (0), the user code 59 | * must not delete or modify 'key' or 'value', otherwise undefined behavior could 60 | * ensue. If a key with the same value was already present (1), the old key and value 61 | * have been deleted and replaced by the new key and value. If the pair was not added 62 | * to the ks_treemap (-1), the user code is responsible for deleting both when they are 63 | * no longer needed. 64 | * 65 | * - The following types do not support comparison: KS_VOIDP, KS_LIST, KS_HASHSET, 66 | * KS_HASHMAP, KS_TREESET and KS_TREEMAP. This function will return -1 for these types. 67 | */ 68 | int ks_treemap_add(ks_treemap* tm, const ks_datacont* key, 69 | const ks_datacont* value); 70 | 71 | /* --------------------------- 72 | * ks_treemap_remove(): 73 | * Find key/value pair and delete it. 74 | * 75 | * Inputs: 76 | * ks_treemap* tm - the ks_treemap to be operated on 77 | * ks_datacont* key - the key to be removed 78 | * 79 | * Returns: 80 | * int result - (-1) if either param is NULL, or if 'key' could not be found. 81 | * - (0) pair removed successfully. 82 | * 83 | * Notes: 84 | * 'key' is not consumed by this procedure. It is only used to locate another ks_datacont containing 85 | * the same data. 86 | */ 87 | int ks_treemap_remove(ks_treemap* tm, const ks_datacont* key); 88 | 89 | /* --------------------------- 90 | * ks_treemap_get(): 91 | * Retrieves a value mapped by 'key' from a ks_treemap. 92 | * 93 | * Inputs: 94 | * ks_treemap* tm - the ks_treemap to be operated on 95 | * ks_datacont* key - the key to use to retrieve a value 96 | * 97 | * Returns: 98 | * ks_datacont* value - (NULL) when the key could not be found. 99 | * - the value mapped to by 'key'. 100 | * 101 | * Notes: 102 | * The ks_datacont returned by this function is a pointer to the original contained within the ks_treemap, 103 | * so it should not be deleted or modified by client code. 104 | * See notes on ks_treemap_remove(). 105 | */ 106 | const ks_datacont* ks_treemap_get(const ks_treemap* tm, const ks_datacont* key); 107 | 108 | /* -------------------------- 109 | * ks_treemap_get_key(): 110 | * Retrieves a key located at a specified index within a ks_treemap. 111 | * 112 | * Inputs: 113 | * ks_treemap* tm - the ks_treemap being operated on. 114 | * int index - the index of the key being retrieved. Negative values 115 | * will wrap around. 116 | * 117 | * Returns: 118 | * ks_datacont* key - (NULL) if 'index' is OOB, or if 'tm' is NULL. 119 | * - the key located at 'index'. 120 | * 121 | * Notes: 122 | * The ks_datacont returned by this function is a pointer to the original contained within the ks_treemap, 123 | * so it should not be deleted or modified by client code. 124 | */ 125 | const ks_datacont* ks_treemap_get_key(const ks_treemap* tm, int index); 126 | 127 | /* ---------------------------- 128 | * ks_treemap_count(): 129 | * Count the number of key-value pairs stored within a ks_treemap. 130 | * 131 | * Inputs: 132 | * ks_treemap* tm - the ks_treemap to be operated on 133 | * 134 | * Returns: 135 | * unsigned int result - >= (0) the number of pairs found in the ks_treemap, (0) if 'tm' is NULL.. 136 | */ 137 | unsigned int ks_treemap_count(const ks_treemap* tm); 138 | 139 | /* -------------------------- 140 | * ks_treemap_height(): 141 | * Calculate the maximum height of a ks_treemap. 142 | * 143 | * Inputs: 144 | * ks_treemap* tm - the ks_treemap to be operated on. 145 | * 146 | * Returns: 147 | * unsigned int height - >= (0) the height of the tree (0) if 'tm' is NULL. 148 | */ 149 | unsigned int ks_treemap_height(const ks_treemap* tm); 150 | 151 | /* -------------------------- 152 | * ks_treemap_balance(): 153 | * Balances a ks_treemap to ensure optimal performance. 154 | * 155 | * Inputs: 156 | * ks_treemap* tm - the ks_treemap being operated on. 157 | * 158 | * Returns: 159 | * void 160 | */ 161 | void ks_treemap_balance(ks_treemap* tm); 162 | 163 | #endif 164 | -------------------------------------------------------------------------------- /include/kylestructs/ks_treemapnode.h: -------------------------------------------------------------------------------- 1 | #ifndef _KS_TREEMAPNODE_H_ 2 | #define _KS_TREEMAPNODE_H_ 3 | 4 | #include "ks_types.h" 5 | 6 | /* ------------------------------------ 7 | * ks_treemapnode_new(): 8 | * Creates a new ks_treemapnode. 9 | * 10 | * Inputs: 11 | * ks_datacont* key - the key 12 | * ks_datacont* value - the value 13 | * 14 | * Returns: 15 | * ks_treemapnode* tmn - (NULL) if either of the parameters is NULL. 16 | * - a ks_treemapnode containing 'key' and 'value'. 17 | */ 18 | ks_treemapnode* ks_treemapnode_new(const ks_datacont* key, 19 | const ks_datacont* value); 20 | 21 | /* ---------------------------------- 22 | * ks_treemapnode_delete(): 23 | * Deletes a ks_treemapnode and its 'key' and 'value' members. 24 | * 25 | * Inputs: 26 | * ks_treemapnode* tmn - the ks_treemapnode to be deleted 27 | * 28 | * Returns: 29 | * void 30 | */ 31 | void ks_treemapnode_delete(ks_treemapnode* tmn); 32 | 33 | /* ---------------------------------- 34 | * ks_treemapnode_copy(): 35 | * Creates a copy of a treemapnode* and its ks_datacont*. 36 | * 37 | * Inputs: 38 | * ks_treempanode* tmn - the ks_treemapnode to be copied. 39 | * 40 | * Returns: 41 | * ks_treemapnode* - a copy of the ks_treemapnode*. 42 | * 43 | * Notes: 44 | * ks_treemapnode_copy() only copies the ks_treemapnode itself 45 | * and its ks_datacont key and value, but not any other connected 46 | * ks_treemapnodes. 47 | */ 48 | ks_treemapnode* ks_treemapnode_copy(const ks_treemapnode* tmn); 49 | 50 | /* ----------------------------------- 51 | * ks_treemapnode_delete_all(): 52 | * Deletes a ks_treemapnode, its 'key' and 'value' members, and recursively 53 | * deletes its 'right' and 'left' members. 54 | * 55 | * Inputs: 56 | * ks_treemapnode* tmn - the ks_treemapnode being deleted. 57 | * 58 | * Returns: 59 | * void 60 | */ 61 | void ks_treemapnode_delete_all(ks_treemapnode* tmn); 62 | 63 | /* ---------------------------------- 64 | * ks_treemapnode_copy_all(): 65 | * Creates a copy of a treemapnode*, its ks_datacont*, and any 66 | * connected ks_treemapnodes. 67 | * 68 | * Inputs: 69 | * ks_treempanode* tmn - the ks_treemapnode to be copied. 70 | * 71 | * Returns: 72 | * ks_treemapnode* - a copy of the ks_treemapnode*. 73 | */ 74 | ks_treemapnode* ks_treemapnode_copy_all(const ks_treemapnode* tmn); 75 | 76 | /* ---------------------------------- 77 | * ks_treemapnode_add(): 78 | * Add a key/value pair to a ks_treemapnode tree. 79 | * 80 | * Inputs: 81 | * ks_treemapnode* tmn - the treemap to be added to 82 | * ks_datacont* key - the key 83 | * ks_datacont* value - the value that the key maps to 84 | * 85 | * Returns: 86 | * int result - (-1) if any params are NULL. 87 | * - (0) pair added successfully 88 | * - (1) already contains pair, old key and value replaced. 89 | * 90 | * Notes: 91 | * If the key-value pair is successfully added to the ks_treemapnode (0), the user code 92 | * must not delete or modify 'key' or 'value', otherwise undefined behavior could 93 | * ensue. If a key with the same value was already present (1), the old key and value 94 | * have been deleted and replaced by the new key and value. If the pair was not added 95 | * to the ks_treemapnode (-1), the user code is responsible for deleting both when they are 96 | * no longer needed. 97 | */ 98 | int ks_treemapnode_add(ks_treemapnode* tmn, const ks_datacont* key, 99 | const ks_datacont* value); 100 | 101 | /* --------------------------- 102 | * ks_treemapnode_remove(): 103 | * Find key/value pair and delete it. 104 | * 105 | * Inputs: 106 | * ks_treemapnode** tmn - the ks_treemapnode to be operated on 107 | * ks_datacont* key - the key to be removed 108 | * 109 | * Returns: 110 | * int result - (-1) if either param is NULL, or 'key' could not be found. 111 | * - (0) pair removed successfully. 112 | * 113 | * Notes: 114 | * Because the key-value pair that is being removed could be located in the root node, 115 | * 'tmn' must be passed as a nested pointer so that it can be set to a different node, 116 | * or NULL if there are no nodes left after the removal. Also: 'key' is not consumed by 117 | * this procedure, it is only used to locate another ks_datacont containing the same data. 118 | */ 119 | int ks_treemapnode_remove(ks_treemapnode** tmn, const ks_datacont* key); 120 | 121 | /* --------------------------- 122 | * ks_treemapnode_get(): 123 | * Get the value from a ks_treemapnode by key. 124 | * 125 | * Inputs: 126 | * ks_treemapnode* tmn - the ks_treemapnode to be operated on. 127 | * ks_datacont* key - the key used to retrieve a value. 128 | * 129 | * Returns: 130 | * ks_datacont* value - (NULL) if either param is NULL, or if 'key' could not be found. 131 | * - the value mapped to by the key. 132 | * 133 | * Notes: 134 | * The ks_datacont returned by this function is a pointer to the original contained within 135 | * the treemap, so it should not be deleted or modified by client code. Also: 136 | * 'key' is not consumed by this procedure, it is only used to locate another ks_datacont 137 | * containing the same data. 138 | */ 139 | const ks_datacont* ks_treemapnode_get(const ks_treemapnode* tmn, 140 | const ks_datacont* key); 141 | 142 | /* -------------------------- 143 | * ks_treemapnode_get_key(): 144 | * Retrieves a key located at a specified index within the ks_treemapnode. 145 | * 146 | * Inputs: 147 | * ks_treemapnode* tmn - the ks_treemapnode being retrieved from. 148 | * int index - the index of the key being retrieved. Negative values 149 | * will wrap around. 150 | * 151 | * Returns: 152 | * ks_datacont* key - (NULL) if 'index' is OOB, or if 'tmn' is NULL. 153 | * - the key located at 'index'. 154 | * Notes: 155 | * The ks_datacont returned by this function is a pointer to the original contained within 156 | * the list, so it should not be deleted or modified by client code. 157 | */ 158 | const ks_datacont* ks_treemapnode_get_key(const ks_treemapnode* tmn, int index); 159 | 160 | /* ---------------------------- 161 | * ks_treemapnode_count(): 162 | * Count the number of key/value pairs stored within a ks_treemapnode. 163 | * 164 | * Inputs: 165 | * ks_treemapnode* tmn - the ks_treemapnode to be operated on. 166 | * 167 | * Returns: 168 | * unsigned int - >= (0) the number of pairs found in the ks_treemapnode, (0) if 'tmn' is NULL. 169 | */ 170 | unsigned int ks_treemapnode_count(const ks_treemapnode* tmn); 171 | 172 | /* -------------------------- 173 | * ks_treemapnode_height(): 174 | * Calculate the maximum height of a ks_treemapnode tree. 175 | * 176 | * Inputs: 177 | * ks_treemapnode* tmn - the ks_treemapnode to be operated on. 178 | * 179 | * Returns: 180 | * unsigned int - >= (0) the height of the tree, (0) if 'tmn' is NULL. 181 | */ 182 | unsigned int ks_treemapnode_height(const ks_treemapnode* tmn); 183 | 184 | /* -------------------------- 185 | * ks_treemapnode_balance(): 186 | * Balances a ks_treemapnode* tree to ensure optimal performance. 187 | * 188 | * Inputs: 189 | * ks_treemapnode* tmn - the root of the ks_treemapnode being balanced. 190 | * 191 | * Returns: 192 | * ks_treemapnode* - a balanced treemapnode*. 193 | */ 194 | ks_treemapnode* ks_treemapnode_balance(ks_treemapnode* tmn); 195 | 196 | #endif 197 | -------------------------------------------------------------------------------- /include/kylestructs/ks_treeset.h: -------------------------------------------------------------------------------- 1 | #ifndef _KS_TREESET_H_ 2 | #define _KS_TREESET_H_ 3 | 4 | #include "ks_types.h" 5 | 6 | /* --------------------- 7 | * ks_treeset_new(): 8 | * Creates a new empty ks_treeset. 9 | * 10 | * Inputs: 11 | * void 12 | * 13 | * Returns: 14 | * ks_treeset* ts - an empty ks_treeset. 15 | */ 16 | ks_treeset* ks_treeset_new(); 17 | 18 | /* ---------------------- 19 | * ks_treeset_delete(): 20 | * Deletes a ks_treeset and all of its contents. 21 | * 22 | * Inputs: 23 | * ks_treeset* ts - the ks_treeset to be deleted. 24 | * 25 | * Returns: 26 | * void 27 | */ 28 | void ks_treeset_delete(ks_treeset* ts); 29 | 30 | /* ----------------------- 31 | * ks_treeset_copy(): 32 | * Creates a copy of a ks_treeset and all of its contents. 33 | * 34 | * Inputs: 35 | * ks_treeset* ts - the ks_treeset to be copied. 36 | * 37 | * Returns: 38 | * ks_treesetnode - a copy of the treesetnode. 39 | */ 40 | ks_treeset* ks_treeset_copy(const ks_treeset* ts); 41 | 42 | /* ---------------------- 43 | * ks_treeset_add(): 44 | * Adds a ks_datacont to a ks_treeset. 45 | * 46 | * Inputs: 47 | * ks_treeset* ts - the ks_treeset being added to. 48 | * ks_datacont* dc - the ks_datacont being added to the ks_treeset. 49 | * 50 | * Returns: 51 | * int result - (-1) if either param is NULL, or if 'dc' is not comparable to the other 52 | * ks_dataconts in the ks_treeset (e.g. if 'dc' is of type CHAR and the others are INT). 53 | * - (0) 'dc' was successfully added to 'ts'. 54 | * - (1) 'dc' is already present in the ks_treeset and was not added. 55 | * 56 | * Notes: 57 | * - If 'dc' is successfully stored into the set, 'dc' should not be deleted by the user code, 58 | * as it will be directly stored into the tree. Otherwise a seg fault is likely to occur. 59 | * In the event that a value matching 'dc' is already present in the ks_treeset, 'dc' will not 60 | * be stored, and 'dc' must be deleted by the user code. 61 | * 62 | * - The following types do not support comparison: KS_VOIDP, KS_LIST, KS_HASHSET, 63 | * KS_HASHMAP, KS_TREESET and KS_TREEMAP. This function will return -1 for these types. 64 | */ 65 | int ks_treeset_add(ks_treeset* ts, const ks_datacont* dc); 66 | 67 | /* ------------------------------ 68 | * ks_treeset_remove_by(): 69 | * Remove a ks_datacont from a ks_treeset that contains a value matching the value of the 'dc' 70 | * argument. 71 | * 72 | * Inputs: 73 | * ks_treeset* ts - the ks_treeset being removed from. 74 | * ks_datacont* dc - the ks_datacont value to remove from the ks_treeset. 75 | * 76 | * Returns: 77 | * int result - (-1) if either param is NULL, or if 'dc' could not be found. 78 | * - (0) on success. 79 | */ 80 | int ks_treeset_remove_by(ks_treeset* ts, const ks_datacont* dc); 81 | 82 | /* ---------------------------- 83 | * ks_treeset_remove_at(): 84 | * Remove a ks_datacont from a ks_treeset at a specified index. 85 | * 86 | * Inputs: 87 | * ks_treeset* ts - the ks_treeset being removed from. 88 | * int index - the index of the ks_datacont to be removed. 89 | * 90 | * Returns: 91 | * int result - (-1) if 'index' is OOB or if 'ts' is NULL. 92 | * - >= (0) on success. 93 | */ 94 | int ks_treeset_remove_at(ks_treeset* ts, int index); 95 | 96 | /* --------------------------- 97 | * ks_treeset_index(): 98 | * Returns the index of a given ks_datacont value. 99 | * 100 | * Inputs: 101 | * ks_treeset* ts - the ks_treeset being searched. 102 | * ks_datacont* dc - the ks_datacont to search for within 'ts'. 103 | * 104 | * Returns: 105 | * int index - (-1) if 'dc' could not be found, or if either param is NULL. 106 | * - >= (0) the index of 'dc'. Negative values will wrap around. 107 | * 108 | * Notes: 109 | * This function should not be used to determine if a ks_datacont is present within 110 | * a ks_treeset*. Instead ks_treeset_contains() should be used as it is a much faster 111 | * operation than ks_treeset_index(). 112 | */ 113 | int ks_treeset_index(const ks_treeset* ts, const ks_datacont* dc); 114 | 115 | /* ----------------------------- 116 | * ks_treeset_contains(): 117 | * Searches for a specified ks_datacont value within a ks_treeset. 118 | * 119 | * Inputs: 120 | * ks_treeset* ts - the ks_treeset being searched. 121 | * ks_datacont* dc - the ks_datacont to search for within 'ts'. 122 | * 123 | * Returns: 124 | * unsigned int result - (0) if 'dc' could not be found, or if either param is NULL. 125 | * - (1) if 'dc' was found. 126 | */ 127 | unsigned int ks_treeset_contains(const ks_treeset* ts, const ks_datacont* dc); 128 | 129 | /* --------------------------- 130 | * ks_treeset_get(): 131 | * Returns a ks_datacont located at a specified index within a ks_treeset. 132 | * 133 | * Inputs: 134 | * ks_treeset* ts - the ks_treeset* being operated on. 135 | * int index - the index of the ks_datacont to being retrieved. Negative values 136 | * will wrap around. 137 | * 138 | * Returns: 139 | * ks_datacont* dc - (NULL) if 'index' is OOB, or if 'tsn' is NULL. 140 | * - the ks_datacont located at 'index'. 141 | * 142 | * Notes: 143 | * The ks_datacont returned by this function is a pointer to the original contained within the ks_treeset, 144 | * so it should not be deleted or modified by client code. 145 | */ 146 | const ks_datacont* ks_treeset_get(const ks_treeset* tsn, int index); 147 | 148 | /* ------------------------- 149 | * ks_treeset_count(): 150 | * Returns the number of ks_dataconts stored in a ks_treeset. 151 | * 152 | * Inputs: 153 | * ks_treeset* ts - the ks_treeset being operated on. 154 | * 155 | * Returns: 156 | * unsigned int count - >= (0) the number of nodes in 'ts', (0) when 'ts' is NULL. 157 | */ 158 | unsigned int ks_treeset_count(const ks_treeset* ts); 159 | 160 | /* -------------------------- 161 | * ks_treeset_height(): 162 | * Calculates the height of the ks_treeset and all connected nodes. 163 | * 164 | * Inputs: 165 | * ks_treeset* ts - the ks_treeset being operated on. 166 | * 167 | * Returns: 168 | * unsigned int height - >= (0) the height of the ks_treeset, (0) when 'ts' is NULL. 169 | */ 170 | unsigned int ks_treeset_height(const ks_treeset* ts); 171 | 172 | /* -------------------------- 173 | * ks_treeset_balance(): 174 | * Balances a ks_treeset tree to ensure optimal performance. 175 | * 176 | * Inputs: 177 | * ks_treeset* tsn - the ks_treeset being balanced. 178 | * 179 | * Returns: 180 | * void 181 | */ 182 | void ks_treeset_balance(ks_treeset* ts); 183 | 184 | #endif 185 | -------------------------------------------------------------------------------- /include/kylestructs/ks_treesetnode.h: -------------------------------------------------------------------------------- 1 | #ifndef _KS_TREESETNODE_H_ 2 | #define _KS_TREESETNODE_H_ 3 | 4 | #include "ks_types.h" 5 | 6 | /* --------------------- 7 | * ks_treesetnode_new(): 8 | * Creates a new ks_treesetnode* containing a specified ks_datacont value. 9 | * 10 | * Inputs: 11 | * ks_datacont* dc - the ks_datacont to be contained by the new ks_treesetnode*. 12 | * 13 | * Returns: 14 | * ks_treesetnode* tsn - NULL if 'dc' is NULL. 15 | * - a ks_treesetnode* containing 'dc'. 16 | * 17 | * Notes: 18 | * The 'right' and 'left' ks_treesetnode members will be NULL. 19 | */ 20 | ks_treesetnode* ks_treesetnode_new(const ks_datacont* dc); 21 | 22 | /* ----------------------- 23 | * ks_treesetnode_delete(): 24 | * Deletes a ks_treesetnode and its ks_datacont* value. 25 | * 26 | * Inputs: 27 | * ks_treesetnode* tsn - the ks_treesetnode being deleted. 28 | * 29 | * Returns: 30 | * void 31 | * 32 | * Notes: 33 | * This function does not delete the 'left' and 'right' nodes 34 | * that might be connected to 'tsn'. 35 | */ 36 | void ks_treesetnode_delete(ks_treesetnode* tsn); 37 | 38 | /* ----------------------- 39 | * ks_treesetnode_copy(): 40 | * Creates a copy of a ks_treesetnode and its ks_datacont. 41 | * 42 | * Inputs: 43 | * ks_treesetnode* tsn - the ks_treesetnode being copy. 44 | * 45 | * Returns: 46 | * ks_treesetnode* - a copy of 'tsn'. 47 | * 48 | * Notes: 49 | * ks_treesetnode_copy() will only copy 'tsn' and its ks_datacont, 50 | * but not any other connected ks_treesetnodes. 51 | */ 52 | ks_treesetnode* ks_treesetnode_copy(const ks_treesetnode* tsn); 53 | 54 | /* -------------------------- 55 | * ks_treesetnode_delete_all(): 56 | * Deletes a ks_treesetnode and all nodes connected to it. 57 | * 58 | * Inputs: 59 | * ks_treesetnode* tsn - the ks_treesetnode being deleted. 60 | * 61 | * Returns: 62 | * void 63 | */ 64 | void ks_treesetnode_delete_all(ks_treesetnode* tsn); 65 | 66 | /* ---------------------------- 67 | * ks_treesetnode_copy_all(): 68 | * Creates a copy of a ks_treesetnode and all nodes connected to it. 69 | * 70 | * Inputs: 71 | * ks_treesetnode* tsn - the ks_treesetnode being copied. 72 | * 73 | * Returns: 74 | * ks_treesetnode* - a copy of 'tsn'. 75 | */ 76 | ks_treesetnode* ks_treesetnode_copy_all(const ks_treesetnode* tsn); 77 | 78 | /* ----------------------- 79 | * ks_treesetnode_add(): 80 | * Adds a ks_datacont* to a collection of other ks_treesetnodes. The ks_datacont is 81 | * compared with the ks_dataconts contained within the linked ks_treesetnodes, and is placed 82 | * in a new ks_treesetnode* based on the ks_datacont value that it contains. 83 | * 84 | * Inputs: 85 | * ks_treesetnode* tsn - the ks_treesetnode being added to. 86 | * ks_datacont* dc - the ks_datacont being added to 'tsn'. 87 | * 88 | * Returns: 89 | * int result - (-1) if either param is NULL, or if 'dc' is not comparable to the other 90 | * ks_dataconts in 'tsn' (e.g. if 'dc' is of type CHAR and the others are INT). 91 | * - (0) 'dc' was successfully added to 'tsn'. 92 | * - (1) 'dc' is already present in the ks_treesetnode and was not added. 93 | * 94 | * Notes: 95 | * If 'dc' is succefully stored into the set, 'dc' should not be deleted by the user code, 96 | * as it will be directly stored into the tree. Otherwise a seg fault is likely to occur. 97 | * In the event that a value matching 'dc' is already present in the treeset, 'dc' is not 98 | * stored in the set. Because of this, it is up to the user code to delete 'dc' if necessary. 99 | */ 100 | int ks_treesetnode_add(ks_treesetnode* tsn, const ks_datacont* dc); 101 | 102 | /* ---------------------------- 103 | * ks_treesetnode_remove_by(): 104 | * Remove a node contained within the ks_treesetnode* parameter that matches the 105 | * ks_datacont* parameter. 106 | * 107 | * Inputs: 108 | * ks_treesetnode** tsn - remove ks_treesetnode from this root node. 109 | * ks_datacont* dc - remove ks_treesetnode that contains the same value 110 | * as this data container. 111 | * 112 | * Returns: 113 | * int result - (-1) if 'dc' could not be found, or if either param is NULL. 114 | * - (0) on success. 115 | * 116 | * Notes: 117 | * Because the ks_datacont that is being removed might be located in the root node, 118 | * 'tsn' must be passed as a nested pointer so that it can be set to a different 119 | * node, or NULL if there are no nodes left after the removal. 120 | */ 121 | int ks_treesetnode_remove_by(ks_treesetnode** tsn, const ks_datacont* dc); 122 | 123 | /* --------------------------- 124 | * ks_treesetnode_remove_at(): 125 | * Remove a ks_datacont* located at a specified index within the set. 126 | * 127 | * Inputs: 128 | * ks_treesetnode** tsn - the ks_treesetnode from which to remove a ks_datacont 129 | * int index - the index of the ks_datacont to be removed from 'tsn'. Negative 130 | * values will wrap around. 131 | * 132 | * Returns: 133 | * int result - (-1) if 'index' is OOB, or if 'tsn' is NULL. 134 | * - (0) on success. 135 | * 136 | * Notes: 137 | * See notes for ks_treesetnode_remove_by(). 138 | */ 139 | int ks_treesetnode_remove_at(ks_treesetnode** tsn, const int index); 140 | 141 | /* ------------------------- 142 | * ks_treesetnode_index(): 143 | * Returns the index of a given ks_datacont value. 144 | * 145 | * Inputs: 146 | * ks_treesetnode* tsn - the ks_treesetnode being searched. 147 | * ks_datacont* dc - the ks_datacont to search for within 'tsn'. 148 | * 149 | * Returns: 150 | * int index - (-1) if 'dc' could not be found, or if either param is NULL. 151 | * - >= (0) the index of 'dc'. 152 | * 153 | * Notes: 154 | * This function should not be used to determine if a ks_datacont is present within 155 | * a ks_treesetnode*. Instead ks_treesetnode_contains() should be used as it is a much faster 156 | * operation than ks_treesetnode_index(). 157 | */ 158 | int ks_treesetnode_index(const ks_treesetnode* tsn, const ks_datacont* dc); 159 | 160 | /* -------------------------- 161 | * ks_treesetnode_contains(): 162 | * Searches for a ks_treesetnode that contains a value matching 'dc'. 163 | * 164 | * Inputs: 165 | * ks_treesetnode* tsn - the ks_treesetnode* being operated on. 166 | * ks_datacont* dc - the ks_datacont value to look for within 'tsn'. 167 | * 168 | * Returns: 169 | * unsigned int result - (0) if 'dc' could not be found, or if either param is NULL. 170 | * - (1) if 'dc' was found. 171 | */ 172 | unsigned int ks_treesetnode_contains(const ks_treesetnode* tsn, 173 | const ks_datacont* dc); 174 | 175 | /* --------------------------- 176 | * ks_treesetnode_get(): 177 | * Returns a ks_datacont located at a specified index within the set. 178 | * 179 | * Inputs: 180 | * ks_treesetnode* tsn - the ks_treesetnode* being operated on. 181 | * int index - the index of the ks_datacont to being retrieved. Negative values 182 | * will wrap around. 183 | * 184 | * Returns: 185 | * ks_datacont* dc - (NULL) if 'index' is OOB, or if 'tsn' is NULL. 186 | * - the ks_datacont located at 'index'. 187 | * Notes: 188 | * The ks_datacont returned by this function is a pointer to the original contained within 189 | * the treeset, so it should not be deleted or modified by client code. 190 | */ 191 | const ks_datacont* ks_treesetnode_get(const ks_treesetnode* tsn, int index); 192 | 193 | /* ------------------------- 194 | * ks_treesetnode_count(): 195 | * Returns the number of nodes connected to a ks_treesetnode* (including itself). 196 | * 197 | * Inputs: 198 | * ks_treesetnode* tsn - the ks_treesetnode being operated on. 199 | * 200 | * Returns: 201 | * unsigned int count - >= (0) the number of nodes in 'tsn', (0) when 'tsn' is NULL. 202 | */ 203 | unsigned int ks_treesetnode_count(const ks_treesetnode* tsn); 204 | 205 | /* -------------------------- 206 | * ks_treesetnode_height(): 207 | * Calculates the height of the ks_treesetnode and all connected nodes. 208 | * 209 | * Inputs: 210 | * ks_treesetnode* tsn - the ks_treesetnode being operated on. 211 | * 212 | * Returns: 213 | * unsigned int height - >= (0) the height of the ks_treesetnode, (0) when 'tsn' is NULL. 214 | */ 215 | unsigned int ks_treesetnode_height(const ks_treesetnode* tsn); 216 | 217 | /* -------------------------- 218 | * ks_treesetnode_balance(): 219 | * Balances a ks_treesetnode* tree to ensure optimal performance. 220 | * 221 | * Inputs: 222 | * ks_treesetnode* tsn - the root of the ks_treesetnode being balanced. 223 | * 224 | * Returns: 225 | * ks_treesetnode* - a balanced treesetnode*. 226 | */ 227 | ks_treesetnode* ks_treesetnode_balance(ks_treesetnode* tsn); 228 | 229 | #endif 230 | -------------------------------------------------------------------------------- /include/kylestructs/ks_types.h: -------------------------------------------------------------------------------- 1 | #ifndef _KS_TYPES_H_ 2 | #define _KS_TYPES_H_ 3 | 4 | #include 5 | 6 | enum ks_comparison { KS_LESSTHAN, KS_EQUAL, KS_GREATERTHAN, KS_CANTCOMPARE }; 7 | 8 | enum ks_datatype { 9 | KS_CHAR, 10 | KS_SHORT, 11 | KS_INT, 12 | KS_LL, 13 | KS_FLOAT, 14 | KS_DOUBLE, 15 | 16 | KS_UCHAR, 17 | KS_USHORT, 18 | KS_UINT, 19 | KS_ULL, 20 | 21 | KS_VOIDP, 22 | KS_CHARP, 23 | KS_SHORTP, 24 | KS_INTP, 25 | KS_LLP, 26 | KS_FLOATP, 27 | KS_DOUBLEP, 28 | 29 | KS_UCHARP, 30 | KS_USHORTP, 31 | KS_UINTP, 32 | KS_ULLP, 33 | 34 | KS_LIST, 35 | KS_TREESET, 36 | KS_HASHSET, 37 | KS_TREEMAP, 38 | KS_HASHMAP 39 | }; 40 | 41 | typedef struct ks_datacont ks_datacont; 42 | 43 | typedef struct ks_listnode ks_listnode; 44 | typedef struct ks_list ks_list; 45 | 46 | typedef struct ks_treesetnode ks_treesetnode; 47 | typedef struct ks_treeset ks_treeset; 48 | typedef struct ks_hashset ks_hashset; 49 | 50 | typedef struct ks_treemapnode ks_treemapnode; 51 | typedef struct ks_treemap ks_treemap; 52 | typedef struct ks_hashmap ks_hashmap; 53 | 54 | typedef struct ks_iterator ks_iterator; 55 | 56 | struct ks_datacont { 57 | enum ks_datatype type; 58 | size_t size; 59 | union { 60 | char c; 61 | short s; 62 | int i; 63 | long long ll; 64 | float f; 65 | double d; 66 | 67 | unsigned char uc; 68 | unsigned short us; 69 | unsigned int ui; 70 | unsigned long long ull; 71 | 72 | void* vp; 73 | char* cp; 74 | short* sp; 75 | int* ip; 76 | long long* llp; 77 | float* fp; 78 | double* dp; 79 | 80 | unsigned char* ucp; 81 | unsigned short* usp; 82 | unsigned int* uip; 83 | unsigned long long* ullp; 84 | 85 | ks_list* ls; 86 | ks_treeset* ts; 87 | ks_hashset* hs; 88 | ks_treemap* tm; 89 | ks_hashmap* hm; 90 | }; 91 | }; 92 | 93 | struct ks_listnode { 94 | ks_datacont* dc; 95 | ks_listnode* next; 96 | }; 97 | 98 | struct ks_list { 99 | ks_listnode* head; 100 | }; 101 | 102 | struct ks_treesetnode { 103 | ks_datacont* dc; 104 | ks_treesetnode* right; 105 | ks_treesetnode* left; 106 | }; 107 | 108 | struct ks_treeset { 109 | ks_treesetnode* root; 110 | }; 111 | 112 | struct ks_hashset { 113 | enum ks_datatype type; 114 | 115 | unsigned int num_buckets; 116 | 117 | ks_treeset** buckets; 118 | }; 119 | 120 | struct ks_treemapnode { 121 | ks_datacont* key; 122 | ks_datacont* value; 123 | ks_treemapnode* left; 124 | ks_treemapnode* right; 125 | }; 126 | 127 | struct ks_treemap { 128 | ks_treemapnode* root; 129 | }; 130 | 131 | struct ks_hashmap { 132 | enum ks_datatype type; 133 | 134 | unsigned int num_buckets; 135 | 136 | ks_treemap** buckets; 137 | }; 138 | 139 | struct ks_iterator { 140 | enum ks_datatype type; 141 | int size; 142 | int index; 143 | void* parent; 144 | ks_listnode* curr; 145 | }; 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /lint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | clang-tidy ./include/kylestructs.h ./include/kylestructs/*.h src/*.c tests/*.c -- -I./include 3 | exit $? 4 | -------------------------------------------------------------------------------- /runtests.sh: -------------------------------------------------------------------------------- 1 | 2 | ERRTITLE="TESTS FAILED:" 3 | FAILED="" 4 | 5 | TESTBIN="testbin" 6 | 7 | echo ============================== 8 | echo ---------------------------- 9 | echo Running all test suites... 10 | 11 | for TESTFILE in $(ls $TESTBIN) 12 | do 13 | ./$TESTBIN/$TESTFILE 14 | if [ $? != 0 ] 15 | then 16 | FAILED="${FAILED}${TESTFILE}\n" 17 | fi 18 | done 19 | 20 | echo Done. 21 | echo ---------------------------- 22 | echo ============================== 23 | 24 | 25 | if [ "$FAILED" != "" ] 26 | then 27 | echo $ERRTITLE 28 | printf $FAILED 29 | exit 1 30 | fi 31 | 32 | exit 0 33 | 34 | 35 | -------------------------------------------------------------------------------- /samples/demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main() 7 | { 8 | ks_hashmap* phonebook = ks_hashmap_new(KS_CHARP, 10); 9 | const ks_datacont* number_dc; 10 | const ks_datacont* name_dc; 11 | 12 | char number[30] = {0}; 13 | char name[30] = {0}; 14 | 15 | printf("Enter a name followed by a 10-digit phone number:\n"); 16 | 17 | while (scanf("%s %s", name, number) != -1) 18 | { 19 | number_dc = ks_datacont_new(number, KS_CHARP, strlen(number)); 20 | name_dc = ks_datacont_new(name, KS_CHARP, strlen(name)); 21 | 22 | if (ks_hashmap_add(phonebook, number_dc, name_dc) == 1) 23 | printf("Replaced existing number %s.\n", number); 24 | 25 | memset(number, 0, 30); 26 | memset(name, 0, 30); 27 | } 28 | 29 | int count = ks_hashmap_count(phonebook); 30 | 31 | for (int i = 0; i < count; i++) 32 | { 33 | number_dc = ks_hashmap_get_key(phonebook, i); 34 | name_dc = ks_hashmap_get(phonebook, number_dc); 35 | 36 | printf("%s => %s\n", number_dc->cp, name_dc->cp); 37 | } 38 | 39 | ks_hashmap_delete(phonebook); 40 | } 41 | -------------------------------------------------------------------------------- /samples/inheritance_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krglaws/KyleStructs/afce01099a915655501a167c567f8934c18b5d92/samples/inheritance_graph.png -------------------------------------------------------------------------------- /samples/project_diagram.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | labelloc="t"; 3 | label = "KyleStructs 'Inheritance' Graph"; 4 | 5 | subgraph cluster0 { 6 | label = "Tier 1"; 7 | color = blue; 8 | ks_datacont; 9 | } 10 | 11 | subgraph cluster1 { 12 | label = "Tier 2"; 13 | color = blue; 14 | ks_treemapnode; 15 | ks_treesetnode; 16 | ks_listnode; 17 | } 18 | 19 | subgraph cluster2 { 20 | label = "Tier 3"; 21 | color = blue; 22 | ks_treemap; 23 | ks_treeset; 24 | ks_list; 25 | } 26 | 27 | subgraph cluster3 { 28 | label = "Tier 4"; 29 | color = blue; 30 | ks_hashmap; 31 | ks_hashset; 32 | } 33 | 34 | ks_datacont -> ks_treemapnode; 35 | ks_datacont -> ks_treesetnode; 36 | ks_datacont -> ks_listnode; 37 | 38 | ks_treemapnode -> ks_treemap; 39 | ks_treesetnode -> ks_treeset; 40 | ks_listnode -> ks_list; 41 | 42 | ks_treemap -> ks_hashmap; 43 | ks_treeset -> ks_hashset; 44 | } 45 | -------------------------------------------------------------------------------- /src/ks_datacont.c: -------------------------------------------------------------------------------- 1 | #include "kylestructs/ks_datacont.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "kylestructs/ks_hashmap.h" 8 | #include "kylestructs/ks_hashset.h" 9 | #include "kylestructs/ks_list.h" 10 | #include "kylestructs/ks_listnode.h" 11 | #include "kylestructs/ks_treemap.h" 12 | #include "kylestructs/ks_treemapnode.h" 13 | #include "kylestructs/ks_treeset.h" 14 | #include "kylestructs/ks_treesetnode.h" 15 | #include "kylestructs/ks_types.h" 16 | 17 | ks_datacont* ks_datacont_new(const void* data, enum ks_datatype dct, 18 | size_t size) { 19 | if (data == NULL) { 20 | return NULL; 21 | } 22 | 23 | if (size == 0 && dct != KS_CHARP) { 24 | return NULL; 25 | } 26 | 27 | ks_datacont* dc = malloc(sizeof(ks_datacont)); 28 | dc->type = dct; 29 | dc->size = size; 30 | 31 | switch (dct) { 32 | case KS_CHAR: 33 | dc->c = *((char*)data); 34 | break; 35 | case KS_SHORT: 36 | dc->s = *((short*)data); 37 | break; 38 | case KS_INT: 39 | dc->i = *((int*)data); 40 | break; 41 | case KS_LL: 42 | dc->ll = *((long long*)data); 43 | break; 44 | case KS_FLOAT: 45 | dc->f = *((float*)data); 46 | break; 47 | case KS_DOUBLE: 48 | dc->d = *((double*)data); 49 | break; 50 | case KS_UCHAR: 51 | dc->uc = *((unsigned char*)data); 52 | break; 53 | case KS_USHORT: 54 | dc->us = *((unsigned short*)data); 55 | break; 56 | case KS_UINT: 57 | dc->ui = *((unsigned int*)data); 58 | break; 59 | case KS_ULL: 60 | dc->ull = *((unsigned long long*)data); 61 | break; 62 | case KS_VOIDP: 63 | dc->vp = (void*)data; 64 | break; 65 | case KS_CHARP: 66 | dc->cp = calloc(1, (sizeof(char) * size) + 1); 67 | memcpy(dc->cp, data, sizeof(char) * size); 68 | break; 69 | case KS_SHORTP: 70 | dc->sp = malloc(sizeof(short) * size); 71 | memcpy(dc->sp, data, sizeof(short) * size); 72 | break; 73 | case KS_INTP: 74 | dc->ip = malloc(sizeof(int) * size); 75 | memcpy(dc->ip, data, sizeof(int) * size); 76 | break; 77 | case KS_LLP: 78 | dc->llp = malloc(sizeof(long long) * size); 79 | memcpy(dc->llp, data, sizeof(long long) * size); 80 | break; 81 | case KS_FLOATP: 82 | dc->fp = malloc(sizeof(float) * size); 83 | memcpy(dc->fp, data, sizeof(float) * size); 84 | break; 85 | case KS_DOUBLEP: 86 | dc->dp = malloc(sizeof(double) * size); 87 | memcpy(dc->dp, data, sizeof(double) * size); 88 | break; 89 | case KS_UCHARP: 90 | dc->ucp = malloc(sizeof(unsigned char) * size); 91 | memcpy(dc->ucp, data, sizeof(char) * size); 92 | break; 93 | case KS_USHORTP: 94 | dc->usp = malloc(sizeof(unsigned short) * size); 95 | memcpy(dc->usp, data, sizeof(short) * size); 96 | break; 97 | case KS_UINTP: 98 | dc->uip = malloc(sizeof(unsigned int) * size); 99 | memcpy(dc->uip, data, sizeof(int) * size); 100 | break; 101 | case KS_ULLP: 102 | dc->ullp = malloc(sizeof(unsigned long long) * size); 103 | memcpy(dc->ullp, data, sizeof(long long) * size); 104 | break; 105 | case KS_LIST: 106 | dc->ls = (ks_list*)data; 107 | break; 108 | case KS_TREESET: 109 | dc->ts = (ks_treeset*)data; 110 | break; 111 | case KS_HASHSET: 112 | dc->hs = (ks_hashset*)data; 113 | break; 114 | case KS_TREEMAP: 115 | dc->tm = (ks_treemap*)data; 116 | break; 117 | case KS_HASHMAP: 118 | dc->hm = (ks_hashmap*)data; 119 | break; 120 | } 121 | return dc; 122 | } 123 | 124 | void ks_datacont_delete(ks_datacont* dc) { 125 | if (dc == NULL) { 126 | return; 127 | } 128 | 129 | switch (dc->type) { 130 | case KS_CHAR: 131 | case KS_SHORT: 132 | case KS_INT: 133 | case KS_LL: 134 | case KS_FLOAT: 135 | case KS_DOUBLE: 136 | case KS_UCHAR: 137 | case KS_USHORT: 138 | case KS_UINT: 139 | case KS_ULL: 140 | case KS_VOIDP: 141 | /* do nothing 142 | * (VOIDP might point to a custom data structure) 143 | */ 144 | break; 145 | case KS_CHARP: 146 | case KS_SHORTP: 147 | case KS_INTP: 148 | case KS_LLP: 149 | case KS_FLOATP: 150 | case KS_DOUBLEP: 151 | case KS_UCHARP: 152 | case KS_USHORTP: 153 | case KS_UINTP: 154 | case KS_ULLP: 155 | free(dc->cp); 156 | break; 157 | case KS_LIST: 158 | ks_list_delete(dc->ls); 159 | break; 160 | case KS_TREESET: 161 | ks_treeset_delete(dc->ts); 162 | break; 163 | case KS_HASHSET: 164 | ks_hashset_delete(dc->hs); 165 | break; 166 | case KS_TREEMAP: 167 | ks_treemap_delete(dc->tm); 168 | break; 169 | case KS_HASHMAP: 170 | ks_hashmap_delete(dc->hm); 171 | break; 172 | } 173 | 174 | free(dc); 175 | } 176 | 177 | ks_datacont* ks_datacont_copy(const ks_datacont* dc) { 178 | if (dc == NULL) return NULL; 179 | switch (dc->type) { 180 | case KS_CHAR: 181 | return ks_datacont_new(&(dc->c), dc->type, dc->size); 182 | case KS_SHORT: 183 | return ks_datacont_new(&(dc->s), dc->type, dc->size); 184 | case KS_INT: 185 | return ks_datacont_new(&(dc->i), dc->type, dc->size); 186 | case KS_LL: 187 | return ks_datacont_new(&(dc->ll), dc->type, dc->size); 188 | case KS_FLOAT: 189 | return ks_datacont_new(&(dc->f), dc->type, dc->size); 190 | case KS_DOUBLE: 191 | return ks_datacont_new(&(dc->d), dc->type, dc->size); 192 | case KS_UCHAR: 193 | return ks_datacont_new(&(dc->uc), dc->type, dc->size); 194 | case KS_USHORT: 195 | return ks_datacont_new(&(dc->us), dc->type, dc->size); 196 | case KS_UINT: 197 | return ks_datacont_new(&(dc->ui), dc->type, dc->size); 198 | case KS_ULL: 199 | return ks_datacont_new(&(dc->ull), dc->type, dc->size); 200 | case KS_VOIDP: 201 | return ks_datacont_new(&(dc->vp), dc->type, dc->size); 202 | case KS_CHARP: 203 | return ks_datacont_new(dc->cp, dc->type, dc->size); 204 | case KS_SHORTP: 205 | return ks_datacont_new(dc->sp, dc->type, dc->size); 206 | case KS_INTP: 207 | return ks_datacont_new(dc->ip, dc->type, dc->size); 208 | case KS_LLP: 209 | return ks_datacont_new(dc->llp, dc->type, dc->size); 210 | case KS_FLOATP: 211 | return ks_datacont_new(dc->fp, dc->type, dc->size); 212 | case KS_DOUBLEP: 213 | return ks_datacont_new(dc->dp, dc->type, dc->size); 214 | case KS_UCHARP: 215 | return ks_datacont_new(dc->ucp, dc->type, dc->size); 216 | case KS_USHORTP: 217 | return ks_datacont_new(dc->usp, dc->type, dc->size); 218 | case KS_UINTP: 219 | return ks_datacont_new(dc->uip, dc->type, dc->size); 220 | case KS_ULLP: 221 | return ks_datacont_new(dc->ullp, dc->type, dc->size); 222 | case KS_LIST: 223 | return ks_datacont_new(ks_list_copy(dc->ls), dc->type, dc->size); 224 | case KS_TREESET: 225 | return ks_datacont_new(ks_treeset_copy(dc->ts), dc->type, dc->size); 226 | case KS_HASHSET: 227 | return ks_datacont_new(ks_hashset_copy(dc->hs), dc->type, dc->size); 228 | case KS_TREEMAP: 229 | return ks_datacont_new(ks_treemap_copy(dc->tm), dc->type, dc->size); 230 | case KS_HASHMAP: 231 | return ks_datacont_new(ks_hashmap_copy(dc->hm), dc->type, dc->size); 232 | } 233 | return NULL; 234 | } 235 | 236 | enum ks_comparison ks_datacont_compare(const ks_datacont* dca, 237 | const ks_datacont* dcb) { 238 | if (dca == NULL || dcb == NULL || dca->type != dcb->type) { 239 | return KS_CANTCOMPARE; 240 | } 241 | 242 | switch (dca->type) { 243 | case KS_CHAR: 244 | if (dca->c == dcb->c) return KS_EQUAL; 245 | if (dca->c < dcb->c) return KS_LESSTHAN; 246 | return KS_GREATERTHAN; 247 | case KS_SHORT: 248 | if (dca->s == dcb->s) return KS_EQUAL; 249 | if (dca->s < dcb->s) return KS_LESSTHAN; 250 | return KS_GREATERTHAN; 251 | case KS_INT: 252 | if (dca->i == dcb->i) return KS_EQUAL; 253 | if (dca->i < dcb->i) return KS_LESSTHAN; 254 | return KS_GREATERTHAN; 255 | case KS_LL: 256 | if (dca->ll == dcb->ll) return KS_EQUAL; 257 | if (dca->ll < dcb->ll) return KS_LESSTHAN; 258 | return KS_GREATERTHAN; 259 | case KS_FLOAT: 260 | if (dca->f == dcb->f) return KS_EQUAL; 261 | if (dca->f < dcb->f) return KS_LESSTHAN; 262 | return KS_GREATERTHAN; 263 | case KS_DOUBLE: 264 | if (dca->d == dcb->d) return KS_EQUAL; 265 | if (dca->d < dcb->d) return KS_LESSTHAN; 266 | return KS_GREATERTHAN; 267 | case KS_UCHAR: 268 | if (dca->uc == dcb->uc) return KS_EQUAL; 269 | if (dca->uc < dcb->uc) return KS_LESSTHAN; 270 | return KS_GREATERTHAN; 271 | case KS_USHORT: 272 | if (dca->us == dcb->us) return KS_EQUAL; 273 | if (dca->us < dcb->us) return KS_LESSTHAN; 274 | return KS_GREATERTHAN; 275 | case KS_UINT: 276 | if (dca->ui == dcb->ui) return KS_EQUAL; 277 | if (dca->ui < dcb->ui) return KS_LESSTHAN; 278 | return KS_GREATERTHAN; 279 | case KS_ULL: 280 | if (dca->ull == dcb->ull) return KS_EQUAL; 281 | if (dca->ull < dcb->ull) return KS_LESSTHAN; 282 | return KS_GREATERTHAN; 283 | case KS_CHARP: { 284 | int res = strcmp(dca->cp, dcb->cp); 285 | if (res == 0) return KS_EQUAL; 286 | if (res < 0) return KS_LESSTHAN; 287 | return KS_GREATERTHAN; 288 | } 289 | case KS_SHORTP: 290 | case KS_INTP: 291 | case KS_LLP: 292 | case KS_UCHARP: 293 | case KS_USHORTP: 294 | case KS_UINTP: 295 | case KS_ULLP: 296 | case KS_FLOATP: 297 | case KS_DOUBLEP: { 298 | size_t min = dca->size > dcb->size ? dcb->size : dca->size; 299 | int res = memcmp(dca->vp, dcb->vp, min); 300 | if (res < 0) return KS_LESSTHAN; 301 | if (res > 0) return KS_GREATERTHAN; 302 | if (dca->size == dcb->size) return KS_EQUAL; 303 | if (dca->size < dcb->size) return KS_LESSTHAN; 304 | return KS_GREATERTHAN; 305 | } 306 | case KS_VOIDP: 307 | case KS_LIST: 308 | case KS_TREESET: 309 | case KS_HASHSET: 310 | case KS_TREEMAP: 311 | case KS_HASHMAP: 312 | break; 313 | } 314 | 315 | return KS_CANTCOMPARE; 316 | } 317 | 318 | static uint32_t __hash(const void* data, size_t size) { 319 | uint32_t hash = 5381; 320 | 321 | for (size_t i = 0; i < size; i++) { 322 | uint8_t byte = *((uint8_t*)data + i); 323 | hash = ((hash << 5) + hash) + byte; 324 | } 325 | 326 | return hash; 327 | } 328 | 329 | uint32_t ks_datacont_hash(const ks_datacont* dc) { 330 | switch (dc->type) { 331 | case KS_CHAR: 332 | case KS_UCHAR: 333 | return __hash(&dc->c, sizeof(char)); 334 | case KS_SHORT: 335 | case KS_USHORT: 336 | return __hash(&dc->s, sizeof(short)); 337 | case KS_INT: 338 | case KS_UINT: 339 | return __hash(&dc->i, sizeof(int)); 340 | case KS_LL: 341 | case KS_ULL: 342 | return __hash(&dc->ll, sizeof(long long)); 343 | case KS_FLOAT: 344 | return __hash(&dc->f, sizeof(float)); 345 | case KS_DOUBLE: 346 | return __hash(&dc->d, sizeof(double)); 347 | case KS_CHARP: 348 | case KS_SHORTP: 349 | case KS_INTP: 350 | case KS_LLP: 351 | case KS_UCHARP: 352 | case KS_USHORTP: 353 | case KS_UINTP: 354 | case KS_ULLP: 355 | case KS_FLOATP: 356 | case KS_DOUBLEP: 357 | return __hash(dc->vp, dc->size); 358 | case KS_VOIDP: 359 | case KS_LIST: 360 | case KS_TREESET: 361 | case KS_HASHSET: 362 | case KS_TREEMAP: 363 | case KS_HASHMAP: 364 | break; 365 | } 366 | return 0; 367 | } 368 | -------------------------------------------------------------------------------- /src/ks_hashmap.c: -------------------------------------------------------------------------------- 1 | #include "kylestructs/ks_hashmap.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "kylestructs/ks_datacont.h" 7 | #include "kylestructs/ks_list.h" 8 | #include "kylestructs/ks_listnode.h" 9 | #include "kylestructs/ks_treemap.h" 10 | #include "kylestructs/ks_treemapnode.h" 11 | #include "kylestructs/ks_types.h" 12 | 13 | ks_hashmap* ks_hashmap_new(enum ks_datatype type, size_t num_buckets) { 14 | if (num_buckets == 0) return NULL; 15 | 16 | ks_hashmap* hm = calloc(1, sizeof(ks_hashmap)); 17 | 18 | hm->type = type; 19 | 20 | hm->buckets = calloc(num_buckets, sizeof(ks_treemap*)); 21 | 22 | hm->num_buckets = num_buckets; 23 | 24 | return hm; 25 | } 26 | 27 | void ks_hashmap_delete(ks_hashmap* hm) { 28 | if (hm == NULL) return; 29 | 30 | for (unsigned int i = 0; i < hm->num_buckets; i++) 31 | ks_treemap_delete(hm->buckets[i]); 32 | 33 | free(hm->buckets); 34 | free(hm); 35 | } 36 | 37 | ks_hashmap* ks_hashmap_copy(const ks_hashmap* hm) { 38 | if (hm == NULL) return NULL; 39 | 40 | ks_hashmap* hm_copy = ks_hashmap_new(hm->type, hm->num_buckets); 41 | 42 | for (unsigned int i = 0; i < hm->num_buckets; i++) { 43 | hm_copy->buckets[i] = ks_treemap_copy(hm->buckets[i]); 44 | } 45 | 46 | return hm_copy; 47 | } 48 | 49 | int ks_hashmap_add(ks_hashmap* hm, const ks_datacont* key, 50 | const ks_datacont* value) { 51 | if (hm == NULL || key == NULL || value == NULL || key->type != hm->type) 52 | return -1; 53 | 54 | switch (key->type) { 55 | case KS_VOIDP: 56 | case KS_LIST: 57 | case KS_TREESET: 58 | case KS_HASHSET: 59 | case KS_TREEMAP: 60 | case KS_HASHMAP: 61 | return -1; 62 | default: 63 | break; 64 | } 65 | 66 | uint32_t hash = ks_datacont_hash(key); 67 | 68 | if (hm->buckets[hash % hm->num_buckets] == NULL) 69 | hm->buckets[hash % hm->num_buckets] = ks_treemap_new(); 70 | 71 | return ks_treemap_add(hm->buckets[hash % hm->num_buckets], key, value); 72 | } 73 | 74 | int ks_hashmap_remove(ks_hashmap* hm, const ks_datacont* key) { 75 | if (hm == NULL || hm->buckets == NULL || key == NULL || 76 | key->type != hm->type) 77 | return -1; 78 | 79 | uint32_t hash = ks_datacont_hash(key); 80 | 81 | return ks_treemap_remove(hm->buckets[hash % hm->num_buckets], key); 82 | } 83 | 84 | const ks_datacont* ks_hashmap_get(const ks_hashmap* hm, 85 | const ks_datacont* key) { 86 | if (hm == NULL || key == NULL || key->type != hm->type) return NULL; 87 | 88 | uint32_t hash = ks_datacont_hash(key); 89 | 90 | return ks_treemap_get(hm->buckets[hash % hm->num_buckets], key); 91 | } 92 | 93 | const ks_datacont* ks_hashmap_get_key(const ks_hashmap* hm, int index) { 94 | if (hm == NULL) return NULL; 95 | 96 | int start = index < 0 ? hm->num_buckets - 1 : 0; 97 | int end = index < 0 ? -1 : hm->num_buckets; 98 | int dir = index < 0 ? -1 : 1; 99 | 100 | for (int i = start; i != end; i += dir) { 101 | ks_treemap* tm = hm->buckets[i]; 102 | 103 | const ks_datacont* dc = ks_treemap_get_key(tm, index); 104 | 105 | if (dc != NULL) return dc; 106 | 107 | index -= (dir * ks_treemap_count(tm)); 108 | } 109 | 110 | return NULL; 111 | } 112 | 113 | unsigned int ks_hashmap_count(const ks_hashmap* hm) { 114 | if (hm == NULL) return 0; 115 | 116 | int count = 0; 117 | 118 | for (unsigned int i = 0; i < hm->num_buckets; i++) 119 | count += ks_treemap_count(hm->buckets[i]); 120 | 121 | return count; 122 | } 123 | 124 | void ks_hashmap_optimize(ks_hashmap* hm) { 125 | if (hm == NULL) return; 126 | 127 | for (unsigned int i = 0; i < hm->num_buckets; i++) 128 | ks_treemap_balance(hm->buckets[i]); 129 | } 130 | -------------------------------------------------------------------------------- /src/ks_hashset.c: -------------------------------------------------------------------------------- 1 | #include "kylestructs/ks_hashset.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "kylestructs/ks_datacont.h" 7 | #include "kylestructs/ks_list.h" 8 | #include "kylestructs/ks_listnode.h" 9 | #include "kylestructs/ks_treeset.h" 10 | #include "kylestructs/ks_treesetnode.h" 11 | #include "kylestructs/ks_types.h" 12 | 13 | ks_hashset* ks_hashset_new(enum ks_datatype type, size_t num_buckets) { 14 | if (num_buckets == 0) return NULL; 15 | 16 | ks_hashset* hs = calloc(1, sizeof(ks_hashset)); 17 | 18 | hs->type = type; 19 | 20 | hs->buckets = calloc(num_buckets, sizeof(ks_treeset*)); 21 | 22 | hs->num_buckets = num_buckets; 23 | 24 | return hs; 25 | } 26 | 27 | void ks_hashset_delete(ks_hashset* hs) { 28 | if (hs == NULL) return; 29 | 30 | for (unsigned int i = 0; i < hs->num_buckets; i++) 31 | ks_treeset_delete(hs->buckets[i]); 32 | 33 | free(hs->buckets); 34 | free(hs); 35 | } 36 | 37 | ks_hashset* ks_hashset_copy(const ks_hashset* hs) { 38 | if (hs == NULL) return NULL; 39 | 40 | ks_hashset* hs_copy = ks_hashset_new(hs->type, hs->num_buckets); 41 | 42 | for (unsigned int i = 0; i < hs->num_buckets; i++) { 43 | hs_copy->buckets[i] = ks_treeset_copy(hs->buckets[i]); 44 | } 45 | 46 | return hs_copy; 47 | } 48 | 49 | int ks_hashset_add(ks_hashset* hs, const ks_datacont* dc) { 50 | if (hs == NULL || dc == NULL || dc->type != hs->type) return -1; 51 | 52 | switch (dc->type) { 53 | case KS_VOIDP: 54 | case KS_LIST: 55 | case KS_TREESET: 56 | case KS_HASHSET: 57 | case KS_TREEMAP: 58 | case KS_HASHMAP: 59 | return -1; 60 | default: 61 | break; 62 | } 63 | 64 | uint32_t hash = ks_datacont_hash(dc); 65 | 66 | if (hs->buckets[hash % hs->num_buckets] == NULL) 67 | hs->buckets[hash % hs->num_buckets] = ks_treeset_new(); 68 | 69 | return ks_treeset_add(hs->buckets[hash % hs->num_buckets], dc); 70 | } 71 | 72 | int ks_hashset_remove(ks_hashset* hs, const ks_datacont* dc) { 73 | if (hs == NULL || dc == NULL || dc->type != hs->type) return -1; 74 | 75 | uint32_t hash = ks_datacont_hash(dc); 76 | 77 | return ks_treeset_remove_by(hs->buckets[hash % hs->num_buckets], dc); 78 | } 79 | 80 | unsigned int ks_hashset_contains(const ks_hashset* hs, const ks_datacont* dc) { 81 | if (hs == NULL || dc == NULL || dc->type != hs->type) return 0; 82 | 83 | uint32_t hash = ks_datacont_hash(dc); 84 | 85 | if (hs->buckets[hash % hs->num_buckets] == NULL) return 0; 86 | 87 | return ks_treeset_contains(hs->buckets[hash % hs->num_buckets], dc); 88 | } 89 | 90 | unsigned int ks_hashset_count(const ks_hashset* hs) { 91 | if (hs == NULL) return 0; 92 | 93 | int count = 0; 94 | 95 | for (unsigned int i = 0; i < hs->num_buckets; i++) 96 | count += ks_treeset_count(hs->buckets[i]); 97 | 98 | return count; 99 | } 100 | 101 | const ks_datacont* ks_hashset_get(const ks_hashset* hs, int index) { 102 | if (hs == NULL) return NULL; 103 | 104 | int start = index < 0 ? hs->num_buckets - 1 : 0; 105 | int end = index < 0 ? -1 : hs->num_buckets; 106 | int dir = index < 0 ? -1 : 1; 107 | 108 | for (; start != end; start += dir) { 109 | ks_treeset* ts = hs->buckets[start]; 110 | 111 | const ks_datacont* dc = ks_treeset_get(ts, index); 112 | 113 | if (dc != NULL) return dc; 114 | 115 | index -= (dir * ks_treeset_count(ts)); 116 | } 117 | 118 | return NULL; 119 | } 120 | 121 | void ks_hashset_optimize(ks_hashset* hs) { 122 | if (hs == NULL) return; 123 | 124 | for (unsigned int i = 0; i < hs->num_buckets; i++) 125 | ks_treeset_balance(hs->buckets[i]); 126 | } 127 | -------------------------------------------------------------------------------- /src/ks_iterator.c: -------------------------------------------------------------------------------- 1 | #include "kylestructs/ks_iterator.h" 2 | 3 | #include 4 | 5 | #include "kylestructs/ks_hashmap.h" 6 | #include "kylestructs/ks_hashset.h" 7 | #include "kylestructs/ks_list.h" 8 | #include "kylestructs/ks_treemap.h" 9 | #include "kylestructs/ks_treeset.h" 10 | #include "kylestructs/ks_types.h" 11 | 12 | ks_iterator* ks_iterator_new(const void* ks_obj, enum ks_datatype type) { 13 | if (ks_obj == NULL) { 14 | return NULL; 15 | } 16 | 17 | ks_iterator* iter = calloc(1, sizeof(ks_iterator)); 18 | iter->parent = (void*)ks_obj; 19 | iter->type = type; 20 | 21 | switch (type) { 22 | case KS_LIST: 23 | iter->size = ks_list_length(ks_obj); 24 | iter->curr = ((ks_list*)ks_obj)->head; 25 | break; 26 | 27 | case KS_TREESET: 28 | iter->size = ks_treeset_count(ks_obj); 29 | break; 30 | 31 | case KS_HASHSET: 32 | iter->size = ks_hashset_count(ks_obj); 33 | break; 34 | 35 | case KS_TREEMAP: 36 | iter->size = ks_treemap_count(ks_obj); 37 | break; 38 | 39 | case KS_HASHMAP: 40 | iter->size = ks_hashmap_count(ks_obj); 41 | break; 42 | 43 | default: 44 | free(iter); 45 | iter = NULL; 46 | } 47 | 48 | return iter; 49 | } 50 | 51 | void ks_iterator_delete(ks_iterator* iter) { free(iter); } 52 | 53 | const ks_datacont* ks_iterator_next(ks_iterator* iter) { 54 | if (iter == NULL) { 55 | return NULL; 56 | } 57 | 58 | const ks_datacont* dc; 59 | 60 | switch (iter->type) { 61 | case KS_LIST: 62 | dc = iter->curr ? iter->curr->dc : NULL; 63 | iter->index += 1; 64 | iter->curr = iter->curr ? iter->curr->next : NULL; 65 | break; 66 | 67 | case KS_TREESET: 68 | dc = ks_treeset_get((ks_treeset*)iter->parent, iter->index); 69 | iter->index += 1; 70 | break; 71 | 72 | case KS_HASHSET: 73 | dc = ks_hashset_get((ks_hashset*)iter->parent, iter->index); 74 | iter->index += 1; 75 | break; 76 | 77 | case KS_TREEMAP: 78 | dc = ks_treemap_get_key((ks_treemap*)iter->parent, iter->index); 79 | iter->index += 1; 80 | break; 81 | 82 | case KS_HASHMAP: 83 | dc = ks_hashmap_get_key((ks_hashmap*)iter->parent, iter->index); 84 | iter->index += 1; 85 | break; 86 | default: 87 | dc = NULL; 88 | } 89 | 90 | return dc; 91 | } 92 | -------------------------------------------------------------------------------- /src/ks_list.c: -------------------------------------------------------------------------------- 1 | #include "kylestructs/ks_list.h" 2 | 3 | #include 4 | 5 | #include "kylestructs/ks_datacont.h" 6 | #include "kylestructs/ks_listnode.h" 7 | #include "kylestructs/ks_types.h" 8 | 9 | ks_list* ks_list_new() { return calloc(1, sizeof(ks_list)); } 10 | 11 | void ks_list_delete(ks_list* ls) { 12 | if (ls == NULL) return; 13 | 14 | ks_listnode_delete_all(ls->head); 15 | 16 | free(ls); 17 | } 18 | 19 | ks_list* ks_list_copy(const ks_list* ls) { 20 | if (ls == NULL) return NULL; 21 | 22 | ks_list* ls_copy = ks_list_new(); 23 | 24 | ls_copy->head = ks_listnode_copy_all(ls->head); 25 | 26 | return ls_copy; 27 | } 28 | 29 | int ks_list_add(ks_list* ls, const ks_datacont* dc) { 30 | if (ls == NULL || dc == NULL) return -1; 31 | 32 | if (ls->head) return ks_listnode_add(ls->head, dc); 33 | 34 | ls->head = ks_listnode_new(dc); 35 | 36 | return 0; 37 | } 38 | 39 | ks_list* ks_list_merge(ks_list* lsa, ks_list* lsb) { 40 | if (lsa == NULL || lsb == NULL) return lsa ? lsa : lsb; 41 | 42 | lsa->head = ks_listnode_merge(lsa->head, lsb->head); 43 | 44 | free(lsb); 45 | 46 | return lsa; 47 | } 48 | 49 | int ks_list_remove_by(ks_list* ls, const ks_datacont* dc) { 50 | if (ls == NULL || dc == NULL) return -1; 51 | 52 | return ks_listnode_remove_by(&(ls->head), dc); 53 | } 54 | 55 | int ks_list_remove_at(ks_list* ls, int index) { 56 | if (ls == NULL) return -1; 57 | 58 | return ks_listnode_remove_at(&(ls->head), index); 59 | } 60 | 61 | int ks_list_remove_all(ks_list* ls, const ks_datacont* dc) { 62 | if (ls == NULL || dc == NULL) return -1; 63 | 64 | return ks_listnode_remove_all(&(ls->head), dc); 65 | } 66 | 67 | int ks_list_replace_by(ks_list* ls, const ks_datacont* old_dc, 68 | const ks_datacont* new_dc) { 69 | if (ls == NULL || old_dc == NULL || new_dc == NULL) return -1; 70 | 71 | return ks_listnode_replace_by(ls->head, old_dc, new_dc); 72 | } 73 | 74 | int ks_list_replace_at(ks_list* ls, const ks_datacont* dc, int index) { 75 | if (ls == NULL || dc == NULL) return -1; 76 | 77 | return ks_listnode_replace_at(ls->head, dc, index); 78 | } 79 | 80 | int ks_list_replace_all(ks_list* ls, const ks_datacont* old_dc, 81 | const ks_datacont* new_dc) { 82 | if (ls == NULL || old_dc == NULL || new_dc == NULL) return -1; 83 | 84 | return ks_listnode_replace_all(ls->head, old_dc, new_dc); 85 | } 86 | 87 | int ks_list_insert(ks_list* ls, const ks_datacont* dc, int index) { 88 | if (ls == NULL || dc == NULL) return -1; 89 | 90 | return ks_listnode_insert(&(ls->head), dc, index); 91 | } 92 | 93 | int ks_list_push(ks_list* ls, const ks_datacont* dc) { 94 | if (ls == NULL || dc == NULL) return -1; 95 | 96 | if (ls->head != NULL) return ks_listnode_insert(&(ls->head), dc, 0); 97 | 98 | ls->head = ks_listnode_new(dc); 99 | 100 | return 0; 101 | } 102 | 103 | ks_datacont* ks_list_pop(ks_list* ls) { 104 | if (ls == NULL || ls->head == NULL) return NULL; 105 | 106 | ks_datacont* dc = ks_datacont_copy(ks_listnode_get(ls->head, 0)); 107 | 108 | ks_listnode_remove_at(&(ls->head), 0); 109 | 110 | return dc; 111 | } 112 | 113 | const ks_datacont* ks_list_peek(const ks_list* ls) { 114 | if (ls == NULL) return NULL; 115 | 116 | return ks_listnode_get(ls->head, 0); 117 | } 118 | 119 | int ks_list_enqueue(ks_list* ls, const ks_datacont* dc) { 120 | if (ls == NULL || dc == NULL) return -1; 121 | 122 | return ks_listnode_insert(&(ls->head), dc, 0); 123 | } 124 | 125 | ks_datacont* ks_list_dequeue(ks_list* ls) { 126 | if (ls == NULL || ls->head == NULL) return NULL; 127 | 128 | ks_datacont* dc = ks_datacont_copy(ks_listnode_get(ls->head, -1)); 129 | 130 | ks_listnode_remove_at(&(ls->head), -1); 131 | 132 | return dc; 133 | } 134 | 135 | int ks_list_index(const ks_list* ls, const ks_datacont* dc) { 136 | if (ls == NULL || dc == NULL) return -1; 137 | 138 | return ks_listnode_index(ls->head, dc); 139 | } 140 | 141 | const ks_datacont* ks_list_get(const ks_list* ls, int index) { 142 | if (ls == NULL) return NULL; 143 | 144 | return ks_listnode_get(ls->head, index); 145 | } 146 | 147 | unsigned int ks_list_count(const ks_list* ls, const ks_datacont* dc) { 148 | if (ls == NULL || dc == NULL) return -1; 149 | 150 | return ks_listnode_count(ls->head, dc); 151 | } 152 | 153 | unsigned int ks_list_length(const ks_list* ls) { 154 | if (ls == NULL) return 0; 155 | 156 | return ks_listnode_length(ls->head); 157 | } 158 | -------------------------------------------------------------------------------- /src/ks_listnode.c: -------------------------------------------------------------------------------- 1 | #include "kylestructs/ks_listnode.h" 2 | 3 | #include 4 | 5 | #include "kylestructs/ks_datacont.h" 6 | #include "kylestructs/ks_types.h" 7 | 8 | ks_listnode* ks_listnode_new(const ks_datacont* dc) { 9 | if (dc == NULL) return NULL; 10 | 11 | ks_listnode* ln = calloc(1, sizeof(ks_listnode)); 12 | 13 | ln->dc = (ks_datacont*)dc; 14 | 15 | return ln; 16 | } 17 | 18 | void ks_listnode_delete(ks_listnode* ln) { 19 | if (ln == NULL) return; 20 | 21 | if (ln->dc) ks_datacont_delete(ln->dc); 22 | 23 | free(ln); 24 | } 25 | 26 | ks_listnode* ks_listnode_copy(const ks_listnode* ln) { 27 | if (ln == NULL) return NULL; 28 | 29 | ks_datacont* dc = ks_datacont_copy(ln->dc); 30 | 31 | return ks_listnode_new(dc); 32 | } 33 | 34 | void ks_listnode_delete_all(ks_listnode* ln) { 35 | if (ln == NULL) return; 36 | 37 | ks_listnode_delete_all(ln->next); 38 | 39 | ks_listnode_delete(ln); 40 | } 41 | 42 | ks_listnode* ks_listnode_copy_all(const ks_listnode* ln) { 43 | if (ln == NULL) return NULL; 44 | 45 | ks_listnode* ln_copy = ks_listnode_copy(ln); 46 | 47 | ln_copy->next = ks_listnode_copy_all(ln->next); 48 | 49 | return ln_copy; 50 | } 51 | 52 | int ks_listnode_add(ks_listnode* ln, const ks_datacont* dc) { 53 | if (ln == NULL || dc == NULL) return -1; 54 | 55 | if (ln->next) return ks_listnode_add(ln->next, dc); 56 | 57 | ln->next = ks_listnode_new(dc); 58 | 59 | return 0; 60 | } 61 | 62 | ks_listnode* ks_listnode_merge(ks_listnode* lna, ks_listnode* lnb) { 63 | if (lna == NULL || lnb == NULL) return lna ? lna : lnb; 64 | 65 | ks_listnode* iter = lna; 66 | 67 | while (iter->next != NULL) iter = iter->next; 68 | 69 | iter->next = lnb; 70 | 71 | return lna; 72 | } 73 | 74 | int ks_listnode_remove_by(ks_listnode** ln, const ks_datacont* dc) { 75 | if (ln == NULL || *ln == NULL || dc == NULL) return -1; 76 | 77 | if (ks_datacont_compare(dc, (*ln)->dc) == KS_EQUAL) { 78 | ks_listnode* temp = (*ln)->next; 79 | ks_listnode_delete(*ln); 80 | *ln = temp; 81 | return 1; 82 | } 83 | 84 | if ((*ln)->next) return ks_listnode_remove_by(&((*ln)->next), dc); 85 | return 0; 86 | } 87 | 88 | int ks_listnode_remove_at(ks_listnode** ln, int index) { 89 | if (ln == NULL || *ln == NULL || 90 | (index < 0 && (index = ks_listnode_length(*ln) + index) < 0)) 91 | return -1; 92 | 93 | if (index == 0) { 94 | ks_listnode* temp = (*ln)->next; 95 | ks_listnode_delete(*ln); 96 | *ln = temp; 97 | return 0; 98 | } 99 | 100 | if ((*ln)->next) return ks_listnode_remove_at(&((*ln)->next), index - 1); 101 | return -1; 102 | } 103 | 104 | int ks_listnode_remove_all(ks_listnode** ln, const ks_datacont* dc) { 105 | if (ln == NULL || *ln == NULL || dc == NULL) return -1; 106 | 107 | if (ks_datacont_compare(dc, (*ln)->dc) == KS_EQUAL) { 108 | ks_listnode* temp = (*ln)->next; 109 | ks_listnode_delete(*ln); 110 | *ln = temp; 111 | if ((*ln) && (*ln)->next) 112 | return 1 + ks_listnode_remove_all(&((*ln)->next), dc); 113 | return 1; 114 | } 115 | 116 | if ((*ln)->next) return ks_listnode_remove_all(&(*ln)->next, dc); 117 | return 0; 118 | } 119 | 120 | int ks_listnode_replace_by(ks_listnode* ln, const ks_datacont* old_dc, 121 | const ks_datacont* new_dc) { 122 | if (ln == NULL || old_dc == NULL || new_dc == NULL) return -1; 123 | 124 | if (ks_datacont_compare(old_dc, ln->dc) == KS_EQUAL) { 125 | ks_datacont_delete(ln->dc); 126 | ln->dc = (ks_datacont*)new_dc; 127 | return 0; 128 | } 129 | 130 | return ks_listnode_replace_by(ln->next, old_dc, new_dc); 131 | } 132 | 133 | int ks_listnode_replace_at(ks_listnode* ln, const ks_datacont* dc, int index) { 134 | if (ln == NULL || dc == NULL || 135 | (index < 0 && (index = ks_listnode_length(ln) + index) < 0)) 136 | return -1; 137 | 138 | if (index == 0) { 139 | ks_datacont_delete(ln->dc); 140 | ln->dc = (ks_datacont*)dc; 141 | return 0; 142 | } 143 | 144 | return ks_listnode_replace_at(ln->next, dc, index - 1); 145 | } 146 | 147 | int ks_listnode_replace_all(ks_listnode* ln, const ks_datacont* old_dc, 148 | const ks_datacont* new_dc) { 149 | if (ln == NULL || old_dc == NULL || new_dc == NULL) return -1; 150 | 151 | if (ks_datacont_compare(old_dc, ln->dc) == KS_EQUAL) { 152 | ks_datacont_delete(ln->dc); 153 | ln->dc = (ks_datacont*)new_dc; 154 | 155 | if (ln->next) { 156 | ks_datacont* copy = ks_datacont_copy(new_dc); 157 | int result = ks_listnode_replace_all(ln->next, old_dc, copy); 158 | if (result == 0) ks_datacont_delete(copy); 159 | return 1 + result; 160 | } 161 | return 1; 162 | } 163 | 164 | else if (ln->next) 165 | return ks_listnode_replace_all(ln->next, old_dc, new_dc); 166 | return 0; 167 | } 168 | 169 | int ks_listnode_insert(ks_listnode** ln, const ks_datacont* dc, int index) { 170 | if (ln == NULL || dc == NULL || 171 | (index < 0 && (index = ks_listnode_length(*ln) + index) < 0)) 172 | return -1; 173 | 174 | if (index == 0) { 175 | ks_listnode* new_node = ks_listnode_new(dc); 176 | new_node->next = *ln; 177 | *ln = new_node; 178 | return 0; 179 | } 180 | 181 | else if (*ln == NULL) 182 | return -1; 183 | 184 | return ks_listnode_insert(&((*ln)->next), dc, index - 1); 185 | } 186 | 187 | static int __ks_listnode_index(const ks_listnode* ln, const ks_datacont* dc, 188 | int curr_index) { 189 | if (ln == NULL || dc == NULL) return -1; 190 | 191 | if (ks_datacont_compare(dc, ln->dc) == KS_EQUAL) return curr_index; 192 | 193 | return __ks_listnode_index(ln->next, dc, curr_index + 1); 194 | } 195 | 196 | int ks_listnode_index(const ks_listnode* ln, const ks_datacont* dc) { 197 | return __ks_listnode_index(ln, dc, 0); 198 | } 199 | 200 | const ks_datacont* ks_listnode_get(const ks_listnode* ln, int index) { 201 | if (ln == NULL || 202 | (index < 0 && (index = ks_listnode_length(ln) + index) < 0)) 203 | return NULL; 204 | 205 | if (index == 0) return ln->dc; 206 | 207 | return ks_listnode_get(ln->next, index - 1); 208 | } 209 | 210 | unsigned int ks_listnode_count(const ks_listnode* ln, const ks_datacont* dc) { 211 | if (ln == NULL || dc == NULL) return -1; 212 | 213 | if (ks_datacont_compare(dc, ln->dc) == KS_EQUAL) { 214 | if (ln->next) return 1 + ks_listnode_count(ln->next, dc); 215 | return 1; 216 | } 217 | 218 | if (ln->next) return ks_listnode_count(ln->next, dc); 219 | return 0; 220 | } 221 | 222 | unsigned int ks_listnode_length(const ks_listnode* ln) { 223 | if (ln == NULL) return 0; 224 | 225 | return 1 + ks_listnode_length(ln->next); 226 | } 227 | -------------------------------------------------------------------------------- /src/ks_treemap.c: -------------------------------------------------------------------------------- 1 | #include "kylestructs/ks_treemap.h" 2 | 3 | #include 4 | 5 | #include "kylestructs/ks_datacont.h" 6 | #include "kylestructs/ks_list.h" 7 | #include "kylestructs/ks_listnode.h" 8 | #include "kylestructs/ks_treemapnode.h" 9 | #include "kylestructs/ks_types.h" 10 | 11 | ks_treemap* ks_treemap_new() { return calloc(1, sizeof(ks_treemap)); } 12 | 13 | void ks_treemap_delete(ks_treemap* tm) { 14 | if (tm == NULL) return; 15 | 16 | ks_treemapnode_delete_all(tm->root); 17 | 18 | free(tm); 19 | } 20 | 21 | ks_treemap* ks_treemap_copy(const ks_treemap* tm) { 22 | if (tm == NULL) return NULL; 23 | 24 | ks_treemap* tm_copy = ks_treemap_new(); 25 | 26 | tm_copy->root = ks_treemapnode_copy_all(tm->root); 27 | 28 | return tm_copy; 29 | } 30 | 31 | int ks_treemap_add(ks_treemap* tm, const ks_datacont* key, 32 | const ks_datacont* value) { 33 | if (tm == NULL || key == NULL || value == NULL) return -1; 34 | 35 | switch (key->type) { 36 | case KS_VOIDP: 37 | case KS_LIST: 38 | case KS_TREESET: 39 | case KS_HASHSET: 40 | case KS_TREEMAP: 41 | case KS_HASHMAP: 42 | return -1; 43 | default: 44 | break; 45 | } 46 | 47 | if (tm->root == NULL) { 48 | tm->root = ks_treemapnode_new(key, value); 49 | return 0; 50 | } 51 | return ks_treemapnode_add(tm->root, key, value); 52 | } 53 | 54 | int ks_treemap_remove(ks_treemap* tm, const ks_datacont* key) { 55 | if (tm == NULL) return -1; 56 | 57 | return ks_treemapnode_remove(&tm->root, key); 58 | } 59 | 60 | const ks_datacont* ks_treemap_get(const ks_treemap* tm, 61 | const ks_datacont* key) { 62 | if (tm == NULL) return NULL; 63 | 64 | return ks_treemapnode_get(tm->root, key); 65 | } 66 | 67 | const ks_datacont* ks_treemap_get_key(const ks_treemap* tm, int index) { 68 | if (tm == NULL) return NULL; 69 | 70 | return ks_treemapnode_get_key(tm->root, index); 71 | } 72 | 73 | unsigned int ks_treemap_count(const ks_treemap* tm) { 74 | if (tm == NULL) return 0; 75 | 76 | return ks_treemapnode_count(tm->root); 77 | } 78 | 79 | unsigned int ks_treemap_height(const ks_treemap* tm) { 80 | if (tm == NULL) return 0; 81 | 82 | return ks_treemapnode_height(tm->root); 83 | } 84 | 85 | void ks_treemap_balance(ks_treemap* tm) { 86 | if (tm == NULL) return; 87 | 88 | tm->root = ks_treemapnode_balance(tm->root); 89 | } 90 | -------------------------------------------------------------------------------- /src/ks_treemapnode.c: -------------------------------------------------------------------------------- 1 | #include "kylestructs/ks_treemapnode.h" 2 | 3 | #include 4 | 5 | #include "kylestructs/ks_datacont.h" 6 | #include "kylestructs/ks_listnode.h" 7 | #include "kylestructs/ks_types.h" 8 | 9 | ks_treemapnode* ks_treemapnode_new(const ks_datacont* key, 10 | const ks_datacont* value) { 11 | if (key == NULL || value == NULL) return NULL; 12 | 13 | ks_treemapnode* tmn = calloc(1, sizeof(ks_treemapnode)); 14 | 15 | tmn->key = (ks_datacont*)key; 16 | 17 | tmn->value = (ks_datacont*)value; 18 | 19 | return tmn; 20 | } 21 | 22 | void ks_treemapnode_delete(ks_treemapnode* tmn) { 23 | if (tmn == NULL) return; 24 | 25 | ks_datacont_delete(tmn->key); 26 | 27 | ks_datacont_delete(tmn->value); 28 | 29 | free(tmn); 30 | } 31 | 32 | ks_treemapnode* ks_treemapnode_copy(const ks_treemapnode* tmn) { 33 | if (tmn == NULL) return NULL; 34 | 35 | ks_datacont* key = ks_datacont_copy(tmn->key); 36 | ks_datacont* val = ks_datacont_copy(tmn->value); 37 | 38 | return ks_treemapnode_new(key, val); 39 | } 40 | 41 | void ks_treemapnode_delete_all(ks_treemapnode* tmn) { 42 | if (tmn == NULL) return; 43 | 44 | ks_treemapnode_delete_all(tmn->left); 45 | 46 | ks_treemapnode_delete_all(tmn->right); 47 | 48 | ks_treemapnode_delete(tmn); 49 | } 50 | 51 | ks_treemapnode* ks_treemapnode_copy_all(const ks_treemapnode* tmn) { 52 | if (tmn == NULL) return NULL; 53 | 54 | ks_treemapnode* tmn_copy = ks_treemapnode_copy(tmn); 55 | 56 | tmn_copy->left = ks_treemapnode_copy_all(tmn->left); 57 | tmn_copy->right = ks_treemapnode_copy_all(tmn->right); 58 | 59 | return tmn_copy; 60 | } 61 | 62 | int ks_treemapnode_add(ks_treemapnode* tmn, const ks_datacont* key, 63 | const ks_datacont* value) { 64 | if (tmn == NULL || key == NULL || value == NULL) return -1; 65 | 66 | enum ks_comparison result = ks_datacont_compare(key, tmn->key); 67 | 68 | if (result == KS_CANTCOMPARE) return -1; 69 | 70 | if (result == KS_EQUAL) { 71 | ks_datacont_delete(tmn->key); 72 | ks_datacont_delete(tmn->value); 73 | tmn->key = (ks_datacont*)key; 74 | tmn->value = (ks_datacont*)value; 75 | return 1; 76 | } else if (result == KS_LESSTHAN) { 77 | if (tmn->left) 78 | return ks_treemapnode_add(tmn->left, key, value); 79 | else 80 | tmn->left = ks_treemapnode_new(key, value); 81 | } else { 82 | if (tmn->right) 83 | return ks_treemapnode_add(tmn->right, key, value); 84 | else 85 | tmn->right = ks_treemapnode_new(key, value); 86 | } 87 | return 0; 88 | } 89 | 90 | int ks_treemapnode_remove(ks_treemapnode** tmn, const ks_datacont* key) { 91 | if (tmn == NULL || *tmn == NULL || key == NULL) return -1; 92 | 93 | enum ks_comparison result = ks_datacont_compare(key, (*tmn)->key); 94 | 95 | if (result == KS_EQUAL) { 96 | if ((*tmn)->left != NULL && (*tmn)->right != NULL) { 97 | ks_treemapnode** leftmost = &(*tmn)->right; 98 | while ((*leftmost)->left) leftmost = &(*leftmost)->left; 99 | ks_datacont_delete((*tmn)->key); 100 | ks_datacont_delete((*tmn)->value); 101 | (*tmn)->key = ks_datacont_copy((*leftmost)->key); 102 | (*tmn)->value = ks_datacont_copy((*leftmost)->value); 103 | return ks_treemapnode_remove(leftmost, (*leftmost)->key); 104 | } else if ((*tmn)->left) { 105 | ks_datacont_delete((*tmn)->key); 106 | ks_datacont_delete((*tmn)->value); 107 | (*tmn)->key = ks_datacont_copy((*tmn)->left->key); 108 | (*tmn)->value = ks_datacont_copy((*tmn)->left->value); 109 | return ks_treemapnode_remove(&(*tmn)->left, (*tmn)->left->key); 110 | } else if ((*tmn)->right) { 111 | ks_datacont_delete((*tmn)->key); 112 | ks_datacont_delete((*tmn)->value); 113 | (*tmn)->key = ks_datacont_copy((*tmn)->right->key); 114 | (*tmn)->value = ks_datacont_copy((*tmn)->right->value); 115 | return ks_treemapnode_remove(&(*tmn)->right, (*tmn)->right->key); 116 | } else { 117 | ks_treemapnode_delete(*tmn); 118 | *tmn = NULL; 119 | return 0; 120 | } 121 | } else if (result == KS_LESSTHAN) 122 | return ks_treemapnode_remove(&(*tmn)->left, key); 123 | else if (result == KS_GREATERTHAN) 124 | return ks_treemapnode_remove(&(*tmn)->right, key); 125 | return 1; 126 | } 127 | 128 | const ks_datacont* ks_treemapnode_get(const ks_treemapnode* tmn, 129 | const ks_datacont* key) { 130 | if (tmn == NULL || key == NULL) return NULL; 131 | 132 | enum ks_comparison result = ks_datacont_compare(key, tmn->key); 133 | 134 | if (result == KS_EQUAL) 135 | return tmn->value; 136 | 137 | else if (result == KS_LESSTHAN) 138 | return ks_treemapnode_get(tmn->left, key); 139 | 140 | else if (result == KS_GREATERTHAN) 141 | return ks_treemapnode_get(tmn->right, key); 142 | 143 | return NULL; 144 | } 145 | 146 | static ks_datacont* __ks_treemapnode_get_key(const ks_treemapnode* tmn, 147 | int index, int* curr_index) { 148 | if (tmn == NULL) return NULL; 149 | 150 | ks_treemapnode* first = index < 0 ? tmn->right : tmn->left; 151 | ks_treemapnode* second = index < 0 ? tmn->left : tmn->right; 152 | 153 | ks_datacont* key; 154 | 155 | if ((key = __ks_treemapnode_get_key(first, index, curr_index)) != NULL) 156 | return key; 157 | 158 | index < 0 ? (*curr_index)-- : (*curr_index)++; 159 | 160 | if (*curr_index == index) return tmn->key; 161 | 162 | return __ks_treemapnode_get_key(second, index, curr_index); 163 | } 164 | 165 | const ks_datacont* ks_treemapnode_get_key(const ks_treemapnode* tmn, 166 | int index) { 167 | int curr_index = index < 0 ? 0 : -1; 168 | 169 | return __ks_treemapnode_get_key(tmn, index, &curr_index); 170 | } 171 | 172 | unsigned int ks_treemapnode_count(const ks_treemapnode* tmn) { 173 | if (tmn == NULL) return 0; 174 | 175 | return 1 + ks_treemapnode_count(tmn->left) + 176 | ks_treemapnode_count(tmn->right); 177 | } 178 | 179 | unsigned int ks_treemapnode_height(const ks_treemapnode* tmn) { 180 | if (tmn == NULL) return 0; 181 | 182 | unsigned int left_height = ks_treemapnode_height(tmn->left); 183 | 184 | unsigned int right_height = ks_treemapnode_height(tmn->right); 185 | 186 | return 1 + (left_height > right_height ? left_height : right_height); 187 | } 188 | 189 | static ks_treemapnode* __ks_treemapnode_balance(ks_treemapnode* tmn, int start, 190 | int end) { 191 | if (start > end) return NULL; 192 | 193 | int mid = (start + end) / 2; 194 | 195 | ks_datacont* key = ks_datacont_copy(ks_treemapnode_get_key(tmn, mid)); 196 | ks_datacont* val = ks_datacont_copy(ks_treemapnode_get(tmn, key)); 197 | ks_treemapnode* root = ks_treemapnode_new(key, val); 198 | 199 | root->left = __ks_treemapnode_balance(tmn, start, mid - 1); 200 | root->right = __ks_treemapnode_balance(tmn, mid + 1, end); 201 | 202 | return root; 203 | } 204 | 205 | ks_treemapnode* ks_treemapnode_balance(ks_treemapnode* root) { 206 | if (root == NULL) return NULL; 207 | 208 | int count = ks_treemapnode_count(root); 209 | 210 | ks_treemapnode* balanced = __ks_treemapnode_balance(root, 0, count - 1); 211 | 212 | ks_treemapnode_delete_all(root); 213 | 214 | return balanced; 215 | } 216 | -------------------------------------------------------------------------------- /src/ks_treeset.c: -------------------------------------------------------------------------------- 1 | #include "kylestructs/ks_treeset.h" 2 | 3 | #include 4 | 5 | #include "kylestructs/ks_datacont.h" 6 | #include "kylestructs/ks_hashset.h" 7 | #include "kylestructs/ks_treesetnode.h" 8 | #include "kylestructs/ks_types.h" 9 | 10 | ks_treeset* ks_treeset_new() { return calloc(1, sizeof(ks_treeset)); } 11 | 12 | void ks_treeset_delete(ks_treeset* ts) { 13 | if (ts == NULL) return; 14 | 15 | ks_treesetnode_delete_all(ts->root); 16 | 17 | free(ts); 18 | } 19 | 20 | ks_treeset* ks_treeset_copy(const ks_treeset* ts) { 21 | if (ts == NULL) return NULL; 22 | 23 | ks_treeset* ts_copy = ks_treeset_new(); 24 | 25 | ts_copy->root = ks_treesetnode_copy_all(ts->root); 26 | 27 | return ts_copy; 28 | } 29 | 30 | int ks_treeset_add(ks_treeset* ts, const ks_datacont* dc) { 31 | if (ts == NULL || dc == NULL) return -1; 32 | 33 | switch (dc->type) { 34 | case KS_VOIDP: 35 | case KS_LIST: 36 | case KS_TREESET: 37 | case KS_HASHSET: 38 | case KS_TREEMAP: 39 | case KS_HASHMAP: 40 | return -1; 41 | default: 42 | break; 43 | } 44 | 45 | if (ts->root == NULL) { 46 | ts->root = ks_treesetnode_new(dc); 47 | return 0; 48 | } 49 | return ks_treesetnode_add(ts->root, dc); 50 | } 51 | 52 | int ks_treeset_remove_by(ks_treeset* ts, const ks_datacont* dc) { 53 | if (ts == NULL || dc == NULL) return -1; 54 | 55 | return ks_treesetnode_remove_by(&ts->root, dc); 56 | } 57 | 58 | int ks_treeset_remove_at(ks_treeset* ts, int index) { 59 | if (ts == NULL) return -1; 60 | 61 | return ks_treesetnode_remove_at(&ts->root, index); 62 | } 63 | 64 | int ks_treeset_index(const ks_treeset* ts, const ks_datacont* dc) { 65 | if (ts == NULL || dc == NULL) return -1; 66 | 67 | return ks_treesetnode_index(ts->root, dc); 68 | } 69 | 70 | unsigned int ks_treeset_contains(const ks_treeset* ts, const ks_datacont* dc) { 71 | if (ts == NULL || dc == NULL) return 0; 72 | 73 | return ks_treesetnode_contains(ts->root, dc); 74 | } 75 | 76 | const ks_datacont* ks_treeset_get(const ks_treeset* ts, int index) { 77 | if (ts == NULL) return NULL; 78 | 79 | return ks_treesetnode_get(ts->root, index); 80 | } 81 | 82 | unsigned int ks_treeset_count(const ks_treeset* ts) { 83 | if (ts == NULL) return 0; 84 | 85 | return ks_treesetnode_count(ts->root); 86 | } 87 | 88 | unsigned int ks_treeset_height(const ks_treeset* ts) { 89 | if (ts == NULL) return 0; 90 | 91 | return ks_treesetnode_height(ts->root); 92 | } 93 | 94 | void ks_treeset_balance(ks_treeset* ts) { 95 | if (ts == NULL) return; 96 | 97 | ts->root = ks_treesetnode_balance(ts->root); 98 | } 99 | -------------------------------------------------------------------------------- /src/ks_treesetnode.c: -------------------------------------------------------------------------------- 1 | #include "kylestructs/ks_treesetnode.h" 2 | 3 | #include 4 | 5 | #include "kylestructs/ks_datacont.h" 6 | #include "kylestructs/ks_types.h" 7 | 8 | ks_treesetnode* ks_treesetnode_new(const ks_datacont* dc) { 9 | if (dc == NULL) return NULL; 10 | 11 | ks_treesetnode* tsn = calloc(1, sizeof(ks_treesetnode)); 12 | 13 | tsn->dc = (ks_datacont*)dc; 14 | 15 | return tsn; 16 | } 17 | 18 | void ks_treesetnode_delete(ks_treesetnode* tsn) { 19 | if (tsn == NULL) return; 20 | 21 | ks_datacont_delete(tsn->dc); 22 | 23 | free(tsn); 24 | } 25 | 26 | ks_treesetnode* ks_treesetnode_copy(const ks_treesetnode* tsn) { 27 | if (tsn == NULL) return NULL; 28 | 29 | ks_datacont* dc = ks_datacont_copy(tsn->dc); 30 | 31 | return ks_treesetnode_new(dc); 32 | } 33 | 34 | void ks_treesetnode_delete_all(ks_treesetnode* tsn) { 35 | if (tsn == NULL) return; 36 | 37 | ks_treesetnode_delete_all(tsn->left); 38 | 39 | ks_treesetnode_delete_all(tsn->right); 40 | 41 | ks_treesetnode_delete(tsn); 42 | } 43 | 44 | ks_treesetnode* ks_treesetnode_copy_all(const ks_treesetnode* tsn) { 45 | if (tsn == NULL) return NULL; 46 | 47 | ks_treesetnode* tsn_copy = ks_treesetnode_copy(tsn); 48 | 49 | tsn_copy->left = ks_treesetnode_copy_all(tsn->left); 50 | tsn_copy->right = ks_treesetnode_copy_all(tsn->right); 51 | 52 | return tsn_copy; 53 | } 54 | 55 | int ks_treesetnode_add(ks_treesetnode* tsn, const ks_datacont* dc) { 56 | if (tsn == NULL || dc == NULL) return -1; 57 | 58 | enum ks_comparison result = ks_datacont_compare(dc, tsn->dc); 59 | 60 | if (result == KS_EQUAL) return 1; 61 | if (result == KS_CANTCOMPARE) 62 | return -1; 63 | 64 | else if (result == KS_LESSTHAN) { 65 | if (tsn->left) 66 | return ks_treesetnode_add(tsn->left, dc); 67 | else 68 | tsn->left = ks_treesetnode_new(dc); 69 | } else { 70 | if (tsn->right) 71 | return ks_treesetnode_add(tsn->right, dc); 72 | else 73 | tsn->right = ks_treesetnode_new(dc); 74 | } 75 | return 0; 76 | } 77 | 78 | int ks_treesetnode_remove_by(ks_treesetnode** tsn, const ks_datacont* dc) { 79 | if (tsn == NULL || *tsn == NULL || dc == NULL) return -1; 80 | 81 | enum ks_comparison result = ks_datacont_compare(dc, (*tsn)->dc); 82 | 83 | if (result == KS_EQUAL) { 84 | if ((*tsn)->left != NULL && (*tsn)->right != NULL) { 85 | ks_treesetnode** leftmost = &(*tsn)->right; 86 | while ((*leftmost)->left) leftmost = &(*leftmost)->left; 87 | ks_datacont_delete((*tsn)->dc); 88 | (*tsn)->dc = ks_datacont_copy((*leftmost)->dc); 89 | return ks_treesetnode_remove_by(leftmost, (*leftmost)->dc); 90 | } else if ((*tsn)->left) { 91 | ks_datacont_delete((*tsn)->dc); 92 | (*tsn)->dc = ks_datacont_copy((*tsn)->left->dc); 93 | return ks_treesetnode_remove_by(&(*tsn)->left, (*tsn)->left->dc); 94 | } else if ((*tsn)->right) { 95 | ks_datacont_delete((*tsn)->dc); 96 | (*tsn)->dc = ks_datacont_copy((*tsn)->right->dc); 97 | return ks_treesetnode_remove_by(&(*tsn)->right, (*tsn)->right->dc); 98 | } else { 99 | ks_treesetnode_delete(*tsn); 100 | *tsn = NULL; 101 | return 0; 102 | } 103 | } else if (result == KS_LESSTHAN) 104 | return ks_treesetnode_remove_by(&(*tsn)->left, dc); 105 | else if (result == KS_GREATERTHAN) 106 | return ks_treesetnode_remove_by(&(*tsn)->right, dc); 107 | return -1; 108 | } 109 | 110 | static int __ks_treesetnode_remove_at(ks_treesetnode** tsn, int index, 111 | int* curr_index) { 112 | if (tsn == NULL || *tsn == NULL) return -1; 113 | 114 | if (index < 0 && 115 | (__ks_treesetnode_remove_at(&(*tsn)->right, index, curr_index) == 0)) 116 | return 0; 117 | 118 | else if (__ks_treesetnode_remove_at(&(*tsn)->left, index, curr_index) == 0) 119 | return 0; 120 | 121 | if (*curr_index == index) return ks_treesetnode_remove_by(tsn, (*tsn)->dc); 122 | 123 | index < 0 ? (*curr_index)-- : (*curr_index)++; 124 | 125 | if (index < 0) 126 | return __ks_treesetnode_remove_at(&(*tsn)->left, index, curr_index); 127 | 128 | return __ks_treesetnode_remove_at(&(*tsn)->right, index, curr_index); 129 | } 130 | 131 | int ks_treesetnode_remove_at(ks_treesetnode** tsn, int index) { 132 | int curr_index; 133 | 134 | if (index < 0) 135 | curr_index = -1; 136 | else 137 | curr_index = 0; 138 | 139 | return __ks_treesetnode_remove_at(tsn, index, &curr_index); 140 | } 141 | 142 | static int __ks_treesetnode_index(const ks_treesetnode* tsn, 143 | const ks_datacont* dc, int* curr_index) { 144 | if (tsn == NULL) return -1; 145 | 146 | int index; 147 | if ((index = __ks_treesetnode_index(tsn->left, dc, curr_index)) > -1) 148 | return index; 149 | 150 | if (ks_datacont_compare(dc, tsn->dc) == KS_EQUAL) return *curr_index; 151 | 152 | (*curr_index)++; 153 | 154 | return __ks_treesetnode_index(tsn->right, dc, curr_index); 155 | } 156 | 157 | int ks_treesetnode_index(const ks_treesetnode* tsn, const ks_datacont* dc) { 158 | int curr_index = 0; 159 | 160 | return __ks_treesetnode_index(tsn, dc, &curr_index); 161 | } 162 | 163 | unsigned int ks_treesetnode_contains(const ks_treesetnode* tsn, 164 | const ks_datacont* dc) { 165 | if (tsn == NULL || dc == NULL) return 0; 166 | 167 | enum ks_comparison result = ks_datacont_compare(dc, tsn->dc); 168 | 169 | if (result == KS_EQUAL) return 1; 170 | 171 | if (result == KS_GREATERTHAN) 172 | return ks_treesetnode_contains(tsn->right, dc); 173 | 174 | return ks_treesetnode_contains(tsn->left, dc); 175 | } 176 | 177 | static ks_datacont* __ks_treesetnode_get(const ks_treesetnode* tsn, int index, 178 | int* curr_index) { 179 | if (tsn == NULL) return NULL; 180 | 181 | ks_treesetnode* first = index < 0 ? tsn->right : tsn->left; 182 | ks_treesetnode* second = index < 0 ? tsn->left : tsn->right; 183 | 184 | ks_datacont* dc; 185 | 186 | if ((dc = __ks_treesetnode_get(first, index, curr_index)) != NULL) 187 | return dc; 188 | 189 | index < 0 ? (*curr_index)-- : (*curr_index)++; 190 | 191 | if (*curr_index == index) return tsn->dc; 192 | 193 | return __ks_treesetnode_get(second, index, curr_index); 194 | } 195 | 196 | const ks_datacont* ks_treesetnode_get(const ks_treesetnode* tsn, int index) { 197 | int curr_index = index < 0 ? 0 : -1; 198 | 199 | return __ks_treesetnode_get(tsn, index, &curr_index); 200 | } 201 | 202 | unsigned int ks_treesetnode_count(const ks_treesetnode* tsn) { 203 | if (tsn == NULL) return 0; 204 | 205 | return 1 + ks_treesetnode_count(tsn->left) + 206 | ks_treesetnode_count(tsn->right); 207 | } 208 | 209 | unsigned int ks_treesetnode_height(const ks_treesetnode* tsn) { 210 | if (tsn == NULL) return 0; 211 | 212 | unsigned int left_height = ks_treesetnode_height(tsn->left); 213 | 214 | unsigned int right_height = ks_treesetnode_height(tsn->right); 215 | 216 | return 1 + (left_height > right_height ? left_height : right_height); 217 | } 218 | 219 | static ks_treesetnode* __ks_treesetnode_balance(ks_treesetnode* tsn, int start, 220 | int end) { 221 | if (start > end) return NULL; 222 | 223 | int mid = (start + end) / 2; 224 | 225 | ks_datacont* dc = ks_datacont_copy(ks_treesetnode_get(tsn, mid)); 226 | ks_treesetnode* root = ks_treesetnode_new(dc); 227 | 228 | root->left = __ks_treesetnode_balance(tsn, start, mid - 1); 229 | root->right = __ks_treesetnode_balance(tsn, mid + 1, end); 230 | 231 | return root; 232 | } 233 | 234 | ks_treesetnode* ks_treesetnode_balance(ks_treesetnode* root) { 235 | if (root == NULL) return NULL; 236 | 237 | int count = ks_treesetnode_count(root); 238 | 239 | ks_treesetnode* balanced = __ks_treesetnode_balance(root, 0, count - 1); 240 | 241 | ks_treesetnode_delete_all(root); 242 | 243 | return balanced; 244 | } 245 | -------------------------------------------------------------------------------- /testbin/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/datacont_tests.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "kylestructs/ks_datacont.h" 4 | #include "kylestructs/ks_hashmap.h" 5 | #include "kylestructs/ks_hashset.h" 6 | #include "kylestructs/ks_list.h" 7 | #include "kylestructs/ks_listnode.h" 8 | #include "kylestructs/ks_treemap.h" 9 | #include "kylestructs/ks_treemapnode.h" 10 | #include "kylestructs/ks_treeset.h" 11 | #include "kylestructs/ks_treesetnode.h" 12 | #include "kylestructs/ks_types.h" 13 | 14 | static int ks_datacont_new_tests() { 15 | int retval = 0; 16 | 17 | /* Test 1 */ 18 | ks_datacont* char_cont = ks_datacont_new("A", KS_CHAR, 1); 19 | if (char_cont->type != KS_CHAR) { 20 | printf("TEST 1: Unexpected container type: %d. Expected: %d\n", 21 | char_cont->type, KS_CHAR); 22 | retval = -1; 23 | } 24 | if (char_cont->size != 1) { 25 | printf("TEST 1: Unexpected size value: %ld. Expected: %d\n", 26 | char_cont->size, 1); 27 | retval = -1; 28 | } 29 | if (char_cont->c != 'A') { 30 | printf("TEST 1: Unexpected container value: %c. Expected: %c\n", 31 | char_cont->c, 'A'); 32 | retval = -1; 33 | } 34 | ks_datacont_delete(char_cont); 35 | 36 | /* Test 2 */ 37 | unsigned int num = 0x12345678; 38 | ks_datacont* uint_cont = ks_datacont_new(&num, KS_UINT, 1); 39 | if (uint_cont->type != KS_UINT) { 40 | printf("TEST 2: Unexpected container type: %d. Expected: %d\n", 41 | uint_cont->type, KS_UINT); 42 | retval = -1; 43 | } 44 | if (uint_cont->size != 1) { 45 | printf("TEST 2: Unexpected size value: %ld. Expected: %d\n", 46 | uint_cont->size, 1); 47 | retval = -1; 48 | } 49 | if (uint_cont->ui != num) { 50 | printf("TEST 2: Unexpected container value: %d. Expected: %d\n", 51 | uint_cont->ui, num); 52 | retval = -1; 53 | } 54 | ks_datacont_delete(uint_cont); 55 | 56 | return retval; 57 | } 58 | 59 | static int ks_datacont_copy_tests() { 60 | int retval = 0; 61 | 62 | int num = 1234; 63 | ks_datacont* dc1 = ks_datacont_new(&num, KS_INT, 1); 64 | ks_datacont* dc2 = ks_datacont_copy(dc1); 65 | 66 | /* TEST 1 */ 67 | if (dc1 == dc2) { 68 | printf( 69 | "TEST 1: ks_datacont_copy() should return different reference.\n"); 70 | retval = -1; 71 | } 72 | 73 | /* TEST 2 */ 74 | enum ks_comparison result = ks_datacont_compare(dc1, dc2); 75 | if (result != KS_EQUAL) { 76 | printf( 77 | "TEST 2: dc1 and dc2 should be equal. ks_datacont_compare() " 78 | "returned: " 79 | "%d.\n", 80 | result); 81 | printf("\ndc1->type = %d\n", dc1->type); 82 | printf("dc2->type = %d\n", dc2->type); 83 | printf("\ndc1->size = %ld\n", dc1->size); 84 | printf("dc2->size = %ld\n", dc2->size); 85 | printf("\ndc1->cp = %s\n", dc1->cp); 86 | printf("dc2->cp = %s\n", dc2->cp); 87 | retval = -1; 88 | } 89 | 90 | ks_datacont_delete(dc1); 91 | ks_datacont_delete(dc2); 92 | 93 | return retval; 94 | } 95 | 96 | static int ks_datacont_compare_tests() { 97 | int retval = 0; 98 | int num; 99 | enum ks_comparison result; 100 | ks_datacont* dca; 101 | ks_datacont* dcb; 102 | 103 | /* Test 1 */ 104 | num = 10; 105 | dca = ks_datacont_new(&num, KS_INT, 1); 106 | num = 11; 107 | dcb = ks_datacont_new(&num, KS_INT, 1); 108 | result = ks_datacont_compare(dca, dcb); 109 | if (result != KS_LESSTHAN) { 110 | printf("TEST 1: Unexpected comparison result: %d. Expected: %d\n", 111 | result, KS_LESSTHAN); 112 | retval = -1; 113 | } 114 | ks_datacont_delete(dca); 115 | ks_datacont_delete(dcb); 116 | 117 | /* Test 2 */ 118 | dca = ks_datacont_new("A", KS_CHAR, 1); 119 | dcb = ks_datacont_new("A", KS_CHAR, 1); 120 | result = ks_datacont_compare(dca, dcb); 121 | if (result != KS_EQUAL) { 122 | printf("TEST 2: Unexpected comparison result: %d. Expected: %d\n", 123 | result, KS_EQUAL); 124 | retval = -1; 125 | } 126 | ks_datacont_delete(dca); 127 | ks_datacont_delete(dcb); 128 | 129 | /* Test 3 */ 130 | char* str = "TESTSTRING"; 131 | dca = ks_datacont_new(str, KS_CHARP, 10); 132 | dcb = ks_datacont_new(&num, KS_INT, 1); 133 | result = ks_datacont_compare(dca, dcb); 134 | if (result != KS_CANTCOMPARE) { 135 | printf("TEST 3: Unexpected comparison result: %d. Expected: %d\n", 136 | result, KS_CANTCOMPARE); 137 | retval = -1; 138 | } 139 | ks_datacont_delete(dca); 140 | ks_datacont_delete(dcb); 141 | 142 | /* TEST 4 */ 143 | short arr1[3] = {0xfff0, 0xffff, 0xffff}; 144 | short arr2[2] = {0xffff, 0xffff}; 145 | 146 | ks_datacont* dcc = ks_datacont_new(arr1, KS_SHORTP, 3); 147 | ks_datacont* dcd = ks_datacont_new(arr2, KS_SHORTP, 2); 148 | 149 | result = ks_datacont_compare(dcc, dcd); 150 | 151 | if (result != KS_LESSTHAN) { 152 | printf("TEST 4: Unexpected comparison result: %d. Expected: %d\n", 153 | result, KS_CANTCOMPARE); 154 | retval = -1; 155 | } 156 | 157 | ks_datacont_delete(dcc); 158 | ks_datacont_delete(dcd); 159 | 160 | return retval; 161 | } 162 | 163 | static int ks_datacont_hash_tests() { 164 | /* tough to test hashes... 165 | * probably just make sure hashes of the 166 | * same value are equal. 167 | */ 168 | int retval = 0; 169 | ks_datacont* dc1 = ks_datacont_new("abcd", KS_CHARP, 5); 170 | ks_datacont* dc2 = ks_datacont_new("abcd", KS_CHARP, 5); 171 | unsigned int hash1 = ks_datacont_hash(dc1); 172 | unsigned int hash2 = ks_datacont_hash(dc2); 173 | if (hash1 != hash2) { 174 | printf("TEST 1: Unexpected hash result: %X. Expected: %X\n", hash2, 175 | hash1); 176 | retval = -1; 177 | } 178 | ks_datacont_delete(dc1); 179 | ks_datacont_delete(dc2); 180 | return retval; 181 | } 182 | 183 | int main() { 184 | int retval = 0; 185 | 186 | printf("\nks_datacont tests:\n\n"); 187 | 188 | printf("==-----------------------------------==\n"); 189 | printf("Running ks_datacont_new_tests()...\n"); 190 | if (ks_datacont_new_tests()) retval = -1; 191 | printf("done.\n"); 192 | printf("==-----------------------------------==\n\n"); 193 | 194 | printf("==-----------------------------------==\n"); 195 | printf("Running ks_datacont_copy_tests()...\n"); 196 | if (ks_datacont_copy_tests()) retval = -1; 197 | printf("done.\n"); 198 | printf("==-----------------------------------==\n\n"); 199 | 200 | printf("==-----------------------------------==\n"); 201 | printf("Running ks_datacont_compare_tests()...\n"); 202 | if (ks_datacont_compare_tests()) retval = -1; 203 | printf("done.\n"); 204 | printf("==-----------------------------------==\n\n"); 205 | 206 | printf("==-----------------------------------==\n"); 207 | printf("Running ks_datacont_hash_tests()...\n"); 208 | if (ks_datacont_hash_tests()) retval = -1; 209 | printf("done.\n"); 210 | printf("==-----------------------------------==\n\n"); 211 | 212 | return retval; 213 | } 214 | -------------------------------------------------------------------------------- /tests/hashmap_tests.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "kylestructs/ks_datacont.h" 4 | #include "kylestructs/ks_hashmap.h" 5 | #include "kylestructs/ks_list.h" 6 | #include "kylestructs/ks_listnode.h" 7 | #include "kylestructs/ks_treemap.h" 8 | #include "kylestructs/ks_treemapnode.h" 9 | #include "kylestructs/ks_types.h" 10 | 11 | static int ks_hashmap_new_tests() { 12 | int retval = 0; 13 | 14 | /* TEST 1 */ 15 | ks_hashmap* hm = ks_hashmap_new(KS_INT, 10); 16 | 17 | if (hm->type != KS_INT) { 18 | printf("TEST 1: Unexpected type value: %d. Expected %d.\n", hm->type, 19 | KS_INT); 20 | retval = -1; 21 | } 22 | 23 | if (hm->num_buckets != 10) { 24 | printf("TEST 1: Unexpected num_buckets value: %d. Expected: 10.\n", 25 | hm->num_buckets); 26 | retval = -1; 27 | } 28 | ks_hashmap_delete(hm); 29 | 30 | return retval; 31 | } 32 | 33 | static int ks_hashmap_copy_tests() { 34 | int retval = 0; 35 | 36 | /* TEST 1 */ 37 | ks_hashmap* hm = ks_hashmap_new(KS_CHAR, 2); 38 | ks_hashmap_add(hm, ks_datacont_new("B", KS_CHAR, 1), 39 | ks_datacont_new("B", KS_CHAR, 1)); 40 | 41 | ks_hashmap* hm_copy = ks_hashmap_copy(hm); 42 | 43 | if (hm_copy == NULL) { 44 | printf( 45 | "TEST 1: Unexpected NULL return from ks_hashmap_copy() result\n"); 46 | return -1; 47 | } 48 | 49 | if (hm_copy->buckets[0] != NULL) { 50 | if (hm_copy->buckets[0]->root->key->c != 'B') { 51 | printf( 52 | "TEST 1: Unexpected ks_datacont value in ks_hashmap_copy() " 53 | "result\n"); 54 | retval = -1; 55 | } 56 | } else if (hm_copy->buckets[1] != NULL) { 57 | if (hm_copy->buckets[1]->root->key->c != 'B') { 58 | printf( 59 | "TEST 1: Unexpected ks_datacont value in ks_hashmap_copy() " 60 | "result\n"); 61 | retval = -1; 62 | } 63 | } else { 64 | printf("TEST 1: Unexpected empty ks_hashmap after ks_hashmap_copy()\n"); 65 | retval = -1; 66 | } 67 | 68 | ks_hashmap_delete(hm); 69 | ks_hashmap_delete(hm_copy); 70 | 71 | return retval; 72 | } 73 | 74 | static int ks_hashmap_add_tests() { 75 | int retval = 0; 76 | 77 | /* TEST 1 */ 78 | ks_hashmap* hm = ks_hashmap_new(KS_INT, 10); 79 | 80 | int one = 1; 81 | ks_datacont* key = ks_datacont_new(&one, KS_INT, 1); 82 | ks_datacont* val = ks_datacont_new("A", KS_CHAR, 1); 83 | ks_datacont* key_copy = ks_datacont_copy(key); 84 | ks_datacont* val2 = ks_datacont_new("C", KS_CHAR, 1); 85 | 86 | if (ks_hashmap_add(hm, key, val) != 0) { 87 | printf( 88 | "TEST 1: ks_hashmap_add() should return 0 when adding a new " 89 | "pair.\n"); 90 | retval = -1; 91 | } 92 | 93 | /* TEST 2 */ 94 | if (ks_hashmap_add(hm, key_copy, val2) != 1) { 95 | printf( 96 | "TEST 2: ks_hashmap_add() should return 1 when replacing an " 97 | "existing " 98 | "pair.\n"); 99 | retval = -1; 100 | } 101 | 102 | ks_hashmap_delete(hm); 103 | 104 | return retval; 105 | } 106 | 107 | static int ks_hashmap_remove_tests() { 108 | int retval = 0; 109 | 110 | /* TEST 1 */ 111 | ks_hashmap* hm = ks_hashmap_new(KS_INT, 20); 112 | 113 | int one = 1; 114 | ks_datacont* key = ks_datacont_new(&one, KS_INT, 1); 115 | ks_datacont* key_copy = ks_datacont_copy(key); 116 | ks_datacont* val = ks_datacont_new("A", KS_CHAR, 1); 117 | 118 | ks_hashmap_add(hm, key, val); 119 | 120 | if (ks_hashmap_remove(hm, key) != 0) { 121 | printf( 122 | "TEST 1: ks_hashmap_remove() should return 0 on removal of " 123 | "existing " 124 | "pair.\n"); 125 | retval = -1; 126 | } 127 | if (ks_hashmap_remove(hm, key_copy) != -1) { 128 | printf( 129 | "TEST 2: ks_hashmap_remove() should return -1 when removing " 130 | "not-present pair.\n"); 131 | retval = -1; 132 | } 133 | 134 | ks_datacont_delete(key_copy); 135 | ks_hashmap_delete(hm); 136 | 137 | return retval; 138 | } 139 | 140 | static int ks_hashmap_get_tests() { 141 | int retval = 0; 142 | 143 | /* TEST 1 */ 144 | ks_hashmap* hm = ks_hashmap_new(KS_INT, 10); 145 | 146 | int one = 1; 147 | ks_datacont* key = ks_datacont_new(&one, KS_INT, 1); 148 | ks_datacont* val = ks_datacont_new("A", KS_CHAR, 1); 149 | 150 | ks_hashmap_add(hm, key, val); 151 | 152 | const ks_datacont* ret = ks_hashmap_get(hm, key); 153 | if (ks_datacont_compare(val, ret) != KS_EQUAL) { 154 | printf("TEST 1: unexpected ks_datacont value: %c. Expected: A.\n", 155 | ret->c); 156 | retval = -1; 157 | } 158 | 159 | ks_hashmap_delete(hm); 160 | 161 | return retval; 162 | } 163 | 164 | static int ks_hashmap_get_key_tests() { 165 | int retval = 0; 166 | 167 | /* TEST 1 */ 168 | ks_hashmap* hm = ks_hashmap_new(KS_CHAR, 2); 169 | 170 | ks_treemap* tm0 = ks_treemap_new(); 171 | ks_treemap_add(tm0, ks_datacont_new("B", KS_CHAR, 1), 172 | ks_datacont_new("B", KS_CHAR, 1)); 173 | ks_treemap_add(tm0, ks_datacont_new("A", KS_CHAR, 1), 174 | ks_datacont_new("A", KS_CHAR, 1)); 175 | ks_treemap_add(tm0, ks_datacont_new("C", KS_CHAR, 1), 176 | ks_datacont_new("C", KS_CHAR, 1)); 177 | 178 | ks_treemap* tm1 = ks_treemap_new(); 179 | ks_treemap_add(tm1, ks_datacont_new("E", KS_CHAR, 1), 180 | ks_datacont_new("E", KS_CHAR, 1)); 181 | ks_treemap_add(tm1, ks_datacont_new("D", KS_CHAR, 1), 182 | ks_datacont_new("D", KS_CHAR, 1)); 183 | ks_treemap_add(tm1, ks_datacont_new("F", KS_CHAR, 1), 184 | ks_datacont_new("F", KS_CHAR, 1)); 185 | 186 | hm->buckets[0] = tm0; 187 | hm->buckets[1] = tm1; 188 | 189 | const ks_datacont* dc = ks_hashmap_get_key(hm, -1); 190 | if (dc->c != 'F') { 191 | printf( 192 | "TEST 1: Unexpected ks_datacont value after ks_hashmap_get_key(): " 193 | "%c. " 194 | "Expected: 'F'\n", 195 | dc->c); 196 | retval = -1; 197 | } 198 | 199 | dc = ks_hashmap_get_key(hm, 5); 200 | if (dc->c != 'F') { 201 | printf( 202 | "TEST 1: Unexpected ks_datacont value after ks_hashmap_get_key(): " 203 | "%c. " 204 | "Expected: 'F'\n", 205 | dc->c); 206 | retval = -1; 207 | } 208 | 209 | dc = ks_hashmap_get_key(hm, -3); 210 | if (dc->c != 'D') { 211 | printf( 212 | "TEST 1: Unexpected ks_datacont value after ks_hashmap_get_key(): " 213 | "%c. " 214 | "Expected: 'D'\n", 215 | dc->c); 216 | retval = -1; 217 | } 218 | 219 | dc = ks_hashmap_get_key(hm, 3); 220 | if (dc->c != 'D') { 221 | printf( 222 | "TEST 1: Unexpected ks_datacont value after ks_hashmap_get_key(): " 223 | "%c. " 224 | "Expected: 'D'\n", 225 | dc->c); 226 | retval = -1; 227 | } 228 | 229 | dc = ks_hashmap_get_key(hm, -4); 230 | if (dc->c != 'C') { 231 | printf( 232 | "TEST 1: Unexpected ks_datacont value after ks_hashmap_get_key(): " 233 | "%c. " 234 | "Expected: 'C'\n", 235 | dc->c); 236 | retval = -1; 237 | } 238 | 239 | dc = ks_hashmap_get_key(hm, 2); 240 | if (dc->c != 'C') { 241 | printf( 242 | "TEST 1: Unexpected ks_datacont value after ks_hashmap_get_key(): " 243 | "%c. " 244 | "Expected: 'C'\n", 245 | dc->c); 246 | retval = -1; 247 | } 248 | 249 | dc = ks_hashmap_get_key(hm, -6); 250 | if (dc->c != 'A') { 251 | printf( 252 | "TEST 1: Unexpected ks_datacont value after ks_hashmap_get_key(): " 253 | "%c. " 254 | "Expected: 'A'\n", 255 | dc->c); 256 | retval = -1; 257 | } 258 | 259 | dc = ks_hashmap_get_key(hm, 0); 260 | if (dc->c != 'A') { 261 | printf( 262 | "TEST 1: Unexpected ks_datacont value after ks_hashmap_get_key(): " 263 | "%c. " 264 | "Expected: 'A'\n", 265 | dc->c); 266 | retval = -1; 267 | } 268 | 269 | ks_hashmap_delete(hm); 270 | 271 | return retval; 272 | } 273 | 274 | static int ks_hashmap_count_tests() { 275 | int retval = 0; 276 | 277 | /* TEST 1 */ 278 | ks_hashmap* hm = ks_hashmap_new(KS_INT, 10); 279 | 280 | int one = 1; 281 | ks_hashmap_add(hm, ks_datacont_new(&one, KS_INT, 1), 282 | ks_datacont_new("A", KS_CHAR, 1)); 283 | 284 | int count = ks_hashmap_count(hm); 285 | if (count != 1) { 286 | printf( 287 | "TEST 1: Unexpected ks_hashmap_count() return value: %d. Expected " 288 | "1.\n", 289 | count); 290 | retval = -1; 291 | } 292 | 293 | ks_hashmap_delete(hm); 294 | 295 | return retval; 296 | } 297 | 298 | int main() { 299 | int retval = 0; 300 | 301 | printf("\nks_hashmap tests:\n\n"); 302 | 303 | printf("==-----------------------------------==\n"); 304 | printf("Running ks_hashmap_new_tests()...\n"); 305 | if (ks_hashmap_new_tests()) retval = -1; 306 | printf("done.\n"); 307 | printf("==-----------------------------------==\n\n"); 308 | 309 | printf("==-----------------------------------==\n"); 310 | printf("Running ks_hashmap_copy_tests()...\n"); 311 | if (ks_hashmap_copy_tests()) retval = -1; 312 | printf("done.\n"); 313 | printf("==-----------------------------------==\n\n"); 314 | 315 | printf("==-----------------------------------==\n"); 316 | printf("Running ks_hashmap_add_tests()...\n"); 317 | if (ks_hashmap_add_tests()) retval = -1; 318 | printf("done.\n"); 319 | printf("==-----------------------------------==\n\n"); 320 | 321 | printf("==-----------------------------------==\n"); 322 | printf("Running ks_hashmap_remove_tests()...\n"); 323 | if (ks_hashmap_remove_tests()) retval = -1; 324 | printf("done.\n"); 325 | printf("==-----------------------------------==\n\n"); 326 | 327 | printf("==-----------------------------------==\n"); 328 | printf("Running ks_hashmap_get_tests()...\n"); 329 | if (ks_hashmap_get_tests()) retval = -1; 330 | printf("done.\n"); 331 | printf("==-----------------------------------==\n\n"); 332 | 333 | printf("==-----------------------------------==\n"); 334 | printf("Running ks_hashmap_get_key_tests()...\n"); 335 | if (ks_hashmap_get_key_tests()) retval = -1; 336 | printf("done.\n"); 337 | printf("==-----------------------------------==\n\n"); 338 | 339 | printf("==-----------------------------------==\n"); 340 | printf("Running ks_hashmap_count_tests()...\n"); 341 | if (ks_hashmap_count_tests()) retval = -1; 342 | printf("done.\n"); 343 | printf("==-----------------------------------==\n\n"); 344 | 345 | return retval; 346 | } 347 | -------------------------------------------------------------------------------- /tests/hashset_tests.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "kylestructs/ks_datacont.h" 4 | #include "kylestructs/ks_hashset.h" 5 | #include "kylestructs/ks_treeset.h" 6 | #include "kylestructs/ks_treesetnode.h" 7 | #include "kylestructs/ks_types.h" 8 | 9 | static int ks_hashset_new_tests() { 10 | int retval = 0; 11 | 12 | /* Test 1 */ 13 | ks_hashset* hs = ks_hashset_new(KS_CHAR, 20); 14 | if (hs->type != KS_CHAR) { 15 | printf( 16 | "TEST 1: ks_hashset contains incorrect ks_datacont type value: %d. " 17 | "Expected: %d.\n", 18 | hs->type, KS_CHAR); 19 | retval = -1; 20 | } 21 | if (hs->num_buckets != 20) { 22 | printf( 23 | "TEST 1: ks_hashset contains incorrect num_buckets value %d. " 24 | "Expected " 25 | "20.\n", 26 | hs->num_buckets); 27 | retval = -1; 28 | } 29 | ks_hashset_delete(hs); 30 | 31 | return retval; 32 | } 33 | 34 | static int ks_hashset_copy_tests() { 35 | int retval = 0; 36 | 37 | /* Test 1 */ 38 | ks_hashset* hs = ks_hashset_new(KS_CHAR, 2); 39 | ks_hashset_add(hs, ks_datacont_new("B", KS_CHAR, 1)); 40 | 41 | ks_hashset* hs_copy = ks_hashset_copy(hs); 42 | 43 | if (hs_copy == NULL) { 44 | printf("TEST 1: Unexpected NULL return from ks_hashset_copy()\n"); 45 | return -1; 46 | } 47 | 48 | if (hs_copy->buckets[0] != NULL) { 49 | if (hs_copy->buckets[0]->root->dc->c != 'B') { 50 | printf( 51 | "TEST 1: Unexpected ks_datacont value after " 52 | "ks_hashset_copy()\n"); 53 | retval = -1; 54 | } 55 | } else if (hs_copy->buckets[1] != NULL) { 56 | if (hs_copy->buckets[1]->root->dc->c != 'B') { 57 | printf( 58 | "TEST 1: Unexpected ks_datacont value after " 59 | "ks_hashset_copy()\n"); 60 | retval = -1; 61 | } 62 | } else { 63 | printf("TEST 1: Unexpected empty ks_hashset after ks_hashset_copy()\n"); 64 | retval = -1; 65 | } 66 | 67 | ks_hashset_delete(hs); 68 | ks_hashset_delete(hs_copy); 69 | 70 | return retval; 71 | } 72 | 73 | static int ks_hashset_add_tests() { 74 | int retval = 0; 75 | 76 | /* Test 1 */ 77 | ks_hashset* hs = ks_hashset_new(KS_CHAR, 30); 78 | ks_datacont* dcA = ks_datacont_new("A", KS_CHAR, 1); 79 | int num = 1; 80 | ks_datacont* dc1 = ks_datacont_new(&num, KS_INT, 1); 81 | 82 | if (ks_hashset_add(hs, ks_datacont_copy(dcA)) != 0) { 83 | printf( 84 | "TEST 1: ks_hashset_add() should return 0 when adding a new " 85 | "item.\n"); 86 | retval = -1; 87 | } 88 | 89 | /* Test 2 */ 90 | if (ks_hashset_add(hs, dcA) != 1) { 91 | printf( 92 | "TEST 2: ks_hashset_add() should return 1 when trying to add an " 93 | "already present item.\n"); 94 | retval = -1; 95 | } 96 | 97 | /* TEST 3 */ 98 | if (ks_hashset_add(hs, dc1) != -1) { 99 | printf( 100 | "TEST 3: ks_hashset_add() should return -1 when adding ks_datacont " 101 | "that is of a different type.\n"); 102 | retval = -1; 103 | } 104 | 105 | /* TEST 4 */ 106 | if (ks_hashset_add(NULL, NULL) != -1) { 107 | printf( 108 | "TEST 4: ks_hashset_add() should return -1 when params are " 109 | "NULL.\n"); 110 | retval = -1; 111 | } 112 | 113 | ks_hashset_delete(hs); 114 | ks_datacont_delete(dcA); 115 | ks_datacont_delete(dc1); 116 | 117 | return retval; 118 | } 119 | 120 | static int ks_hashset_remove_tests() { 121 | int retval = 0; 122 | 123 | ks_hashset* hs = ks_hashset_new(KS_CHAR, 10); 124 | ks_datacont* dc = ks_datacont_new("A", KS_CHAR, 1); 125 | ks_hashset_add(hs, ks_datacont_copy(dc)); 126 | 127 | /* TEST 1 */ 128 | if (ks_hashset_remove(hs, dc) != 0) { 129 | printf( 130 | "TEST 1: hahset_remove() should return 0 when removing present " 131 | "ks_datacont.\n"); 132 | retval = -1; 133 | } 134 | 135 | /* TEST 2 */ 136 | if (ks_hashset_remove(hs, dc) != -1) { 137 | printf( 138 | "TEST 2: ks_hashset_remove() should return -1 when removing " 139 | "not-present ks_datacont.\n"); 140 | retval = -1; 141 | } 142 | 143 | /* TEST 3 */ 144 | if (ks_hashset_remove(hs, NULL) != -1) { 145 | printf( 146 | "TEST 3: ks_hashset_remove() should return -1 when params are " 147 | "NULL.\n"); 148 | retval = -1; 149 | } 150 | 151 | ks_datacont_delete(dc); 152 | ks_hashset_delete(hs); 153 | 154 | return retval; 155 | } 156 | 157 | static int ks_hashset_contains_tests() { 158 | int retval = 0; 159 | 160 | /* Test 1 */ 161 | ks_hashset* hs = ks_hashset_new(KS_CHAR, 10); 162 | ks_datacont* dcA = ks_datacont_new("A", KS_CHAR, 1); 163 | ks_datacont* dcB = ks_datacont_new("B", KS_CHAR, 1); 164 | ks_hashset_add(hs, ks_datacont_copy(dcA)); 165 | if (ks_hashset_contains(hs, dcA) != 1) { 166 | printf("TEST 1: ks_hashset_contains() should return 1.\n"); 167 | retval = -1; 168 | } 169 | 170 | /* TEST 2 */ 171 | if (ks_hashset_contains(hs, dcB) != 0) { 172 | printf( 173 | "TEST 2: ks_hashset_contains() should return 0 on not present " 174 | "ks_datacont.\n"); 175 | retval = -1; 176 | } 177 | 178 | ks_datacont_delete(dcA); 179 | ks_datacont_delete(dcB); 180 | ks_hashset_delete(hs); 181 | 182 | return retval; 183 | } 184 | 185 | static int ks_hashset_count_tests() { 186 | int retval = 0; 187 | 188 | ks_hashset* hs = ks_hashset_new(KS_CHAR, 10); 189 | ks_datacont* dcA = ks_datacont_new("A", KS_CHAR, 1); 190 | ks_datacont* dcB = ks_datacont_new("B", KS_CHAR, 1); 191 | 192 | int count; 193 | 194 | /* TEST 1 */ 195 | if ((count = ks_hashset_count(hs)) != 0) { 196 | printf( 197 | "TEST 1: Unexpected return value from ks_hashset_count(): %d. " 198 | "Expected " 199 | "0.\n", 200 | count); 201 | retval = -1; 202 | } 203 | 204 | /* TEST 2 */ 205 | ks_hashset_add(hs, dcA); 206 | if ((count = ks_hashset_count(hs)) != 1) { 207 | printf( 208 | "TEST 2: Unexpected return value from ks_hashset_count(): %d. " 209 | "Expected " 210 | "1.\n", 211 | count); 212 | retval = -1; 213 | } 214 | 215 | /* TEST 3 */ 216 | ks_hashset_add(hs, dcB); 217 | if ((count = ks_hashset_count(hs)) != 2) { 218 | printf( 219 | "TEST 3: Unexpected return value from ks_hashset_count(): %d. " 220 | "Expected " 221 | "2.\n", 222 | count); 223 | retval = -1; 224 | } 225 | 226 | /* TEST 4 */ 227 | if ((count = ks_hashset_count(NULL)) != 0) { 228 | printf( 229 | "TEST 4: Unexpected return value from ks_hashset_count(): %d. " 230 | "Expected " 231 | "0.\n", 232 | count); 233 | retval = -1; 234 | } 235 | 236 | ks_hashset_delete(hs); 237 | 238 | return retval; 239 | } 240 | 241 | static int ks_hashset_get_tests() { 242 | int retval = 0; 243 | 244 | /* TEST 1 */ 245 | ks_hashset* hs = ks_hashset_new(KS_CHAR, 2); 246 | 247 | ks_treeset* ts0 = ks_treeset_new(); 248 | ks_treeset_add(ts0, ks_datacont_new("B", KS_CHAR, 1)); 249 | ks_treeset_add(ts0, ks_datacont_new("A", KS_CHAR, 1)); 250 | ks_treeset_add(ts0, ks_datacont_new("C", KS_CHAR, 1)); 251 | 252 | ks_treeset* ts1 = ks_treeset_new(); 253 | ks_treeset_add(ts1, ks_datacont_new("E", KS_CHAR, 1)); 254 | ks_treeset_add(ts1, ks_datacont_new("D", KS_CHAR, 1)); 255 | ks_treeset_add(ts1, ks_datacont_new("F", KS_CHAR, 1)); 256 | 257 | hs->buckets[0] = ts0; 258 | hs->buckets[1] = ts1; 259 | 260 | const ks_datacont* dc = ks_hashset_get(hs, -1); 261 | if (dc->c != 'F') { 262 | printf( 263 | "TEST 1: Unexpected ks_datacont value after ks_hashset_get(): %c. " 264 | "Expected: 'F'\n", 265 | dc->c); 266 | retval = -1; 267 | } 268 | 269 | dc = ks_hashset_get(hs, 5); 270 | if (dc->c != 'F') { 271 | printf( 272 | "TEST 1: Unexpected ks_datacont value after ks_hashset_get(): %c. " 273 | "Expected: 'F'\n", 274 | dc->c); 275 | retval = -1; 276 | } 277 | 278 | dc = ks_hashset_get(hs, -3); 279 | if (dc->c != 'D') { 280 | printf( 281 | "TEST 1: Unexpected ks_datacont value after ks_hashset_get(): %c. " 282 | "Expected: 'D'\n", 283 | dc->c); 284 | retval = -1; 285 | } 286 | 287 | dc = ks_hashset_get(hs, 3); 288 | if (dc->c != 'D') { 289 | printf( 290 | "TEST 1: Unexpected ks_datacont value after ks_hashset_get(): %c. " 291 | "Expected: 'D'\n", 292 | dc->c); 293 | retval = -1; 294 | } 295 | 296 | dc = ks_hashset_get(hs, -4); 297 | if (dc->c != 'C') { 298 | printf( 299 | "TEST 1: Unexpected ks_datacont value after ks_hashset_get(): %c. " 300 | "Expected: 'C'\n", 301 | dc->c); 302 | retval = -1; 303 | } 304 | 305 | dc = ks_hashset_get(hs, 2); 306 | if (dc->c != 'C') { 307 | printf( 308 | "TEST 1: Unexpected ks_datacont value after ks_hashset_get(): %c. " 309 | "Expected: 'C'\n", 310 | dc->c); 311 | retval = -1; 312 | } 313 | 314 | dc = ks_hashset_get(hs, -6); 315 | if (dc->c != 'A') { 316 | printf( 317 | "TEST 1: Unexpected ks_datacont value after ks_hashset_get(): %c. " 318 | "Expected: 'A'\n", 319 | dc->c); 320 | retval = -1; 321 | } 322 | 323 | dc = ks_hashset_get(hs, 0); 324 | if (dc->c != 'A') { 325 | printf( 326 | "TEST 1: Unexpected ks_datacont value after ks_hashset_get(): %c. " 327 | "Expected: 'A'\n", 328 | dc->c); 329 | retval = -1; 330 | } 331 | 332 | ks_hashset_delete(hs); 333 | 334 | return retval; 335 | } 336 | 337 | int main() { 338 | int retval = 0; 339 | 340 | printf("\nks_hashset tests:\n\n"); 341 | 342 | printf("==-----------------------------------==\n"); 343 | printf("Running ks_hashset_new_tests()...\n"); 344 | if (ks_hashset_new_tests()) retval = -1; 345 | printf("done.\n"); 346 | printf("==-----------------------------------==\n\n"); 347 | 348 | printf("==-----------------------------------==\n"); 349 | printf("Running ks_hashset_copy_tests()...\n"); 350 | if (ks_hashset_copy_tests()) retval = -1; 351 | printf("done.\n"); 352 | printf("==-----------------------------------==\n\n"); 353 | 354 | printf("==-----------------------------------==\n"); 355 | printf("Running ks_hashset_add_tests()...\n"); 356 | if (ks_hashset_add_tests()) retval = -1; 357 | printf("done.\n"); 358 | printf("==-----------------------------------==\n\n"); 359 | 360 | printf("==-----------------------------------==\n\n"); 361 | printf("Running ks_hashset_remove_tests()...\n"); 362 | if (ks_hashset_add_tests()) retval = -1; 363 | printf("done.\n"); 364 | printf("==-----------------------------------==\n\n"); 365 | 366 | printf("==-----------------------------------==\n"); 367 | printf("Running ks_hashset_contains_tests()...\n"); 368 | if (ks_hashset_contains_tests()) retval = -1; 369 | printf("done.\n"); 370 | printf("==-----------------------------------==\n\n"); 371 | 372 | printf("==-----------------------------------==\n"); 373 | printf("Running ks_hashset_count_tests()...\n"); 374 | if (ks_hashset_count_tests()) retval = -1; 375 | printf("done.\n"); 376 | printf("==-----------------------------------==\n\n"); 377 | 378 | printf("==-----------------------------------==\n"); 379 | printf("Running ks_hashset_get_tests()...\n"); 380 | if (ks_hashset_get_tests()) retval = -1; 381 | printf("done.\n"); 382 | printf("==-----------------------------------==\n\n"); 383 | 384 | return retval; 385 | } 386 | -------------------------------------------------------------------------------- /tests/iterator_tests.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "kylestructs/ks_datacont.h" 4 | #include "kylestructs/ks_hashmap.h" 5 | #include "kylestructs/ks_hashset.h" 6 | #include "kylestructs/ks_iterator.h" 7 | #include "kylestructs/ks_list.h" 8 | #include "kylestructs/ks_listnode.h" 9 | #include "kylestructs/ks_treemap.h" 10 | #include "kylestructs/ks_treemapnode.h" 11 | #include "kylestructs/ks_treeset.h" 12 | #include "kylestructs/ks_treesetnode.h" 13 | #include "kylestructs/ks_types.h" 14 | 15 | static int ks_iterator_new_tests() { 16 | int retval = 0; 17 | 18 | /* TEST 1 */ 19 | ks_list* ls = ks_list_new(); 20 | ks_list_add(ls, ks_datacont_new("A", KS_CHAR, 1)); 21 | ks_list_add(ls, ks_datacont_new("B", KS_CHAR, 1)); 22 | ks_list_add(ls, ks_datacont_new("C", KS_CHAR, 1)); 23 | 24 | ks_iterator* iter = ks_iterator_new(ls, KS_LIST); 25 | 26 | if (iter->type != KS_LIST) { 27 | printf("TEST 1: Unexpected iterator->type value: %d. Expected: %d\n", 28 | iter->type, KS_LIST); 29 | retval = -1; 30 | } 31 | 32 | if (iter->size != 3) { 33 | printf("TEST 1: Unexpected iterator->size value: %d. Expected: 3\n", 34 | iter->size); 35 | retval = -1; 36 | } 37 | 38 | if (iter->index != 0) { 39 | printf("TEST 1: Unexpected iterator->index value: %d. Expected: 0\n", 40 | iter->index); 41 | retval = -1; 42 | } 43 | 44 | if (iter->curr->dc->c != 'A') { 45 | printf("TEST 1: Unexpected iterator->curr value: %c. Expected: A\n", 46 | iter->curr->dc->c); 47 | retval = -1; 48 | } 49 | 50 | ks_iterator_delete(iter); 51 | ks_list_delete(ls); 52 | 53 | return retval; 54 | } 55 | 56 | static int ks_iterator_next_tests() { 57 | int retval = 0; 58 | 59 | /* TEST 1 */ 60 | ks_list* ls = ks_list_new(); 61 | ks_list_add(ls, ks_datacont_new("A", KS_CHAR, 1)); 62 | ks_list_add(ls, ks_datacont_new("B", KS_CHAR, 1)); 63 | ks_list_add(ls, ks_datacont_new("C", KS_CHAR, 1)); 64 | 65 | ks_iterator* iter = ks_iterator_new(ls, KS_LIST); 66 | 67 | const ks_datacont* dc = ks_iterator_next(iter); 68 | if (dc->c != 'A') { 69 | printf("TEST 1: Unexpected ks_iterator_next() value: %c. Expected: A\n", 70 | iter->curr->dc->c); 71 | retval = -1; 72 | } 73 | 74 | dc = ks_iterator_next(iter); 75 | if (dc->c != 'B') { 76 | printf("TEST 1: Unexpected ks_iterator_next() value: %c. Expected: B\n", 77 | iter->curr->dc->c); 78 | retval = -1; 79 | } 80 | 81 | dc = ks_iterator_next(iter); 82 | if (dc->c != 'C') { 83 | printf("TEST 1: Unexpected ks_iterator_next() value: %c. Expected: C\n", 84 | iter->curr->dc->c); 85 | retval = -1; 86 | } 87 | 88 | ks_iterator_delete(iter); 89 | ks_list_delete(ls); 90 | 91 | return retval; 92 | } 93 | 94 | int main() { 95 | int retval = 0; 96 | 97 | printf("\nks_iterator tests:\n\n"); 98 | 99 | printf("==-----------------------------------==\n"); 100 | printf("Running ks_iterator_new_tests()...\n"); 101 | if (ks_iterator_new_tests()) retval = -1; 102 | printf("done.\n"); 103 | printf("==-----------------------------------==\n\n"); 104 | 105 | printf("==-----------------------------------==\n"); 106 | printf("Running ks_iterator_next_tests()...\n"); 107 | if (ks_iterator_next_tests()) retval = -1; 108 | printf("done.\n"); 109 | printf("==-----------------------------------==\n\n"); 110 | 111 | return retval; 112 | } 113 | -------------------------------------------------------------------------------- /tests/treemap_tests.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "kylestructs/ks_datacont.h" 4 | #include "kylestructs/ks_list.h" 5 | #include "kylestructs/ks_listnode.h" 6 | #include "kylestructs/ks_treemap.h" 7 | #include "kylestructs/ks_treemapnode.h" 8 | #include "kylestructs/ks_types.h" 9 | 10 | static int ks_treemap_new_tests() { 11 | int retval = 0; 12 | 13 | /* TEST 1 */ 14 | ks_treemap* tm = ks_treemap_new(); 15 | 16 | if (tm->root != NULL) { 17 | printf("TEST 1: ks_treemap->root should be NULL when empty.\n"); 18 | retval = -1; 19 | } 20 | ks_treemap_delete(tm); 21 | 22 | return retval; 23 | } 24 | 25 | static int ks_treemap_copy_tests() { 26 | int retval = 0; 27 | 28 | /* TEST 1 */ 29 | ks_treemap* tm = ks_treemap_new(); 30 | ks_treemap_add(tm, ks_datacont_new("B", KS_CHAR, 1), 31 | ks_datacont_new("B", KS_CHAR, 1)); 32 | ks_treemap_add(tm, ks_datacont_new("C", KS_CHAR, 1), 33 | ks_datacont_new("C", KS_CHAR, 1)); 34 | 35 | ks_treemap* tm_copy = ks_treemap_copy(tm); 36 | 37 | if (tm_copy == NULL) { 38 | printf("TEST 1: Unexpected NULL return from ks_treemap_copy()\n"); 39 | return -1; 40 | } 41 | 42 | if (tm_copy->root->key->c != 'B') { 43 | printf( 44 | "TEST 1: Unexpected ks_datacont value in ks_treemap_copy() " 45 | "result\n"); 46 | retval = -1; 47 | } 48 | 49 | if (tm_copy->root->right->key->c != 'C') { 50 | printf( 51 | "TEST 1: Unexpected ks_datacont value in ks_treemap_copy() " 52 | "result\n"); 53 | retval = -1; 54 | } 55 | 56 | ks_treemap_delete(tm); 57 | ks_treemap_delete(tm_copy); 58 | 59 | return retval; 60 | } 61 | 62 | static int ks_treemap_add_tests() { 63 | int retval = 0; 64 | 65 | /* TEST 1 */ 66 | int two = 2; 67 | ks_datacont* key2 = ks_datacont_new(&two, KS_INT, 1); 68 | ks_datacont* val2 = ks_datacont_new("B", KS_CHAR, 1); 69 | 70 | int three = 3; 71 | ks_datacont* key3 = ks_datacont_new(&three, KS_INT, 1); 72 | ks_datacont* val3 = ks_datacont_new("C", KS_CHAR, 1); 73 | 74 | ks_datacont* val4 = ks_datacont_new("D", KS_CHAR, 1); 75 | 76 | ks_treemap* tm = ks_treemap_new(); 77 | 78 | if (ks_treemap_add(tm, key2, val2)) { 79 | printf( 80 | "TEST 1: ks_treemap_add() should return zero when adding a new " 81 | "pair.\n"); 82 | retval = -1; 83 | } 84 | if (tm->root->key->i != 2) { 85 | printf( 86 | "TEST 1: Unexpected key ks_datacont at root node: %d. Expected: " 87 | "2.\n", 88 | tm->root->key->i); 89 | retval = -1; 90 | } 91 | if (tm->root->value->c != 'B') { 92 | printf( 93 | "TEST 1: Unexpected value ks_datacont at root node: %d. Expected " 94 | "B.\n", 95 | tm->root->value->c); 96 | retval = -1; 97 | } 98 | 99 | /* TEST 2 */ 100 | if (ks_treemap_add(tm, key3, val3)) { 101 | printf( 102 | "TEST 2: ks_treemap_add() should return zero when adding a new " 103 | "pair.\n"); 104 | retval = -1; 105 | } 106 | if (tm->root->right == NULL) { 107 | printf("TEST 2: expected root->right to be non-NULL.\n"); 108 | retval = -1; 109 | } 110 | 111 | /* TEST 3 */ 112 | if (ks_treemap_add(tm, ks_datacont_copy(key2), val4) != 1) { 113 | printf( 114 | "TEST 3: ks_treemap_add() should return 1 when replacing existing " 115 | "pair.\n"); 116 | retval = -1; 117 | } 118 | if (tm->root->value->c != 'D') { 119 | printf("TEST 3: Unexpected root node value: %c. Expected: D.\n", 120 | tm->root->value->c); 121 | retval = -1; 122 | } 123 | 124 | /* TEST 4 */ 125 | if (ks_treemap_add(NULL, NULL, NULL) != -1) { 126 | printf( 127 | "TEST 4: ks_treemap_add() should return -1 when params are " 128 | "NULL.\n"); 129 | retval = -1; 130 | } 131 | 132 | ks_treemap_delete(tm); 133 | 134 | return retval; 135 | } 136 | 137 | static int ks_treemap_remove_tests() { 138 | int retval = 0; 139 | 140 | /* TEST 1 */ 141 | int one = 1; 142 | ks_datacont* key1 = ks_datacont_new(&one, KS_INT, 1); 143 | ks_datacont* val1 = ks_datacont_new("A", KS_CHAR, 1); 144 | 145 | int two = 2; 146 | ks_datacont* key2 = ks_datacont_new(&two, KS_INT, 1); 147 | ks_datacont* val2 = ks_datacont_new("B", KS_CHAR, 1); 148 | 149 | int three = 3; 150 | ks_datacont* key3 = ks_datacont_new(&three, KS_INT, 1); 151 | ks_datacont* val3 = ks_datacont_new("C", KS_CHAR, 1); 152 | 153 | ks_treemap* tm = ks_treemap_new(); 154 | 155 | ks_treemap_add(tm, key2, val2); 156 | key2 = ks_datacont_copy(key2); 157 | 158 | ks_treemap_add(tm, key1, val1); 159 | key1 = ks_datacont_copy(key1); 160 | 161 | ks_treemap_add(tm, key3, val3); 162 | key3 = ks_datacont_copy(key3); 163 | 164 | if (ks_treemap_remove(tm, key2)) { 165 | printf("TEST 1: Failed to remove root node from ks_treemap.\n"); 166 | retval = -1; 167 | } 168 | if (tm->root->key->i != 3) { 169 | printf("TEST 1: Unexpected root key value: %d. Expected: 3.\n", 170 | tm->root->key->i); 171 | retval = -1; 172 | } 173 | if (tm->root->right != NULL) { 174 | printf("TEST 1: Expected right node to be NULL.\n"); 175 | retval = -1; 176 | } 177 | 178 | /* TEST 2 */ 179 | if (ks_treemap_remove(tm, key2) != -1) { 180 | printf( 181 | "TEST 2: ks_treemap_remove() should return -1 when removing " 182 | "not-present node key.\n"); 183 | retval = -1; 184 | } 185 | 186 | /* TEST 3 */ 187 | if (ks_treemap_remove(tm, key1)) { 188 | printf("TEST 3: Failed to remove left node from ks_treemap.\n"); 189 | retval = -1; 190 | } 191 | if (tm->root->left != NULL) { 192 | printf("TEST 3: Expected left node to be NULL.\n"); 193 | retval = -1; 194 | } 195 | 196 | /* TEST 4 */ 197 | if (ks_treemap_remove(tm, key3)) { 198 | printf("TEST 4: failed to remove last node in ks_treemap.\n"); 199 | retval = -1; 200 | } 201 | if (tm->root != NULL) { 202 | printf( 203 | "TEST 4: Expected root node to be NULL after last " 204 | "ks_treemap_remove().\n"); 205 | retval = -1; 206 | } 207 | 208 | ks_datacont_delete(key1); 209 | ks_datacont_delete(key2); 210 | ks_datacont_delete(key3); 211 | 212 | ks_treemap_delete(tm); 213 | 214 | return retval; 215 | } 216 | 217 | static int ks_treemap_get_tests() { 218 | int retval = 0; 219 | 220 | /* TEST 1 */ 221 | int one = 1; 222 | ks_datacont* key1 = ks_datacont_new(&one, KS_INT, 1); 223 | ks_datacont* val1 = ks_datacont_new("A", KS_CHAR, 1); 224 | 225 | int two = 2; 226 | ks_datacont* key2 = ks_datacont_new(&two, KS_INT, 1); 227 | ks_datacont* val2 = ks_datacont_new("B", KS_CHAR, 1); 228 | 229 | int three = 3; 230 | ks_datacont* key3 = ks_datacont_new(&three, KS_INT, 1); 231 | ks_datacont* val3 = ks_datacont_new("C", KS_CHAR, 1); 232 | 233 | int four = 4; 234 | ks_datacont* not_there = ks_datacont_new(&four, KS_INT, 1); 235 | 236 | ks_treemap* tm = ks_treemap_new(); 237 | ks_treemap_add(tm, key2, val2); 238 | ks_treemap_add(tm, key1, val1); 239 | ks_treemap_add(tm, key3, val3); 240 | 241 | const ks_datacont* val = ks_treemap_get(tm, key2); 242 | if (val->c != val2->c) { 243 | printf("TEST 1: Unexpected ks_datacont value: %c. Expected: %c.\n", 244 | val->c, val2->c); 245 | retval = -1; 246 | } 247 | 248 | /* TEST 2 */ 249 | val = ks_treemap_get(tm, key1); 250 | if (val->c != val1->c) { 251 | printf("TEST 2: Unexpected ks_datacont value: %c. Expected: %c.\n", 252 | val->c, val1->c); 253 | retval = -1; 254 | } 255 | 256 | /* TEST 3 */ 257 | val = ks_treemap_get(tm, not_there); 258 | if (val != NULL) { 259 | printf( 260 | "TEST 3: ks_treemapnode_get() should return NULL on not-present " 261 | "key " 262 | "value.\n"); 263 | retval = -1; 264 | } 265 | 266 | ks_treemap_delete(tm); 267 | ks_datacont_delete(not_there); 268 | 269 | return retval; 270 | } 271 | 272 | static int ks_treemap_get_key_tests() { 273 | int retval = 0; 274 | 275 | /* TEST 1 */ 276 | int one = 1; 277 | ks_datacont* key1 = ks_datacont_new(&one, KS_INT, 1); 278 | ks_datacont* val1 = ks_datacont_new("A", KS_CHAR, 1); 279 | 280 | int two = 2; 281 | ks_datacont* key2 = ks_datacont_new(&two, KS_INT, 1); 282 | ks_datacont* val2 = ks_datacont_new("B", KS_CHAR, 1); 283 | 284 | int three = 3; 285 | ks_datacont* key3 = ks_datacont_new(&three, KS_INT, 1); 286 | ks_datacont* val3 = ks_datacont_new("C", KS_CHAR, 1); 287 | 288 | ks_treemap* tm = ks_treemap_new(); 289 | ks_treemap_add(tm, key2, val2); 290 | ks_treemap_add(tm, key1, val1); 291 | ks_treemap_add(tm, key3, val3); 292 | 293 | const ks_datacont* get_dc = ks_treemap_get_key(tm, 0); 294 | if (get_dc->i != 1) { 295 | printf("TEST 1: Unexpected ks_datacont value: %d. Expected 1.\n", 296 | get_dc->i); 297 | retval = -1; 298 | } 299 | 300 | /* TEST 2 */ 301 | get_dc = ks_treemap_get_key(tm, 1); 302 | if (get_dc->i != 2) { 303 | printf("TEST 2: Unexpected ks_datacont value: %d. Expected 2.\n", 304 | get_dc->i); 305 | retval = -1; 306 | } 307 | 308 | /* TEST 3 */ 309 | get_dc = ks_treemap_get_key(tm, 2); 310 | if (get_dc->i != 3) { 311 | printf("TEST 3: Unexpected ks_datacont value: %d. Expected 3.\n", 312 | get_dc->i); 313 | retval = -1; 314 | } 315 | 316 | /* TEST 4 */ 317 | get_dc = ks_treemap_get_key(tm, 3); 318 | if (get_dc != NULL) { 319 | printf( 320 | "TEST 4: Expected OOB call to ks_treemap_get_key() to return " 321 | "NULL.\n"); 322 | retval = -1; 323 | } 324 | 325 | ks_treemap_delete(tm); 326 | 327 | return retval; 328 | } 329 | 330 | static int ks_treemap_count_tests() { 331 | int retval = 0; 332 | 333 | /* TEST 1 */ 334 | int one = 1; 335 | ks_datacont* key1 = ks_datacont_new(&one, KS_INT, 1); 336 | ks_datacont* val1 = ks_datacont_new("A", KS_CHAR, 1); 337 | 338 | int two = 2; 339 | ks_datacont* key2 = ks_datacont_new(&two, KS_INT, 1); 340 | ks_datacont* val2 = ks_datacont_new("B", KS_CHAR, 1); 341 | 342 | int three = 3; 343 | ks_datacont* key3 = ks_datacont_new(&three, KS_INT, 1); 344 | ks_datacont* val3 = ks_datacont_new("C", KS_CHAR, 1); 345 | 346 | int four = 4; 347 | ks_datacont* key4 = ks_datacont_new(&four, KS_INT, 1); 348 | ks_datacont* val4 = ks_datacont_new("D", KS_CHAR, 1); 349 | 350 | ks_treemap* tm = ks_treemap_new(); 351 | ks_treemap_add(tm, key2, val2); 352 | ks_treemap_add(tm, key1, val1); 353 | ks_treemap_add(tm, key3, val3); 354 | ks_treemap_add(tm, key4, val4); 355 | 356 | int count = ks_treemap_count(tm); 357 | if (count != 4) { 358 | printf( 359 | "TEST 1: Unexpected ks_treemap_count() return value: %d. Expected: " 360 | "4.\n", 361 | count); 362 | retval = -1; 363 | } 364 | 365 | /* TEST 2 */ 366 | count = ks_treemap_count(NULL); 367 | if (count != 0) { 368 | printf( 369 | "TEST 2: Unexpected ks_treemap_count() return value: %d. Expected: " 370 | "4.\n", 371 | count); 372 | retval = -1; 373 | } 374 | 375 | ks_treemap_delete(tm); 376 | 377 | return retval; 378 | } 379 | 380 | static int ks_treemap_height_tests() { 381 | int retval = 0; 382 | 383 | /* TEST 1 */ 384 | int one = 1; 385 | ks_datacont* key1 = ks_datacont_new(&one, KS_INT, 1); 386 | ks_datacont* val1 = ks_datacont_new("A", KS_CHAR, 1); 387 | 388 | int two = 2; 389 | ks_datacont* key2 = ks_datacont_new(&two, KS_INT, 1); 390 | ks_datacont* val2 = ks_datacont_new("B", KS_CHAR, 1); 391 | 392 | int three = 3; 393 | ks_datacont* key3 = ks_datacont_new(&three, KS_INT, 1); 394 | ks_datacont* val3 = ks_datacont_new("C", KS_CHAR, 1); 395 | 396 | int four = 4; 397 | ks_datacont* key4 = ks_datacont_new(&four, KS_INT, 1); 398 | ks_datacont* val4 = ks_datacont_new("D", KS_CHAR, 1); 399 | 400 | ks_treemap* tm = ks_treemap_new(); 401 | ks_treemap_add(tm, key2, val2); 402 | ks_treemap_add(tm, key1, val1); 403 | ks_treemap_add(tm, key3, val3); 404 | ks_treemap_add(tm, key4, val4); 405 | 406 | int height = ks_treemap_height(tm); 407 | if (height != 3) { 408 | printf( 409 | "TEST 1: Unexpected ks_treemap_height() return value: %d. " 410 | "Expected: " 411 | "3.\n", 412 | height); 413 | retval = -1; 414 | } 415 | 416 | /* TEST 2 */ 417 | height = ks_treemap_height(NULL); 418 | if (height != 0) { 419 | printf( 420 | "TEST 2: Unexpected ks_treemap_height() return value: %d. " 421 | "Expected: " 422 | "0.\n", 423 | height); 424 | retval = -1; 425 | } 426 | 427 | ks_treemap_delete(tm); 428 | 429 | return retval; 430 | } 431 | 432 | static int ks_treemap_balance_tests() { 433 | int retval = 0; 434 | 435 | /* TEST 1 */ 436 | char c = 'A'; 437 | int i = 0; 438 | ks_treemap* tm = ks_treemap_new(); 439 | ks_treemap_add(tm, ks_datacont_new(&i, KS_INT, 1), 440 | ks_datacont_new(&c, KS_CHAR, 1)); 441 | 442 | for (int i = 0; i < 26; i++, c++) 443 | ks_treemap_add(tm, ks_datacont_new(&i, KS_INT, 1), 444 | ks_datacont_new(&c, KS_CHAR, 1)); 445 | 446 | unsigned int height = ks_treemap_height(tm); 447 | if (height != 26) { 448 | printf( 449 | "TEST 1: ks_treemap_height() should have returned 26. Can't " 450 | "continue, " 451 | "quitting test...\n"); 452 | ks_treemap_delete(tm); 453 | return -1; 454 | } 455 | 456 | ks_treemap_balance(tm); 457 | height = ks_treemap_height(tm); 458 | if (height != 5) { 459 | printf( 460 | "TEST 1: Unexpected tree height after ks_treemap_balance(): %d. " 461 | "Expected: 5.\n", 462 | height); 463 | retval = -1; 464 | } 465 | 466 | ks_treemap_delete(tm); 467 | 468 | return retval; 469 | } 470 | 471 | int main() { 472 | int retval = 0; 473 | 474 | printf("\nks_treemap tests:\n\n"); 475 | 476 | printf("==-----------------------------------==\n"); 477 | printf("Running ks_treemap_new_tests()...\n"); 478 | if (ks_treemap_new_tests()) retval = -1; 479 | printf("done.\n"); 480 | printf("==-----------------------------------==\n\n"); 481 | 482 | printf("==-----------------------------------==\n"); 483 | printf("Running ks_treemap_copy_tests()...\n"); 484 | if (ks_treemap_copy_tests()) retval = -1; 485 | printf("done.\n"); 486 | printf("==-----------------------------------==\n\n"); 487 | 488 | printf("==-----------------------------------==\n"); 489 | printf("Running ks_treemap_add_tests()...\n"); 490 | if (ks_treemap_add_tests()) retval = -1; 491 | printf("done.\n"); 492 | printf("==-----------------------------------==\n\n"); 493 | 494 | printf("==-----------------------------------==\n"); 495 | printf("Running ks_treemap_remove_tests()...\n"); 496 | if (ks_treemap_remove_tests()) retval = -1; 497 | printf("done.\n"); 498 | printf("==-----------------------------------==\n\n"); 499 | 500 | printf("==-----------------------------------==\n"); 501 | printf("Running ks_treemap_get_tests()...\n"); 502 | if (ks_treemap_get_tests()) retval = -1; 503 | printf("done.\n"); 504 | printf("==-----------------------------------==\n\n"); 505 | 506 | printf("==-----------------------------------==\n"); 507 | printf("Running ks_treemap_get_key_tests()...\n"); 508 | if (ks_treemap_get_key_tests()) retval = -1; 509 | printf("done.\n"); 510 | printf("==-----------------------------------==\n\n"); 511 | 512 | printf("==-----------------------------------==\n"); 513 | printf("Running ks_treemap_count_tests()...\n"); 514 | if (ks_treemap_count_tests()) retval = -1; 515 | printf("done.\n"); 516 | printf("==-----------------------------------==\n\n"); 517 | 518 | printf("==-----------------------------------==\n"); 519 | printf("Running ks_treemap_height_tests()...\n"); 520 | if (ks_treemap_height_tests()) retval = -1; 521 | printf("done.\n"); 522 | printf("==-----------------------------------==\n\n"); 523 | 524 | printf("==-----------------------------------==\n"); 525 | printf("Running ks_treemap_balance_tests()...\n"); 526 | if (ks_treemap_balance_tests()) retval = -1; 527 | printf("done.\n"); 528 | printf("==-----------------------------------==\n\n"); 529 | 530 | return retval; 531 | } 532 | -------------------------------------------------------------------------------- /tests/treeset_tests.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "kylestructs/ks_datacont.h" 4 | #include "kylestructs/ks_hashset.h" 5 | #include "kylestructs/ks_treeset.h" 6 | #include "kylestructs/ks_treesetnode.h" 7 | #include "kylestructs/ks_types.h" 8 | 9 | static int ks_treeset_new_tests() { 10 | int retval = 0; 11 | 12 | /* TEST 1 */ 13 | 14 | ks_treeset* ts = ks_treeset_new(); 15 | 16 | if (ts == NULL) { 17 | printf( 18 | "TEST 1: Unexpected NULL value returned from ks_treeset_new().\n"); 19 | retval = -1; 20 | } 21 | 22 | if (ts->root) { 23 | printf( 24 | "TEST 1: ks_treeset should contain NULL 'root' ks_treesetnode* " 25 | "values.\n"); 26 | retval = -1; 27 | } 28 | ks_treeset_delete(ts); 29 | 30 | return retval; 31 | } 32 | 33 | static int ks_treeset_copy_tests() { 34 | int retval = 0; 35 | 36 | /* TEST 1 */ 37 | ks_treeset* ts = ks_treeset_new(); 38 | ks_treeset_add(ts, ks_datacont_new("A", KS_CHAR, 1)); 39 | ks_treeset_add(ts, ks_datacont_new("B", KS_CHAR, 1)); 40 | 41 | ks_treeset* ts_copy = ks_treeset_copy(ts); 42 | 43 | if (ts_copy == NULL) { 44 | printf("TEST 1: Unexpected NULL return from ks_treeset_copy()\n"); 45 | return -1; 46 | } 47 | 48 | if (ts_copy->root->dc->c != 'A' || ts_copy->root->right->dc->c != 'B') { 49 | printf( 50 | "TEST 1: Unexpected ks_datacont values after ts_treeset_copy()\n"); 51 | retval = -1; 52 | } 53 | 54 | ks_treeset_delete(ts); 55 | ks_treeset_delete(ts_copy); 56 | 57 | return retval; 58 | } 59 | 60 | static int ks_treeset_add_tests() { 61 | int retval = 0; 62 | 63 | ks_treeset* ts = ks_treeset_new(); 64 | ks_datacont* dcB = ks_datacont_new("B", KS_CHAR, 2); 65 | 66 | /* Test 1 */ 67 | int result; 68 | if ((result = ks_treeset_add(ts, ks_datacont_copy(dcB))) != 0) { 69 | printf( 70 | "TEST 1: Unexpected return value from ks_treeset_add(): %d. " 71 | "Expected: " 72 | "0.\n", 73 | result); 74 | retval = -1; 75 | } 76 | 77 | /* TEST 2 */ 78 | if ((result = ks_treeset_add(ts, dcB)) != 1) { 79 | printf( 80 | "TEST 2: Unexpected return value from ks_treeset_add(): %d. " 81 | "Expected " 82 | "1.\n", 83 | result); 84 | retval = -1; 85 | } 86 | 87 | /* TEST 3 */ 88 | if ((result = ks_treeset_add(NULL, NULL)) != -1) { 89 | printf( 90 | "TEST 3: Unexpected return value from ks_treeset_add(): %d. " 91 | "Expected " 92 | "-1.\n", 93 | result); 94 | retval = -1; 95 | } 96 | 97 | ks_datacont_delete(dcB); 98 | ks_treeset_delete(ts); 99 | 100 | return retval; 101 | } 102 | 103 | static int ks_treeset_remove_by_tests() { 104 | int retval = 0; 105 | 106 | /* TEST 1 */ 107 | ks_datacont* dc = ks_datacont_new("A", KS_CHAR, 1); 108 | 109 | ks_treeset* ts = ks_treeset_new(); 110 | ks_treeset_add(ts, ks_datacont_copy(dc)); 111 | 112 | int result; 113 | if ((result = ks_treeset_remove_by(ts, dc)) != 0) { 114 | printf( 115 | "TEST 1: Unexpected return value from ks_treeset_remove_by(): %d. " 116 | "Expected: 0.\n", 117 | result); 118 | retval = -1; 119 | } 120 | 121 | /* TEST 2 */ 122 | if ((result = ks_treeset_remove_by(ts, dc)) != -1) { 123 | printf( 124 | "TEST 2: Unexpected return value from ks_treeset_remove_by(): %d. " 125 | "Expected: -1.\n", 126 | result); 127 | retval = -1; 128 | } 129 | 130 | /* TEST 3 */ 131 | if ((result = ks_treeset_remove_by(NULL, NULL)) != -1) { 132 | printf( 133 | "TEST 3: Unexpected return value from ks_treeset_remove_by(): %d. " 134 | "Expected: -1.\n", 135 | result); 136 | retval = -1; 137 | } 138 | 139 | ks_datacont_delete(dc); 140 | ks_treeset_delete(ts); 141 | 142 | return retval; 143 | } 144 | 145 | static int ks_treeset_remove_at_tests() { 146 | int retval = 0; 147 | 148 | ks_treeset* ts = ks_treeset_new(); 149 | ks_treeset_add(ts, ks_datacont_new("B", KS_CHAR, 1)); 150 | ks_treeset_add(ts, ks_datacont_new("A", KS_CHAR, 1)); 151 | ks_treeset_add(ts, ks_datacont_new("C", KS_CHAR, 1)); 152 | 153 | int result; 154 | 155 | /* TEST 1 */ 156 | if ((result = ks_treeset_remove_at(ts, 0)) != 0) { 157 | printf( 158 | "TEST 1: Unexpected return value from ks_treeset_remove_at(): %d. " 159 | "Expected: 0.\n", 160 | result); 161 | retval = -1; 162 | } 163 | 164 | /* TEST 2 */ 165 | if ((result = ks_treeset_remove_at(ts, -6)) != -1) { 166 | printf( 167 | "TEST 2: Unexpected return value from ks_treeset_remove_at(): %d. " 168 | "Expected: -1.\n", 169 | result); 170 | retval = -1; 171 | } 172 | 173 | /* TEST 3 */ 174 | if ((result = ks_treeset_remove_at(NULL, 0)) != -1) { 175 | printf( 176 | "TEST 3: Unexpected return value from ks_treeset_remove_at(): %d. " 177 | "Expected: -1.\n", 178 | result); 179 | retval = -1; 180 | } 181 | 182 | ks_treeset_delete(ts); 183 | 184 | return retval; 185 | } 186 | 187 | static int ks_treeset_index_tests() { 188 | int retval = 0; 189 | 190 | /* TEST 1 */ 191 | ks_datacont* dcA = ks_datacont_new("A", KS_CHAR, 1); 192 | ks_datacont* dcB = ks_datacont_new("B", KS_CHAR, 1); 193 | ks_datacont* dcC = ks_datacont_new("C", KS_CHAR, 1); 194 | 195 | ks_treeset* ts = ks_treeset_new(); 196 | ks_treeset_add(ts, ks_datacont_copy(dcB)); 197 | ks_treeset_add(ts, ks_datacont_copy(dcA)); 198 | ks_treeset_add(ts, ks_datacont_copy(dcC)); 199 | 200 | int index; 201 | 202 | if ((index = ks_treeset_index(ts, dcA)) != 0) { 203 | printf( 204 | "TEST 1: Unexpected value returned from ks_treeset_index(): %d. " 205 | "Expected: 0.\n", 206 | index); 207 | retval = -1; 208 | } 209 | 210 | /* TEST 2 */ 211 | if ((index = ks_treeset_index(ts, dcB)) != 1) { 212 | printf( 213 | "TEST 2: Unexpected value returned from ks_treeset_index(): %d. " 214 | "Expected: 1.\n", 215 | index); 216 | retval = -1; 217 | } 218 | 219 | /* TEST 3 */ 220 | if ((index = ks_treeset_index(ts, dcC)) != 2) { 221 | printf( 222 | "TEST 3: Unexpected value returned from ks_treeset_index(): %d. " 223 | "Expected: 2.\n", 224 | index); 225 | retval = -1; 226 | } 227 | 228 | if ((index = ks_treeset_index(NULL, NULL)) != -1) { 229 | printf( 230 | "TEST 4: Unexpected value returned from ks_treeset_index(): %d. " 231 | "Expected: -1.\n", 232 | index); 233 | retval = -1; 234 | } 235 | 236 | ks_datacont_delete(dcA); 237 | ks_datacont_delete(dcB); 238 | ks_datacont_delete(dcC); 239 | ks_treeset_delete(ts); 240 | 241 | return retval; 242 | } 243 | 244 | static int ks_treeset_contains_tests() { 245 | int retval = 0; 246 | 247 | /* Test 1 */ 248 | ks_datacont* dcA = ks_datacont_new("A", KS_CHAR, 1); 249 | ks_datacont* dcB = ks_datacont_new("B", KS_CHAR, 1); 250 | ks_datacont* dcC = ks_datacont_new("C", KS_CHAR, 1); 251 | ks_datacont* dcZ = ks_datacont_new("Z", KS_CHAR, 1); 252 | 253 | ks_treeset* ts = ks_treeset_new(); 254 | ks_treeset_add(ts, dcB); 255 | ks_treeset_add(ts, dcC); 256 | ks_treeset_add(ts, dcA); 257 | 258 | if (ks_treeset_contains(ts, dcZ) == 1) { 259 | printf("TEST 1: ks_treeset should not contain char value 'Z'.\n"); 260 | retval = -1; 261 | } 262 | 263 | /* TEST 2 */ 264 | if (ks_treeset_contains(ts, dcA) == 0) { 265 | printf("TEST 2: ks_treeset should contain char value 'A'.\n"); 266 | retval = -1; 267 | } 268 | 269 | /* TEST 3 */ 270 | if (ks_treeset_contains(ts, NULL) != 0) { 271 | printf( 272 | "TEST 3: ks_treeset_contains() should return 0 on NULL params.\n"); 273 | retval = -1; 274 | } 275 | 276 | ks_datacont_delete(dcZ); 277 | ks_treeset_delete(ts); 278 | 279 | return retval; 280 | } 281 | 282 | static int ks_treeset_get_tests() { 283 | int retval = 0; 284 | 285 | /* TEST 1 */ 286 | ks_datacont* dcA = ks_datacont_new("A", KS_CHAR, 1); 287 | ks_datacont* dcB = ks_datacont_new("B", KS_CHAR, 1); 288 | ks_datacont* dcC = ks_datacont_new("C", KS_CHAR, 1); 289 | 290 | ks_treeset* ts = ks_treeset_new(); 291 | ks_treeset_add(ts, dcB); 292 | ks_treeset_add(ts, dcC); 293 | ks_treeset_add(ts, dcA); 294 | 295 | const ks_datacont* get_dc = ks_treeset_get(ts, -1); 296 | if (get_dc->c != 'C') { 297 | printf( 298 | "TEST 1: Unexpected ks_datacont value after ks_treeset_get(): %c. " 299 | "Expected: C.\n", 300 | get_dc->c); 301 | retval = -1; 302 | } 303 | 304 | /* TEST 2 */ 305 | get_dc = ks_treeset_get(ts, 1); 306 | if (get_dc->c != 'B') { 307 | printf( 308 | "TEST 2: Unexpected ks_datacont value after ks_treeset_get(): %c. " 309 | "Expected: B.\n", 310 | get_dc->c); 311 | retval = -1; 312 | } 313 | 314 | /* TEST 3 */ 315 | get_dc = ks_treeset_get(ts, 1234); 316 | if (get_dc != NULL) { 317 | printf( 318 | "TEST 3: Unexpected ks_datacont value after OOB ks_treeset_get(): " 319 | "%c. " 320 | "Expected: NULL.\n", 321 | get_dc->c); 322 | retval = -1; 323 | } 324 | 325 | ks_treeset_delete(ts); 326 | 327 | return retval; 328 | } 329 | 330 | static int ks_treeset_count_tests() { 331 | int retval = 0; 332 | 333 | /* Test 1 */ 334 | ks_treeset* ts = ks_treeset_new(); 335 | ks_treeset_add(ts, ks_datacont_new("B", KS_CHAR, 1)); 336 | ks_treeset_add(ts, ks_datacont_new("A", KS_CHAR, 1)); 337 | ks_treeset_add(ts, ks_datacont_new("C", KS_CHAR, 1)); 338 | 339 | unsigned int count = ks_treeset_count(ts); 340 | if (count != 3) { 341 | printf( 342 | "TEST 1: Unexpected value returned from ks_treeset_count(): %d. " 343 | "Expected: 3.\n", 344 | count); 345 | retval = -1; 346 | } 347 | 348 | /* TEST 2 */ 349 | ks_treeset_add(ts, ks_datacont_new("Z", KS_CHAR, 1)); 350 | count = ks_treeset_count(ts); 351 | if (count != 4) { 352 | printf( 353 | "TEST 2: Unexpected value returned from ks_treeset_count(): %d. " 354 | "Expected 4.\n", 355 | count); 356 | retval = -1; 357 | } 358 | 359 | /* TEST 3 */ 360 | count = ks_treeset_count(NULL); 361 | if (count != 0) { 362 | printf( 363 | "TEST 3: Unexpected value returned from ks_treeset_count(): %d. " 364 | "Expected 0.\n", 365 | count); 366 | retval = -1; 367 | } 368 | 369 | ks_treeset_delete(ts); 370 | 371 | return retval; 372 | } 373 | 374 | static int ks_treeset_height_tests() { 375 | int retval = 0; 376 | 377 | /* Test 1 */ 378 | ks_treeset* ts = ks_treeset_new(); 379 | ks_treeset_add(ts, ks_datacont_new("B", KS_CHAR, 1)); 380 | ks_treeset_add(ts, ks_datacont_new("A", KS_CHAR, 1)); 381 | ks_treeset_add(ts, ks_datacont_new("C", KS_CHAR, 1)); 382 | 383 | unsigned int height = ks_treeset_height(ts); 384 | if (height != 2) { 385 | printf("TEST 1: Unexpected ks_treeset height: %d. Expected: 2\n", 386 | height); 387 | retval = -1; 388 | } 389 | 390 | /* TEST 2 */ 391 | height = ks_treeset_height(NULL); 392 | if (height != 0) { 393 | printf( 394 | "TEST 2: Unexpected result from ks_treeset_height() on NULL param: " 395 | "%d. " 396 | "Expected: 0.\n", 397 | height); 398 | retval = -1; 399 | } 400 | 401 | ks_treeset_delete(ts); 402 | return retval; 403 | } 404 | 405 | static int ks_treeset_balance_tests() { 406 | int retval = 0; 407 | 408 | /* TEST 1 */ 409 | char c = 'A'; 410 | ks_treeset* ts = ks_treeset_new(); 411 | 412 | for (int i = 0; i < 26; i++, c++) 413 | ks_treeset_add(ts, ks_datacont_new(&c, KS_CHAR, 1)); 414 | 415 | unsigned int height = ks_treeset_height(ts); 416 | if (height != 26) { 417 | printf( 418 | "TEST 1: ks_treeset_height() should have returned 26. Can't " 419 | "continue, " 420 | "quitting test...\n"); 421 | ks_treeset_delete(ts); 422 | return -1; 423 | } 424 | 425 | ks_treeset_balance(ts); 426 | height = ks_treeset_height(ts); 427 | if (height != 5) { 428 | printf( 429 | "TEST 1: Unexpected tree height after ks_treeset_balance(): %d. " 430 | "Expected: 5.\n", 431 | height); 432 | retval = -1; 433 | } 434 | 435 | ks_treeset_delete(ts); 436 | 437 | return retval; 438 | } 439 | 440 | int main() { 441 | int retval = 0; 442 | 443 | printf("\nks_treeset tests:\n\n"); 444 | 445 | printf("==-----------------------------------==\n"); 446 | printf("Running ks_treeset_new_tests()...\n"); 447 | if (ks_treeset_new_tests()) retval = -1; 448 | printf("done.\n"); 449 | printf("==-----------------------------------==\n\n"); 450 | 451 | printf("==-----------------------------------==\n"); 452 | printf("Running ks_treeset_copy_tests()...\n"); 453 | if (ks_treeset_copy_tests()) retval = -1; 454 | printf("done.\n"); 455 | printf("==-----------------------------------==\n\n"); 456 | 457 | printf("==-----------------------------------==\n"); 458 | printf("Running ks_treeset_add_tests()...\n"); 459 | if (ks_treeset_add_tests()) retval = -1; 460 | printf("done.\n"); 461 | printf("==-----------------------------------==\n\n"); 462 | 463 | printf("==-----------------------------------==\n"); 464 | printf("Running ks_treeset_remove_by_tests()...\n"); 465 | if (ks_treeset_remove_by_tests()) retval = -1; 466 | printf("done.\n"); 467 | printf("==-----------------------------------==\n\n"); 468 | 469 | printf("==-----------------------------------==\n"); 470 | printf("Running ks_treeset_remove_at_tests()...\n"); 471 | if (ks_treeset_remove_at_tests()) retval = -1; 472 | printf("done.\n"); 473 | printf("==-----------------------------------==\n\n"); 474 | 475 | printf("==-----------------------------------==\n"); 476 | printf("Running ks_treesetnode_index_tests()...\n"); 477 | if (ks_treeset_index_tests()) retval = -1; 478 | printf("done.\n"); 479 | printf("==-----------------------------------==\n\n"); 480 | 481 | printf("==-----------------------------------==\n"); 482 | printf("Running ks_treeset_contains_tests()...\n"); 483 | if (ks_treeset_contains_tests()) retval = -1; 484 | printf("done.\n"); 485 | printf("==-----------------------------------==\n\n"); 486 | 487 | printf("==-----------------------------------==\n"); 488 | printf("Running ks_treeset_get_tests()...\n"); 489 | if (ks_treeset_get_tests()) retval = -1; 490 | printf("done.\n"); 491 | printf("==-----------------------------------==\n\n"); 492 | 493 | printf("==-----------------------------------==\n"); 494 | printf("Running ks_treeset_count_tests()...\n"); 495 | if (ks_treeset_count_tests()) retval = -1; 496 | printf("done.\n"); 497 | printf("==-----------------------------------==\n\n"); 498 | 499 | printf("==-----------------------------------==\n"); 500 | printf("Running ks_treeset_height_tests()...\n"); 501 | if (ks_treeset_height_tests()) retval = -1; 502 | printf("done.\n"); 503 | printf("==-----------------------------------==\n\n"); 504 | 505 | printf("==-----------------------------------==\n"); 506 | printf("Running ks_treeset_balance_tests()...\n"); 507 | if (ks_treeset_balance_tests()) retval = -1; 508 | printf("done.\n"); 509 | printf("==-----------------------------------==\n\n"); 510 | 511 | return retval; 512 | } 513 | --------------------------------------------------------------------------------