Skip to content

Commit

Permalink
recovery recommit
Browse files Browse the repository at this point in the history
  • Loading branch information
prathameshd30 committed Jan 7, 2025
0 parents commit 865e169
Show file tree
Hide file tree
Showing 40 changed files with 2,216 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .github/ISSUE_TEMPLATE/add-tests.md
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? -
110 changes: 110 additions & 0 deletions .github/workflows/cmake-multi-platform-val.yml
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



29 changes: 29 additions & 0 deletions .gitignore
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
19 changes: 19 additions & 0 deletions CMakeLists.txt
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)
2 changes: 2 additions & 0 deletions CTestCustom.cmake
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")
24 changes: 24 additions & 0 deletions LICENSE
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>
109 changes: 109 additions & 0 deletions README.md
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.

[![Multiplatform CMake Build, CTest, Valgrind Profiling](https://github.com/prathameshd30/prime-headers/actions/workflows/cmake-multi-platform-val.yml/badge.svg)](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
31 changes: 31 additions & 0 deletions include/algorithms/search/binary_search_arr.h
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
18 changes: 18 additions & 0 deletions include/algorithms/search/linear_search_arr.h
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
Loading

0 comments on commit 865e169

Please sign in to comment.