-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 865e169
Showing
40 changed files
with
2,216 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
name: Add tests | ||
about: Add tests for a particular data structure or algorithm | ||
title: Add tests | ||
labels: add-tests | ||
assignees: '' | ||
|
||
--- | ||
|
||
Name of data structure or algorithm to which testing is to be added - | ||
Is test already present - [YES,NO] | ||
If test is already present, what is not covered and needs to be added? - |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
name: Multiplatform CMake Build, CTest, Valgrind Profiling | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
paths-ignore: | ||
- '**/*.md' | ||
- '.github/**' | ||
pull_request: | ||
branches: | ||
- main | ||
paths-ignore: | ||
- '**/README.md' | ||
- '.github/**' | ||
workflow_dispatch: | ||
|
||
jobs: | ||
build: | ||
runs-on: ${{ matrix.os }} | ||
|
||
strategy: | ||
#For testing all configs, true for report first failure and stop | ||
fail-fast: false | ||
# 1. <Windows, Release, latest MSVC compiler toolchain on the default runner image, default generator> | ||
# 2. <Linux, Release, latest GCC compiler toolchain on the default runner image, default generator> | ||
# 3. <Linux, Release, latest Clang compiler toolchain on the default runner image, default generator> | ||
matrix: | ||
os: [ubuntu-latest, windows-latest] | ||
build_type: [Release] | ||
c_compiler: [gcc, clang, cl] | ||
include: | ||
- os: windows-latest | ||
c_compiler: cl | ||
cpp_compiler: cl | ||
- os: ubuntu-latest | ||
c_compiler: gcc | ||
cpp_compiler: g++ | ||
- os: ubuntu-latest | ||
c_compiler: clang | ||
cpp_compiler: clang++ | ||
exclude: | ||
- os: windows-latest | ||
c_compiler: gcc | ||
- os: windows-latest | ||
c_compiler: clang | ||
- os: ubuntu-latest | ||
c_compiler: cl | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Set reusable strings | ||
id: strings | ||
shell: bash | ||
run: | | ||
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" | ||
- name: Install Valgrind if not present | ||
if: matrix.os == 'ubuntu-latest' | ||
run: | | ||
sudo apt-get update | ||
sudo apt-get -y install valgrind | ||
- name: Configure CMake | ||
run: > | ||
cmake -B ${{ steps.strings.outputs.build-output-dir }} | ||
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} | ||
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }} | ||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} | ||
-S ${{ github.workspace }} | ||
- name: Build | ||
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} | ||
|
||
- name: Test | ||
working-directory: ${{ steps.strings.outputs.build-output-dir }} | ||
run: ctest --build-config ${{ matrix.build_type }} | ||
|
||
- name: CTest-Memcheck-Valgrind | ||
if: matrix.os == 'ubuntu-latest' | ||
run: | | ||
ctest -T memcheck -C Debug --test-dir build | ||
ctest_output_code=$? | ||
- name: CTest Memcheck (Valgrind) Upload Results | ||
if: matrix.os == 'ubuntu-latest' | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: memcheck-results-${{matrix.c_compiler}} | ||
path: /home/runner/work/prime-headers/prime-headers/build/Testing/Temporary/MemoryChecker.* | ||
if-no-files-found: ignore | ||
|
||
- name: Check if valgrind failed | ||
if: matrix.os == 'ubuntu-latest' | ||
run: | | ||
pattern=".*LastTestsFailed.*.log" | ||
files=$(find /home/runner/work/prime-headers/prime-headers/build/Testing/Temporary/ -regex "$pattern") | ||
if [ -n "$files" ]; then | ||
echo "Valgrind Failed, LastTestFailed files exist and are uploaded to Artifacts" | ||
exit 1 | ||
else | ||
echo "Valgrind Passed" | ||
fi | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
*.gch | ||
*.exe | ||
*.out | ||
*.exe | ||
.vscode/ | ||
.vs/ | ||
out/ | ||
|
||
list.txt | ||
|
||
#CMake | ||
build/ | ||
CMakeLists.txt.user | ||
CMakeCache.txt | ||
CMakeFiles/ | ||
CMakeScripts | ||
Testing | ||
Makefile | ||
cmake_install.cmake | ||
install_manifest.txt | ||
compile_commands.json | ||
CTestTestfile.cmake | ||
_deps | ||
CMakeUserPresets.json | ||
DartConfiguration.tcl | ||
|
||
#Misc | ||
string/ | ||
local-test.bash |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
cmake_minimum_required(VERSION 3.28) # Needed to reduce version for compatibility with MS VS 2022 | ||
|
||
project(prime-headers C) | ||
|
||
set(CMAKE_C_STANDARD 11) | ||
set(CMAKE_C_STANDARD_REQUIRED ON) | ||
set(CMAKE_BUILD_TYPE Debug) | ||
##set(CMAKE_BUILD_TYPE Release) | ||
|
||
# deliberately not including these subdirectories by glob regex as precaution | ||
|
||
include_directories(include/algorithms/sort) | ||
include_directories(include/data_structures/vector) | ||
include_directories(util) | ||
|
||
enable_testing() | ||
include(CTest) | ||
|
||
add_subdirectory(tests/data_structures/vector) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
set(MEMORYCHECK_COMMAND valgrind) | ||
set(MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
This is free and unencumbered software released into the public domain. | ||
|
||
Anyone is free to copy, modify, publish, use, compile, sell, or | ||
distribute this software, either in source code form or as a compiled | ||
binary, for any purpose, commercial or non-commercial, and by any | ||
means. | ||
|
||
In jurisdictions that recognize copyright laws, the author or authors | ||
of this software dedicate any and all copyright interest in the | ||
software to the public domain. We make this dedication for the benefit | ||
of the public at large and to the detriment of our heirs and | ||
successors. We intend this dedication to be an overt act of | ||
relinquishment in perpetuity of all present and future rights to this | ||
software under copyright law. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
OTHER DEALINGS IN THE SOFTWARE. | ||
|
||
For more information, please refer to <https://unlicense.org> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
# Prime Headers | ||
## Header-only, type-safe, generic data structures and algorithms for C. | ||
|
||
[](https://github.com/prathameshd30/prime-headers/actions/workflows/cmake-multi-platform-val.yml) | ||
|
||
Prime Headers is (aiming to be) a headers-only, easy to use, type-safe way to use generic data structures and algorithms in C Projects. | ||
|
||
It aims to have each data structure and algorithm thoroughly tested with primitive and pointer-to-structs examples. | ||
|
||
It works primarily by ~~ab~~using the C preprocessor to a scale hitherto undreamt of (I have later realised that this scale was indeed dreamt to). | ||
|
||
It uses macros with arguments to generate the appropriate structs and functions at the preprocessing stage, leading to no runtime overhead. However, this approach has definite drawbacks, which are clarified further. | ||
|
||
It uses CMake as the build system, Valgrind for checking memory safety (which needs to be migrated to AddressSanitizer as Valgrind is too slow) and GitHub Actions for checking cross-platform compatibility. | ||
|
||
### Features | ||
- [x] Header-only, generic, type-safe data structures and algorithms. | ||
- [x] Build tested on multiple platforms and compilers using CMake and GitHub actions. | ||
- [x] Unit tested using CTest. | ||
- [x] Memory profiled using Valgrind. | ||
- [x] Supports primitive data structures as well as pointer-to-structs. | ||
|
||
### Currently Tested Platforms | ||
- Ubuntu | ||
- gcc | ||
- clang | ||
- Windows | ||
- cl (MSVC) | ||
|
||
### To Do | ||
- [x] Use GitHub Actions for testing | ||
- [x] Use Valgrind for testing | ||
- [x] Setup CMake, CTest and GitHub actions | ||
- [ ] Migrate memory profiler to AddressSanitizer from Valgrind | ||
- [ ] Write primitive as well as pointer-to-structs examples for each data structure and algorithm | ||
|
||
### Checklist | ||
- Each function, with pointer parameters, should check for NULL for each pointer parameter. | ||
- Have a thorough deletion mechanism for each data structure. | ||
- Library functions in snake_case_##DATA_STRUCTURE().. | ||
- All reallocs need to be first assigned to temp variables, so as to not lose access to data. | ||
|
||
### To build and test locally | ||
After ensuring you have the prerequisite dependencies (CMake and Valgrind), run these commands in the root directory of the repository. | ||
```bash | ||
$ pwd # Make sure you are in the root directory of the repository | ||
$ mkdir build | ||
$ cd build | ||
$ cmake .. | ||
$ cmake --build . | ||
$ ctest # Just run the tests without memory profiling | ||
$ ctest -T memcheck -C Debug --test-dir ../build # Valgrind memcheck and test | ||
``` | ||
|
||
### Data structures and algorithms implemented | ||
|
||
> The project is a work in progress, with an emphasis on getting things working first. Apologies for the ugly/(currently wrong) code. | ||
- [x] Vector | ||
- [x] Stack using Vector | ||
- [x] Stack using Linked List | ||
- [x] Queue using Vector | ||
- [x] Queue using Linked List | ||
- [x] Deque (Double Ended Queue) using Vector | ||
- [x] Deque (Double Ended Queue) using Doubly Linked List | ||
- [x] Singly Linked List | ||
- [ ] Set | ||
- [ ] Unordered Set | ||
- [ ] Map | ||
- [ ] Unordered Map (Hashmap) | ||
- [ ] Circular Singly Linked List | ||
- [x] Doubly Linked List | ||
- [ ] Circular Doubly Linked List | ||
- [ ] Generalized Linked List | ||
- [ ] Heap | ||
- [x] Binary Tree (Generation using 2 traversals left) | ||
- [x] Binary Search Tree (Done recursively, TODO delete for all 3 cases) | ||
- [ ] AVL Tree | ||
- [ ] RB Tree | ||
|
||
### Algorithms implemented | ||
|
||
- [x] Linear Search in Vector | ||
- [x] Linear Search in SLL | ||
- [ ] Binary Search | ||
- [x] Bubble Sort | ||
- [x] Selection Sort | ||
- [x] Insertion Sort | ||
- [ ] Merge Sort | ||
- [ ] Quick sort | ||
|
||
### Pros | ||
|
||
1. Relatively easy use of generic data structures and algorithms while being type-safe. | ||
2. Is cool, I mean what is cooler than preprocessor hijinks. | ||
|
||
### Cons | ||
|
||
1. This method is optimised for ease of use (probably for beginners/learners because it primarily works with pointers to structs), however, defining multiple data structures in the same file may (read WILL) lead to **slower compilation times** due to large compilation units because of the coupling of interfaces (headers & prototypes) and the actual functionality (function definitions) itself. | ||
2. **Poor support** (slow) for Intellisense and similar code intelligence and autocompletion tools. | ||
3. As all the functions are defined in the macro, with everything being in C, there is no way to apply **access modifiers** to helper functions for a cleaner interface and hacks like using double underscores seem inelegant. | ||
|
||
> This project is a side-effect of trying to develop a command-line tool for easier use of generic data structures for C, which splits the interface and the function definitions, leading to better compilation times. | ||
## Some helpful projects which helped me develop this | ||
|
||
1. Thought this was an original idea, but this repository I found later implemented this already - https://github.com/mystborn/GenericDataStructures | ||
|
||
2. I got the idea for the need of type-safe data structures by seeing this repository, otherwise it is perfect, especially the error handling is **chef's kiss** - https://github.com/MostafaTwfiq/C-DataStructures-And-Algorithms |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#ifndef BINARY_SEARCH_ARR_H | ||
#define BINARY_SEARCH_ARR_H | ||
|
||
#include <stdint.h> | ||
|
||
#define DEFINE_BINARY_SEARCH_ARR(NAME, TYPE)\ | ||
TYPE* recursive_binary_helper_##NAME(TYPE* arr, uint64_t low, uint64_t high, TYPE val, int16_t (*comparator)(TYPE, TYPE)){\ | ||
if(high >= low){\ | ||
uint64_t mid = (low+high)/2;\ | ||
int16_t res = comparator(val ,arr[mid]);\ | ||
if(res == 0){\ | ||
return &(arr[mid]);\ | ||
}\ | ||
else if(res < 0){\ | ||
return recursive_binary_helper_##NAME(arr, low, mid, val, comparator);\ | ||
}\ | ||
else if(res > 0){\ | ||
return recursive_binary_helper_##NAME(arr, mid+1, high, val, comparator);\ | ||
}\ | ||
}\ | ||
return NULL;\ | ||
}\ | ||
TYPE* recursive_binary_search_##NAME(TYPE* arr, size_t size, TYPE val ,int16_t (*comparator)(TYPE,TYPE)){\ | ||
uint64_t low = 0;\ | ||
uint64_t high = size - 1;\ | ||
return recursive_binary_helper_##NAME(arr, low, high, val, comparator);\ | ||
}\ | ||
|
||
|
||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#ifndef LINEAR_SEARCH | ||
#define LINEAR_SEARCH | ||
|
||
#include <stdbool.h> | ||
#include <stdint.h> | ||
|
||
#define DEFINE_LINEAR_SEARCH_ARR(NAME, TYPE)\ | ||
bool linear_search_##NAME(TYPE* arr, uint64_t arrSize, bool(*comparator)(TYPE,TYPE), TYPE ref ,uint64_t* index){\ | ||
for (uint64_t i = 0; i < count; ++i){\ | ||
if(comparator(ref,arr[i])){\ | ||
*index = i;\ | ||
return true;\ | ||
}\ | ||
}\ | ||
return false;\ | ||
} | ||
|
||
#endif |
Oops, something went wrong.