From 3509b411d21f079d64a0574a89605567eb42614f Mon Sep 17 00:00:00 2001 From: matteokeole Date: Fri, 14 Nov 2025 16:17:37 +0100 Subject: [PATCH 1/3] feat: sequence and view --- Base/{Types.hpp => Aliases.hpp} | 0 Base/Base.hpp | 11 ++-- Base/Context.hpp | 8 ++- Base/Types/base_sequence.hpp | 109 ++++++++++++++++++++++++++++++++ Base/Types/base_view.hpp | 44 +++++++++++++ Base/Types/sequence.hpp | 46 ++++++++++++++ Base/Types/view.hpp | 64 +++++++++++++++++++ Base/Utilities.hpp | 8 +++ Base/buffer.hpp | 100 ----------------------------- Base/str8.hpp | 105 ------------------------------ 10 files changed, 284 insertions(+), 211 deletions(-) rename Base/{Types.hpp => Aliases.hpp} (100%) create mode 100644 Base/Types/base_sequence.hpp create mode 100644 Base/Types/base_view.hpp create mode 100644 Base/Types/sequence.hpp create mode 100644 Base/Types/view.hpp create mode 100644 Base/Utilities.hpp delete mode 100644 Base/buffer.hpp delete mode 100644 Base/str8.hpp diff --git a/Base/Types.hpp b/Base/Aliases.hpp similarity index 100% rename from Base/Types.hpp rename to Base/Aliases.hpp diff --git a/Base/Base.hpp b/Base/Base.hpp index e54e987..863916b 100644 --- a/Base/Base.hpp +++ b/Base/Base.hpp @@ -1,4 +1,4 @@ -// Copyright 2025 Atalante. +// Copyright 2025 Atalante. // Licensed under MIT. #pragma once @@ -9,13 +9,14 @@ #include "Context.hpp" #include "Macros.hpp" -#include "Types.hpp" + +#include "Aliases.hpp" #include "Limits.hpp" #include "Cast.hpp" +#include "Utilities.hpp" #include "Bit.hpp" - -#include "buffer.hpp" -#include "str8.hpp" +#include "Types/sequence.hpp" +#include "Types/view.hpp" #if OPERATING_SYSTEM == OPERATING_SYSTEM_WINDOWS #include diff --git a/Base/Context.hpp b/Base/Context.hpp index 51e3da8..cd86e88 100644 --- a/Base/Context.hpp +++ b/Base/Context.hpp @@ -1,4 +1,4 @@ -// Copyright 2025 Atalante. +// Copyright 2025 Atalante. // Licensed under MIT. #pragma once @@ -57,4 +57,10 @@ #define ARCHITECTURE ARCHITECTURE_INTEL_X86 #else #define ARCHITECTURE ARCHITECTURE_OTHER +#endif + +#if STANDARD >= STANDARD_CPP17 + #define CONSTEXPR_CPP17 constexpr +#else + #define CONSTEXPR_CPP17 #endif \ No newline at end of file diff --git a/Base/Types/base_sequence.hpp b/Base/Types/base_sequence.hpp new file mode 100644 index 0000000..4e8061a --- /dev/null +++ b/Base/Types/base_sequence.hpp @@ -0,0 +1,109 @@ +// Copyright 2025 Atalante. +// Licensed under MIT. + +#pragma once + +namespace ProjectA { + // TODO(upgrade): Allocate from arena. + template + class base_sequence { + private: + static T* allocate(uint64 count) { + return new T[count](); + } + + static void free(const T* data) { + delete[] data; + } + + public: + base_sequence() = default; + + explicit base_sequence(uint64 count) : + _count(count), + _data(allocate(_count)) + {} + + base_sequence(std::initializer_list list) : + base_sequence(list.size()) + { + copy(list.begin(), list.end(), _data); + } + + base_sequence(const base_sequence& sequence) : + base_sequence(sequence._count) + { + copy(sequence.begin(), sequence.end(), _data); + } + + base_sequence(base_sequence&& sequence) noexcept : + _count(sequence._count) + { + _data = sequence._data; + + sequence._count = 0; + sequence._data = nullptr; + } + + ~base_sequence() { + free(_data); + } + + void operator=(const base_sequence& sequence) { + free(_data); + + _count = sequence._count; + _data = allocate(_count); + + copy(sequence.begin(), sequence.end(), _data); + } + + void operator=(base_sequence&& sequence) noexcept { + ASSERT(_data != sequence._data); + + _count = sequence._count; + _data = sequence._data; + + sequence._count = 0; + sequence._data = nullptr; + } + + uint64 count() const { + return _count; + } + + const T& operator[](uint64 index) const { + // TODO: Always allow 0? + ASSERT(index < _count); + + return _data[index]; + } + + T& operator[](uint64 index) { + // TODO: Always allow 0? + ASSERT(index < _count); + + return _data[index]; + } + + const T* begin() const { + return _data; + } + + T* begin() { + return _data; + } + + const T* end() const { + return _data + _count; + } + + T* end() { + return _data + _count; + } + + protected: + uint64 _count = 0; + T* _data = nullptr; + }; +} \ No newline at end of file diff --git a/Base/Types/base_view.hpp b/Base/Types/base_view.hpp new file mode 100644 index 0000000..cba70ad --- /dev/null +++ b/Base/Types/base_view.hpp @@ -0,0 +1,44 @@ +// Copyright 2025 Atalante. +// Licensed under MIT. + +#pragma once + +namespace ProjectA { + template + class base_view { + public: + explicit base_view() = default; + + base_view(const base_sequence& sequence) : + _count(sequence.count()), + _data(sequence.begin()) + {} + + constexpr explicit base_view(const char8* data, uint64 count) : + _count(count), + _data(data) + {} + + uint64 count() const { + return _count; + } + + const T& operator[](uint64 index) const { + ASSERT(index < _count); + + return _data[index]; + } + + const T* begin() const { + return _data; + } + + const T* end() const { + return _data + _count; + } + + protected: + const uint64 _count = 0; + const T* _data = nullptr; + }; +} \ No newline at end of file diff --git a/Base/Types/sequence.hpp b/Base/Types/sequence.hpp new file mode 100644 index 0000000..bd9375a --- /dev/null +++ b/Base/Types/sequence.hpp @@ -0,0 +1,46 @@ +// Copyright 2025 Atalante. +// Licensed under MIT. + +#pragma once + +#include "Types/base_sequence.hpp" +#include "Types/base_view.hpp" + +namespace ProjectA { + // A container that encapsulates a dynamic size array. + // Unlike `std::vector`, `sequence` is not resizeable. + // It *should* be used when the number of elements is known at runtime, before creating the sequence. + // + // NOTE: `T` **must** expose a default constructor. + template + class sequence : public base_sequence { + public: + using base_sequence::base_sequence; + }; + + template<> + class sequence : public base_sequence { + public: + using base_sequence::base_sequence; + + explicit sequence(const char8* data, uint64 count) : + sequence(count + 1) + { + _count -= 1; + + copy(data, data + _count, _data); + } + + sequence(const char8* data) : + sequence(data, std::strlen(data)) + {} + + sequence(base_view view) : + sequence(&view[0], view.count()) + {} + + sequence(const sequence& sequence) : + sequence(sequence.begin(), sequence.count()) + {} + }; +} \ No newline at end of file diff --git a/Base/Types/view.hpp b/Base/Types/view.hpp new file mode 100644 index 0000000..92fccea --- /dev/null +++ b/Base/Types/view.hpp @@ -0,0 +1,64 @@ +// Copyright 2025 Atalante. +// Licensed under MIT. + +#pragma once + +#include "Types/base_view.hpp" + +namespace ProjectA { + template + class view : public base_view { + public: + using base_view::base_view; + }; + + template<> + class view : public base_view { + public: + using base_view::base_view; + + // TODO: Add support for versions below C++17. + CONSTEXPR_CPP17 view(const char8* data) : + view(data, std::char_traits::length(data)) + {} + + uint64 find(char8 character, uint64 characterOffset) const { + while (characterOffset < count()) { + if (_data[characterOffset] == character) { + break; + } + + characterOffset += 1; + } + + return characterOffset; + } + + uint64 find(view view, uint64 characterOffset) const { + uint64 characterIndex; + uint64 viewCharacterIndex; + + while (characterOffset < count()) { + if (view.count() > count() - characterOffset) { + return count(); + } + + characterIndex = characterOffset; + viewCharacterIndex = 0; + + while (_data[characterIndex] == view[viewCharacterIndex]) { + characterIndex += 1; + viewCharacterIndex += 1; + + if (characterIndex >= count() || viewCharacterIndex >= view.count()) { + return characterOffset; + } + } + + characterOffset += 1; + } + + return characterOffset; + } + }; +} \ No newline at end of file diff --git a/Base/Utilities.hpp b/Base/Utilities.hpp new file mode 100644 index 0000000..63193a8 --- /dev/null +++ b/Base/Utilities.hpp @@ -0,0 +1,8 @@ +#pragma once + +namespace ProjectA { + template + inline void copy(const T* sourceBegin, const T* sourceEnd, T* destination) { + std::copy(sourceBegin, sourceEnd, destination); + } +} \ No newline at end of file diff --git a/Base/buffer.hpp b/Base/buffer.hpp deleted file mode 100644 index 897234d..0000000 --- a/Base/buffer.hpp +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2025 Atalante. -// Licensed under MIT. - -#pragma once - -namespace ProjectA { - // An owning and non-resizeable array of elements of type `T`. - // NOTE: `T` must expose a default constructor. - template - class buffer { - public: - buffer() = default; - - explicit buffer(uint64 _count) : - _count(_count), - pointer(new T[_count]()) - {} - - buffer(const std::initializer_list& list) : - buffer(list.size()) - { - std::copy(list.begin(), list.end(), pointer); - } - - buffer(const buffer& buffer) : - buffer(buffer._count) - { - std::copy(buffer.begin(), buffer.end(), pointer); - } - - buffer(buffer&& buffer) : - _count(buffer._count), - pointer(buffer.pointer) - { - buffer.pointer = nullptr; - buffer._count = 0; - } - - ~buffer() { - delete[] pointer; - } - - uint64 count() const { - return _count; - } - - buffer& operator =(const buffer& buffer) { - delete[] pointer; - - pointer = new T[buffer._count](); - _count = buffer._count; - - std::copy(buffer.begin(), buffer.end(), pointer); - - return *this; - } - - buffer& operator =(buffer&& buffer) { - pointer = buffer.pointer; - _count = buffer._count; - - buffer.pointer = nullptr; - buffer._count = 0; - - return *this; - } - - const T& operator [](uint64 index) const { - ASSERT(index == 0 || index < _count); - - return pointer[index]; - } - - T& operator [](uint64 index) { - ASSERT(index == 0 || index < _count); - - return pointer[index]; - } - - const T* begin() const { - return &pointer[0]; - } - - T* begin() { - return &pointer[0]; - } - - const T* end() const { - return &pointer[_count]; - } - - T* end() { - return &pointer[_count]; - } - - protected: - uint64 _count = 0; - T* pointer = nullptr; - }; -} \ No newline at end of file diff --git a/Base/str8.hpp b/Base/str8.hpp deleted file mode 100644 index 7c5c7d0..0000000 --- a/Base/str8.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2025 Atalante. -// Licensed under MIT. - -#pragma once - -namespace ProjectA { - class str8 : public buffer { - public: - str8() = default; - - explicit str8(uint64 count) : - buffer(count) - {} - - // NOTE: Returns a null-terminated string. - str8(const char8* characters) : - buffer(std::strlen(characters) + 1) - { - // Exclude '\0' from the character count. - _count -= 1; - - std::copy_n(characters, _count, begin()); - - pointer[_count] = '\0'; - } - - str8(const std::string& string) : - buffer(string.size() + 1) - { - // Exclude '\0' from the character count. - _count -= 1; - - std::copy(string.begin(), string.end(), begin()); - - pointer[_count] = '\0'; - } - - str8(const buffer& buffer) : - buffer(buffer.count() + 1) - { - // Exclude '\0' from the character count. - _count -= 1; - - std::copy(buffer.begin(), buffer.end(), begin()); - - pointer[_count] = '\0'; - } - - str8(buffer&& buffer) : - buffer(buffer) - {} - - str8& operator =(const str8& string) { - delete[] pointer; - - pointer = new char8[string._count + 1](); - _count = string._count; - - std::copy(string.begin(), string.end(), pointer); - - pointer[_count] = '\0'; - - return *this; - } - - uint64 find(char8 character, uint64 characterOffset) const { - while (characterOffset < count()) { - if (operator[](characterOffset) == character) { - break; - } - - characterOffset += 1; - } - - return characterOffset; - } - - uint64 find(const str8& string, uint64 characterOffset) const { - uint64 characterIndex; - uint64 stringCharacterIndex; - - while (characterOffset < count()) { - if (string.count() > count() - characterOffset) { - return count(); - } - - characterIndex = characterOffset; - stringCharacterIndex = 0; - - while (operator[](characterIndex) == string[stringCharacterIndex]) { - characterIndex += 1; - stringCharacterIndex += 1; - - if (characterIndex >= count() || stringCharacterIndex >= string.count()) { - return characterOffset; - } - } - - characterOffset += 1; - } - - return characterOffset; - } - }; -} \ No newline at end of file From b74e93d385c2015bee3dcb382616473523e8698d Mon Sep 17 00:00:00 2001 From: matteokeole Date: Fri, 14 Nov 2025 16:20:54 +0100 Subject: [PATCH 2/3] ci: Fix copyright license script --- .github/workflows/check_copyright_license_headers.yaml | 1 - scripts/check_copyright_license_headers.sh | 10 +++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check_copyright_license_headers.yaml b/.github/workflows/check_copyright_license_headers.yaml index 8126223..fabc664 100644 --- a/.github/workflows/check_copyright_license_headers.yaml +++ b/.github/workflows/check_copyright_license_headers.yaml @@ -20,7 +20,6 @@ jobs: chmod +x ./scripts/check_copyright_license_headers.sh ./scripts/check_copyright_license_headers.sh env: - HEADER: "// Copyright 2025 Atalante.\n// Licensed under MIT." GITHUB_BASE_REF: ${{github.base_ref}} GITHUB_HEAD_REF: ${{github.head_ref}} GITHUB_TREE_URL: ${{github.server_url}}/${{github.repository}}/tree/${{github.head_ref}} \ No newline at end of file diff --git a/scripts/check_copyright_license_headers.sh b/scripts/check_copyright_license_headers.sh index 87931e3..1a2037e 100644 --- a/scripts/check_copyright_license_headers.sh +++ b/scripts/check_copyright_license_headers.sh @@ -1,16 +1,20 @@ #!/bin/bash -files=$(git diff --diff-filter=d --name-only origin/$GITHUB_BASE_REF origin/$GITHUB_HEAD_REF -- ***.{cpp,hpp,ipp}) +HEADER=$'// Copyright 2025 Atalante.\n// Licensed under MIT.' + +files=$(git diff --diff-filter=d --name-only origin/$GITHUB_BASE_REF origin/$GITHUB_HEAD_REF -- *.{cpp,hpp,ipp}) unlicensed_files=() for file in $files; do - if [[ $(head -n 2 $file) != "$HEADER" ]]; then + line=$(head -n 2 $file | sed "s/^\xef\xbb\xbf//") + + if [ "$line" != "$HEADER" ]; then unlicensed_files+=($file) fi done if [[ ${#unlicensed_files[@]} -gt 0 ]]; then - echo "The following file(s) don't start with a copyright license header." >> $GITHUB_STEP_SUMMARY + echo "The following file(s) don't have a valid copyright license header." >> $GITHUB_STEP_SUMMARY for file in "${unlicensed_files[@]}"; do echo "- [$file]($GITHUB_TREE_URL/$file)" >> $GITHUB_STEP_SUMMARY From 12a5b83e67ccecfdc8ed2d36afe9a426068de60b Mon Sep 17 00:00:00 2001 From: matteokeole Date: Fri, 14 Nov 2025 17:17:35 +0100 Subject: [PATCH 3/3] fix: Add missing copyright license header --- Base/Utilities.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Base/Utilities.hpp b/Base/Utilities.hpp index 63193a8..b4d87b2 100644 --- a/Base/Utilities.hpp +++ b/Base/Utilities.hpp @@ -1,3 +1,6 @@ +// Copyright 2025 Atalante. +// Licensed under MIT. + #pragma once namespace ProjectA {