Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/actions/run-ci-container/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: 'Run CI Docker container'
description: 'Download Docker image archive and runs it as a container.'
runs:
using: "composite"
steps:
- name: Download CI image
uses: actions/download-artifact@v4
with:
name: docker-ci-image
- name: Run CI container
shell: bash
run: |
chmod +x -R data_structures_library/scripts/
docker load -i=ci-image.tar
docker run -v="$(pwd):/home/workspace" -dt --name="data-structures-v2" "data-structures-v2" "/bin/bash"
68 changes: 68 additions & 0 deletions .github/workflows/library.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: "C++ library pipeline"
on:
push
jobs:
prepare_docker_image:
name: "Create CI Docker container"
runs-on: ubuntu-22.04
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: Prepare image
run: |
docker build . -t "data-structures-v2"
docker save -o ci-image.tar data-structures-v2
- name: Store image
uses: actions/upload-artifact@v4
with:
name: docker-ci-image
path: ci-image.tar
retention-days: 1

build:
name: "Build C++ library for Linux"
runs-on: ubuntu-22.04
needs: prepare_docker_image
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: "Run CI container"
uses: ./.github/actions/run-ci-container
- name: Build
run: docker exec data-structures-v2 "data_structures_library/scripts/build-library.sh"
- name: Store build
uses: actions/upload-artifact@v4
with:
name: data-structures-lib.a
path: data_structures_library/build/lib/data-structures.a

test:
name: "Test C++ library"
runs-on: ubuntu-22.04
needs: prepare_docker_image
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: "Run CI container"
uses: ./.github/actions/run-ci-container
- name: Build tests
run: docker exec data-structures-v2 "data_structures_library/scripts/build-tests.sh"
- name: Test
run: docker exec data-structures-v2 "data_structures_library/scripts/test.sh"
- name: Store report
uses: actions/upload-artifact@v4
with:
name: data-structures-lib-coverage.html
path: data_structures_library/build/coverage.html

lint:
name: "Lint C++ library"
runs-on: ubuntu-22.04
needs: prepare_docker_image
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: "Run CI container"
uses: ./.github/actions/run-ci-container
- name: Lint
run: docker exec data-structures-v2 "data_structures_library/scripts/lint.sh"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode
20 changes: 20 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM ubuntu:22.04

ENV PROJECT_ROOT="/home/workspace"

ENV LIB_ROOT="${PROJECT_ROOT}/data_structures_library"
ENV LIB_BUILD="${LIB_ROOT}/build"

SHELL ["/bin/bash", "-c"]
RUN mkdir /home/workspace
WORKDIR /home/workspace

RUN apt-get update -y
RUN apt-get upgrade -y
RUN apt-get install clang -y
RUN apt-get install git -y
RUN apt-get install cmake -y
RUN apt-get install clang-tidy -y
RUN apt-get install libc++-14-dev -y
RUN apt-get install libc++abi-14-dev -y
RUN apt-get install llvm -y
2 changes: 2 additions & 0 deletions data_structures_library/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build/
Testing/
15 changes: 15 additions & 0 deletions data_structures_library/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.22.1)

project("Data Structure Library")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-instr-generate")

set(LIB_TARGET_NAME "data-structures")
set(TEST_TARGET_NAME "data-structures-tests")

enable_testing()

add_subdirectory(library)
add_subdirectory(tests)
19 changes: 19 additions & 0 deletions data_structures_library/library/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
add_library(
${LIB_TARGET_NAME}
STATIC
"src/dynamic-array.cpp"
)

target_include_directories(
${LIB_TARGET_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)

set_target_properties(
${LIB_TARGET_NAME}
PROPERTIES
OUTPUT_NAME ${LIB_TARGET_NAME}
PREFIX ""
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
)
114 changes: 114 additions & 0 deletions data_structures_library/library/include/dynamic-array.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#ifndef DYNAMIC_ARRAY_H
#define DYNAMIC_ARRAY_H


#include <memory>
#include <span>


class DynamicArray
{
public:

/**
* Creates new dynamic array with given length & filled with given deafult value.
*
* @param initial_length Initial length of the array.
* @param default_value Value that would be used to fill the array.
*/
DynamicArray(const std::size_t& initial_length = 0, const int& default_value = 0);

/* Creates deep copy of array. */
DynamicArray(const DynamicArray& to_copy);
DynamicArray(DynamicArray&& to_move) = default;
DynamicArray& operator=(DynamicArray&& to_move) = default;
DynamicArray& operator=(const DynamicArray& to_copy);
~DynamicArray() = default;

/* === Elements access === */

// Random access
int& operator[](const size_t& index) { return std::span<int>(mData.get(), mLength)[index]; }
const int& operator[](const size_t& index) const { return std::span<int>(mData.get(), mLength)[index]; }

// Acces to first element
int& front() { return std::span<int>(mData.get(), mLength).front(); }
[[nodiscard]] const int& front() const { return std::span<int>(mData.get(), mLength).front(); }

// Access to last element
int& back() { return std::span<int>(mData.get(), mLength).back(); }
[[nodiscard]] const int& back() const { return std::span<int>(mData.get(), mLength).back(); }

/* === Capacity === */

// Get number of elements
[[nodiscard]] size_t size() const { return mLength; }

/* === Modification === */

/**
* Inserts new element at selected index. The rest of the elements in the array would be shifted one position
* to the right.
*
* @param position Index where element would be placed.
* @param value Value that would be inserted.
*
* @return Exit code.
* @retval 0 - element inserted.
* @retval 1 - position out of bounds.
*/
int insert(const size_t& position, const int& value);

/**
* Inserts new element at first position. The rest of the elements in the array would be shifted one position to the
* right.
*
* @param value Value that would be inserted.
*/
void push_front(const int& value);

/**
* Inserts new element at last position.
*
* @param value Value that would be inserted.
*/
void push_back(const int& value);

/**
* Removes element from given position. All elements to the right of this position would be shifted one position
* to the right.
*
* @param position Position that would be removed.
*
* @return Exit code.
* @retval 0 - element removed.
* @retval 1 - array's empty.
* @retval 2 - position out of bounds.
*/
int erase(const std::size_t& position);

/**
* Removes first element. All other elements would be shifted one position to the right.
*
* @return Exit code.
* @retval 0 - element removed.
* @retval 1 - array's empty.
*/
int pop_front();

/**
* Removes last element.
*
* @return Exit code.
* @retval 0 - element's removed.
* @retval 1 - array's empty.
*/
int pop_back();

private:

std::shared_ptr<int[]> mData;
size_t mLength;
};

#endif
49 changes: 49 additions & 0 deletions data_structures_library/library/src/dynamic-array.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef DYNAMIC_ARRAY_CPP
#define DYNAMIC_ARRAY_CPP

#include <stdexcept>

#include "dynamic-array.hpp"

DynamicArray::DynamicArray(const std::size_t& initial_length, const int& default_value):
mLength(initial_length)
{
mData = std::shared_ptr<int[]>(new int[mLength]);
for (int& element : std::span<int>(mData.get(), mLength))
{
element = default_value;
}
}

DynamicArray::DynamicArray(const DynamicArray &to_copy):
mLength(to_copy.mLength)
{
throw std::logic_error("Not yet implemented!");
}

DynamicArray &DynamicArray::operator=(const DynamicArray &to_copy)
{
throw std::logic_error("Not yet implemented!");
}

int DynamicArray::insert(const std::size_t& position, const int& value)
{
throw std::logic_error("Not yet implemented!");
}

void DynamicArray::push_front(const int& value)
{
throw std::logic_error("Not yet implemented!");
}

void DynamicArray::push_back(const int& value)
{
throw std::logic_error("Not yet implemented!");
}

int DynamicArray::erase(const std::size_t& position)
{
throw std::logic_error("Not yet implemented!");
}

#endif
5 changes: 5 additions & 0 deletions data_structures_library/scripts/build-library.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

cmake -S "${LIB_ROOT}" -B "${LIB_BUILD}" -DCMAKE_EXPORT_COMPILE_COMMANDS=on
cd "${LIB_ROOT}/library"
cmake --build ${LIB_BUILD} --target "data-structures"
6 changes: 6 additions & 0 deletions data_structures_library/scripts/build-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

cmake -S "${LIB_ROOT}" -B "${LIB_BUILD}" -DCMAKE_EXPORT_COMPILE_COMMANDS=on
cd "${LIB_ROOT}/tests"
cmake --build ${LIB_BUILD} --target "data-structures-tests"

12 changes: 12 additions & 0 deletions data_structures_library/scripts/lint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

echo "Running linter for C++ library"

clang-tidy \
${LIB_ROOT}/library/src/*.cpp ${LIB_ROOT}/library/include/*.hpp \
-p build/ \
-checks=-*,cppcoreguidelines-*,cert-*,clang-analyzer-*,cppcoreguidelines-*,modernize-*,performance-*,portability-*,readability-*,-modernize-use-trailing-return-type,-cppcoreguidelines-avoid-c-arrays,-modernize-avoid-c-arrays\
-warnings-as-errors=* \
-- \
-I "${LIB_ROOT}/library/include" \
-std=c++20
13 changes: 13 additions & 0 deletions data_structures_library/scripts/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

cd ${LIB_BUILD}
ctest --output-on-failure

llvm-profdata merge -o unittest.profdata ${LIB_BUILD}/tests/*.profraw
llvm-cov report ${LIB_BUILD}/lib/data-structures.a -instr-profile=unittest.profdata -use-color -show-region-summary=false

llvm-cov show ${LIB_BUILD}/lib/data-structures.a \
-instr-profile=unittest.profdata \
-format=html \
-show-branches=count \
> coverage.html
31 changes: 31 additions & 0 deletions data_structures_library/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/52eb8108c5bdec04579160ae17225d66034bd723.zip
)
FetchContent_MakeAvailable(googletest)

add_executable(
${TEST_TARGET_NAME}
"ut/dynamic-array/default-initialization.cpp"
)

target_link_libraries(
${TEST_TARGET_NAME}
PRIVATE
${LIB_TARGET_NAME}
GTest::gtest_main
)

set_target_properties(
${TEST_TARGET_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)

include(GoogleTest)
gtest_discover_tests(${TEST_TARGET_NAME}
DISCOVERY_MODE PRE_TEST
PROPERTIES
ENVIRONMENT "LLVM_PROFILE_FILE=coverage-%m-%p.profraw"
)
Loading
Loading