Skip to content

Commit

Permalink
Ensure class/structs name consistency, add more docs (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
es3n1n authored Oct 12, 2024
1 parent b702a03 commit 3689ecd
Show file tree
Hide file tree
Showing 21 changed files with 468 additions and 321 deletions.
58 changes: 38 additions & 20 deletions src/lib/es3n1n/common/defer.hpp
Original file line number Diff line number Diff line change
@@ -1,27 +1,45 @@
#pragma once
#include <memory>
#include "base.hpp"
#include "macros.hpp"
#include <utility>

#define CAT_(x, y) x##y
#define CAT(x, y) CAT_(x, y)
/// \brief A class that holds a callable object and executes it upon destruction.
/// \tparam Callable The type of the callable object.
template <typename Callable>
class DeferHolder : public base::NonCopyable {
public:
/// \brief Constructor that takes a callable object.
/// \param callable The callable object to be executed upon destruction.
explicit DeferHolder(Callable&& callable) noexcept: callable_(std::forward<Callable>(callable)) { }

#define defer auto CAT(_defer_instance_, __COUNTER__) = defer_::defer_{} % [&]()
/// \brief Destructor that executes the stored callable object.
~DeferHolder() {
callable_();
}

namespace defer_ {
template <typename callable>
struct type {
callable cb;
private:
Callable callable_; ///< The stored callable object.
};

explicit type(callable&& _cb): cb(std::forward<callable>(_cb)) { }
/// \brief A helper class for creating deferred execution objects.
class Defer : public base::NonCopyable {
public:
/// \brief Default constructor.
constexpr Defer() noexcept = default;

~type() {
cb();
}
};
/// \brief Default destructor.
constexpr ~Defer() noexcept = default;

struct defer_ {
template <typename callable>
type<callable> operator%(callable&& cb) {
return type<callable>{std::forward<callable>(cb)};
}
};
} // namespace defer_
/// \brief Overloaded modulus operator to create a DeferHolder object.
/// \tparam Callable The type of the callable object.
/// \param cb The callable object to be deferred.
/// \return A DeferHolder object containing the callable.
template <typename Callable>
DeferHolder<Callable> operator%(Callable&& cb) {
return DeferHolder<Callable>{std::forward<Callable>(cb)};
}
};

/// \brief Create a deferred execution object.
/// \note This macro creates a unique variable name for each use.
#define defer auto COMMON_CAT(_defer_instance_, __LINE__) = Defer{} % [&]()
47 changes: 31 additions & 16 deletions src/lib/es3n1n/common/files.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,46 @@
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <optional>
#include <vector>

namespace files {
inline std::vector<std::uint8_t> read_file(const std::filesystem::path& path) {
std::fstream file(path, std::ios::in | std::ios::binary);
if (!file) {
/// \brief Calculates the size of a file.
/// \param file A reference to an open input file stream.
/// \return An optional containing the file size in bytes if successful,
/// or an empty optional if the file is not in a good state.
inline std::optional<std::size_t> file_size(std::ifstream& file) {
if (!file.good()) {
return {};
}

file.seekg(0, std::fstream::end);
const auto f_size = file.tellg();
file.seekg(0, std::fstream::beg);

std::vector<uint8_t> buffer(static_cast<const unsigned int>(f_size));
file.seekg(0, std::ios::end);
const auto file_size = file.tellg();
file.seekg(0, std::ios::beg);
return static_cast<std::size_t>(file_size);
}

// NOLINTNEXTLINE
file.read(reinterpret_cast<char*>(buffer.data()), buffer.size());
/// \brief Reads the contents of a file into a vector of bytes.
/// \param path The filesystem path to the file to be read.
/// \return A vector of unsigned 8-bit integers containing the file contents.
/// Returns std::nullopt if the file cannot be opened.
inline std::optional<std::vector<std::uint8_t>> read_file(const std::filesystem::path& path) {
std::ifstream file(path, std::ios::binary);
if (!file.good()) {
return {};
}

std::vector<std::uint8_t> buffer(file_size(file).value());
file.read(reinterpret_cast<char*>(buffer.data()), static_cast<std::streamsize>(buffer.size()));
return buffer;
}

inline void write_file(const std::filesystem::path& path, const std::uint8_t* raw_buffer, const size_t buffer_size) {
std::ofstream file(path, std::ios::binary | std::ios::out);
// NOLINTNEXTLINE
file.write(reinterpret_cast<const char*>(raw_buffer), buffer_size);
file.close();
/// \brief Writes a buffer of bytes to a file.
/// \param path The filesystem path where the file should be written.
/// \param raw_buffer Pointer to the buffer containing the data to be written.
/// \param buffer_size The size of the buffer in bytes.
inline void write_file(const std::filesystem::path& path, const std::uint8_t* raw_buffer, const std::size_t buffer_size) {
std::ofstream file(path, std::ios::binary);
file.write(reinterpret_cast<const char*>(raw_buffer), static_cast<std::streamsize>(buffer_size));
}
} // namespace files
} // namespace files
14 changes: 7 additions & 7 deletions src/lib/es3n1n/common/linalg/matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace linalg {
/// \tparam Ty The type of elements in the matrix (must be a number type).
/// \tparam Rows The number of rows in the matrix.
/// \tparam Cols The number of columns in the matrix.
template <traits::number Ty, std::size_t Rows, std::size_t Cols>
template <traits::Number Ty, std::size_t Rows, std::size_t Cols>
class Matrix {
public:
/// \brief Default constructor.
Expand Down Expand Up @@ -180,17 +180,17 @@ namespace linalg {

/// \brief Alias for 4x4 matrices.
/// \tparam Ty The type of elements in the matrix (must be a number type).
template <traits::number Ty>
using mat4x4_t = Matrix<Ty, 4, 4>;
template <traits::Number Ty>
using Matrix4x4 = Matrix<Ty, 4, 4>;

/// \brief Alias for 3x4 matrices.
/// \tparam Ty The type of elements in the matrix (must be a number type).
template <traits::number Ty>
using mat3x4_t = Matrix<Ty, 3, 4>;
template <traits::Number Ty>
using Matrix3x4 = Matrix<Ty, 3, 4>;

/// \brief Alias for 4x4 matrices of 32-bit floats.
using mat4x4f32_t = mat4x4_t<float>;
using Matrix4x4f32 = Matrix4x4<float>;

/// \brief Alias for 3x4 matrices of 32-bit floats.
using mat3x4f32_t = mat3x4_t<float>;
using Matrix3x4f32 = Matrix3x4<float>;
} // namespace linalg
39 changes: 16 additions & 23 deletions src/lib/es3n1n/common/linalg/vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace linalg {
/// \brief A templated vector class representing an N-dimensional vector of numeric type Ty
/// \tparam Ty The numeric type of the vector components
/// \tparam N The dimension of the vector
template <traits::number Ty, std::size_t N>
template <traits::Number Ty, std::size_t N>
class Vector {
public:
/// \brief Default constructor
Expand Down Expand Up @@ -240,42 +240,35 @@ namespace linalg {
};

/// \brief Type alias for 2D vector
template <traits::number Ty>
using vec2_t = Vector<Ty, 2>;
template <traits::Number Ty>
using Vector2 = Vector<Ty, 2>;

/// \brief Type alias for 3D vector
template <traits::number Ty>
using vec3_t = Vector<Ty, 3>;
template <traits::Number Ty>
using Vector3 = Vector<Ty, 3>;

/// \brief Type alias for 4D vector
template <traits::number Ty>
using vec4_t = Vector<Ty, 4>;
template <traits::Number Ty>
using Vector4 = Vector<Ty, 4>;

/// \brief Type alias for 2D vector of unsigned 32-bit integers
using vec2u32_t = vec2_t<std::uint32_t>;
using Vector2u32 = Vector2<std::uint32_t>;
/// \brief Type alias for 3D vector of unsigned 32-bit integers
using vec3u32_t = vec3_t<std::uint32_t>;
using Vector3u32 = Vector3<std::uint32_t>;
/// \brief Type alias for 4D vector of unsigned 32-bit integers
using vec4u32_t = vec4_t<std::uint32_t>;
using Vector4u32 = Vector4<std::uint32_t>;

/// \brief Type alias for 2D vector of signed 32-bit integers
using vec2i32_t = vec2_t<std::int32_t>;
using Vector2i32 = Vector2<std::int32_t>;
/// \brief Type alias for 3D vector of signed 32-bit integers
using vec3i32_t = vec3_t<std::int32_t>;
using Vector3i32 = Vector3<std::int32_t>;
/// \brief Type alias for 4D vector of signed 32-bit integers
using vec4i32_t = vec4_t<std::int32_t>;
using Vector4i32 = Vector4<std::int32_t>;

/// \brief Type alias for 2D vector of 32-bit floats
using vec2f32_t = vec2_t<float>;
using Vector2f32 = Vector2<float>;
/// \brief Type alias for 3D vector of 32-bit floats
using vec3f32_t = vec3_t<float>;
using Vector3f32 = Vector3<float>;
/// \brief Type alias for 4D vector of 32-bit floats
using vec4f32_t = vec4_t<float>;

/// \brief Type alias for 2D vector of 64-bit doubles
using vec2f64_t = vec2_t<double>;
/// \brief Type alias for 3D vector of 64-bit doubles
using vec3f64_t = vec3_t<double>;
/// \brief Type alias for 4D vector of 64-bit doubles
using vec4f64_t = vec4_t<double>;
using Vector4f32 = Vector4<float>;
} // namespace linalg
7 changes: 7 additions & 0 deletions src/lib/es3n1n/common/macros.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

/// \brief Concatenate two tokens.
#define COMMON_CAT_(x, y) x##y

/// \brief Concatenate two tokens (indirect).
#define COMMON_CAT(x, y) COMMON_CAT_(x, y)
44 changes: 22 additions & 22 deletions src/lib/es3n1n/common/memory/address.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,67 +53,67 @@ namespace memory {
/// \param buffer Pointer to the data to write
/// \param size Size of the data to write
/// \return Expected containing this address on success, or an error code on failure
std::expected<Address, e_error_code> write(const void* buffer, std::size_t size) {
std::expected<Address, ErrorCode> write(const void* buffer, std::size_t size) {
return memory::reader.write(address_, buffer, size).transform([this](auto) { return *this; });
}

/// \brief Write a trivially copyable value to the address
/// \tparam Ty Type of the value to write (must be trivially copyable)
/// \param value The value to write
/// \return Expected containing this address on success, or an error code on failure
template <traits::trivially_copyable Ty>
std::expected<Address, e_error_code> write(Ty value) {
template <traits::TriviallyCopyable Ty>
std::expected<Address, ErrorCode> write(Ty value) {
return memory::reader.write(&value, address_).transform([this](auto) { return *this; });
}

/// \brief Read a trivially copyable value from the address
/// \tparam Ty Type of the value to read (must be trivially copyable)
/// \return Expected containing the read value on success, or an error code on failure
template <traits::trivially_copyable Ty>
[[nodiscard]] std::expected<Ty, e_error_code> read() const {
template <traits::TriviallyCopyable Ty>
[[nodiscard]] std::expected<Ty, ErrorCode> read() const {
return memory::reader.read<Ty>(address_);
}

/// \brief Read a trivially copyable value from the address into a provided destination
/// \tparam Ty Type of the value to read (must be trivially copyable)
/// \param dst Pointer to the destination where the read value will be stored
/// \return Expected containing the destination pointer on success, or an error code on failure
template <traits::trivially_copyable Ty>
std::expected<Ty*, e_error_code> read(Ty* dst) const {
template <traits::TriviallyCopyable Ty>
std::expected<Ty*, ErrorCode> read(Ty* dst) const {
return memory::reader.read(dst, address_).transform([dst](auto) { return dst; });
}

/// \brief Read a vector of bytes from the address
/// \param size Number of bytes to read
/// \return Expected containing the read vector on success, or an error code on failure
[[nodiscard]] std::expected<std::vector<std::uint8_t>, e_error_code> read_vector(std::size_t size) const {
[[nodiscard]] std::expected<std::vector<std::uint8_t>, ErrorCode> read_vector(std::size_t size) const {
std::vector<std::uint8_t> result(size);
return memory::reader.read(result.data(), address_, size).transform([&result](auto) { return result; });
}

/// \brief Dereference the address to read a value
/// \tparam Ty Type of the value to read (default is address)
/// \return Expected containing the dereferenced value on success, or an error code on failure
template <traits::trivially_copyable Ty = Address>
[[nodiscard]] std::expected<Ty, e_error_code> deref() const {
template <traits::TriviallyCopyable Ty = Address>
[[nodiscard]] std::expected<Ty, ErrorCode> deref() const {
return memory::reader.read<Ty>(inner());
}

/// \brief Get a value by dereferencing the address multiple times
/// \tparam Ty Type of the value to read (default is address)
/// \param count Number of times to dereference (default is 1)
/// \return Expected containing the final dereferenced value on success, or an error code on failure
template <traits::trivially_copyable Ty = Address>
[[nodiscard]] std::expected<Ty, e_error_code> get(std::size_t count = 1) const noexcept {
template <traits::TriviallyCopyable Ty = Address>
[[nodiscard]] std::expected<Ty, ErrorCode> get(std::size_t count = 1) const noexcept {
if (!address_ || count == 0) {
return std::unexpected(e_error_code::INVALID_ADDRESS);
return std::unexpected(ErrorCode::INVALID_ADDRESS);
}

auto tmp = *this;
for (std::size_t i = 1; i < count; ++i) {
auto deref_value = tmp.deref();
if (!deref_value) {
return std::unexpected(e_error_code::NOT_ENOUGH_BYTES);
return std::unexpected(ErrorCode::NOT_ENOUGH_BYTES);
}
tmp = *deref_value;
}
Expand All @@ -125,7 +125,7 @@ namespace memory {
/// \tparam Ty Type of the pointer (default is address)
/// \param offset Offset to add to the address (default is 0)
/// \return Pointer of type Ty* to the address (plus offset)
template <traits::trivially_copyable Ty = Address>
template <traits::TriviallyCopyable Ty = Address>
[[nodiscard]] constexpr Ty* ptr(std::ptrdiff_t offset = 0) const noexcept {
return this->offset(offset).as<std::add_pointer_t<Ty>>();
}
Expand All @@ -134,7 +134,7 @@ namespace memory {
/// \tparam Ty Type of the pointer (default is address)
/// \param offset Offset to add to the address before getting the pointer (default is 0)
/// \return Pointer of type Ty* to the original address (plus offset)
template <traits::trivially_copyable Ty = Address>
template <traits::TriviallyCopyable Ty = Address>
[[nodiscard]] constexpr Ty* self_inc_ptr(std::ptrdiff_t offset = 0) noexcept {
Ty* result = ptr<Ty>(offset);
*this = Address{result}.offset(sizeof(Ty));
Expand All @@ -146,8 +146,8 @@ namespace memory {
/// \param data The data to write
/// \param offset Offset to add to the address before writing (default is 0)
/// \return Expected containing this address on success, or an error code on failure
template <traits::trivially_copyable Ty>
std::expected<Address, e_error_code> self_write_inc(const Ty& data, std::ptrdiff_t offset = 0) noexcept {
template <traits::TriviallyCopyable Ty>
std::expected<Address, ErrorCode> self_write_inc(const Ty& data, std::ptrdiff_t offset = 0) noexcept {
auto result = this->offset(offset).write(data);
*this = this->offset(offset + sizeof(Ty));
return result;
Expand Down Expand Up @@ -194,7 +194,7 @@ namespace memory {
/// \brief Cast the address to another type (alias for cast)
/// \tparam Ty The destination type (must be trivially copyable)
/// \return The address cast to the specified type
template <traits::trivially_copyable Ty>
template <traits::TriviallyCopyable Ty>
[[nodiscard]] constexpr Ty as() const noexcept {
return cast<Ty>();
}
Expand All @@ -203,7 +203,7 @@ namespace memory {
/// \tparam Ty The integral type to read
/// \return Expected containing the read value on success, or an error code on failure
template <std::integral Ty>
[[nodiscard]] std::expected<Ty, e_error_code> read_le() const {
[[nodiscard]] std::expected<Ty, ErrorCode> read_le() const {
auto result = read<Ty>();
if (!result) {
return result;
Expand All @@ -218,7 +218,7 @@ namespace memory {
/// \tparam Ty The integral type to read
/// \return Expected containing the read value on success, or an error code on failure
template <std::integral Ty>
[[nodiscard]] std::expected<Ty, e_error_code> read_be() const {
[[nodiscard]] std::expected<Ty, ErrorCode> read_be() const {
auto result = read<Ty>();
if (!result) {
return result;
Expand Down Expand Up @@ -342,7 +342,7 @@ struct std::formatter<memory::Address> : std::formatter<std::uintptr_t> {
/// Custom hash implementation for std::hash to use this type in containers
template <>
struct std::hash<memory::Address> {
size_t operator()(const memory::Address& instance) const noexcept {
std::size_t operator()(const memory::Address& instance) const noexcept {
return std::hash<std::uintptr_t>()(instance.inner());
}
};
Loading

0 comments on commit 3689ecd

Please sign in to comment.