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
3 changes: 2 additions & 1 deletion cmake/load_dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ find_package(magic_enum REQUIRED CONFIG)
find_package(CLI11 REQUIRED CONFIG)
find_package(Eigen3 REQUIRED CONFIG)
find_package(GSL REQUIRED)
find_package(indicators REQUIRED)

if(ENABLE_TEST)
find_package(GTest CONFIG REQUIRED)
find_package(GTest CONFIG REQUIRED)
endif()
1 change: 1 addition & 0 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def requirements(self):
self.requires("magic_enum/0.9.7") # type: ignore
self.requires("cli11/2.6.0") # type: ignore
self.requires("eigen/5.0.1") # type: ignore
self.requires("indicators/2.3") # type: ignore

# Conditions on cmake variables set from cmake/project_options
if os.environ["CMAKE_ENABLE_TEST"] == "ON":
Expand Down
1 change: 1 addition & 0 deletions source/centipede/reader/binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ namespace centipede::reader
{
return std::unexpected{ size.error() };
}
last_entry_bytes_ = (read_size + 1U) * sizeof(uint32_t);
++n_entries_;
size_ = size.value();
return size.value();
Expand Down
27 changes: 21 additions & 6 deletions source/centipede/reader/binary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <cstddef>
#include <cstdint>
#include <expected>
#include <filesystem>
#include <fstream>
#include <iterator>
#include <span>
Expand Down Expand Up @@ -169,6 +170,15 @@ namespace centipede::reader
*/
[[nodiscard]] constexpr auto get_n_entries() const -> std::size_t { return n_entries_; }

// TODO: Add documentation
[[nodiscard]] auto get_file_size() const -> std::size_t
{
return static_cast<std::size_t>(std::filesystem::file_size(config_.in_filename));
}

// TODO: Add documentation
[[nodiscard]] auto get_last_entry_bytes() const -> std::size_t { return last_entry_bytes_; }

/**
* @brief Checks if last read operation reached end of file.
* @return Returns true if end of file is reached.
Expand All @@ -181,7 +191,7 @@ namespace centipede::reader
* The status is updated during iteration and after manual read operations.
*
* @return
* - ErrorCode::invalid while iteration/reading is in progress.
* - ErrorCode::incomplete while iteration/reading is in progress.
* - ErrorCode::success if iteration finished successfully.
* - Any other ErrorCode if a read or parsing error occurred.
*/
Expand Down Expand Up @@ -235,7 +245,7 @@ namespace centipede::reader
explicit Iterator(Binary* reader_ptr)
: reader_{ reader_ptr }
{
reader_->status_ = ErrorCode::invalid;
reader_->status_ = ErrorCode::incomplete;
++(*this);
}

Expand Down Expand Up @@ -276,7 +286,7 @@ namespace centipede::reader
}

current_ = reader_->get_current_entry();
reader_->status_ = ErrorCode::invalid;
reader_->status_ = ErrorCode::incomplete;
return *this;
}
/**
Expand All @@ -296,7 +306,10 @@ namespace centipede::reader
*
* @return Returns true while iteration is not finished.
*/
auto operator!=(const Sentinel&) const -> bool { return reader_->status_ == ErrorCode::invalid; }
auto operator!=(const Sentinel&) const -> bool { return reader_->status_ == ErrorCode::incomplete; }

// TODO: add documentation
bool operator==(Sentinel) const { return reader_->status_ != ErrorCode::incomplete; }

private:
Binary* reader_{}; //!< Associated Binary reader instance.
Expand Down Expand Up @@ -324,8 +337,10 @@ namespace centipede::reader
std::ifstream input_file_; //!< Input file handler
std::size_t size_{}; //!< Number of Entrypoints in the current entry
std::size_t n_entries_{}; //!< Total number of entries read by this instance
bool end_of_file_{ false }; //!< Indicates if end of file is reached. Gets updated on read.
ErrorCode status_{ ErrorCode::invalid };
std::size_t last_entry_bytes_{}; // TODO: Add documentation

bool end_of_file_{ false }; //!< Indicates if end of file is reached. Gets updated on read.
ErrorCode status_{ ErrorCode::incomplete };

void reset();
auto read_entry_to_buffer(uint32_t read_size) -> EnumError<>;
Expand Down
4 changes: 3 additions & 1 deletion source/centipede/util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ target_sources(
PUBLIC
FILE_SET publicHeaders
TYPE HEADERS
FILES common_traits.hpp error_types.hpp return_types.hpp
FILES common_traits.hpp error_types.hpp return_types.hpp progress_indicator.hpp
)

target_link_libraries(core PUBLIC indicators::indicators)
3 changes: 3 additions & 0 deletions source/centipede/util/error_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace centipede
// TODO: duplication of comments
invalid, //!< Error due to no evaluation!
success, //!< No error. All good!
incomplete, //!< Operation incomplete!
handler_incomp_n_locals, //!< Incompatible number of local variables from the current entrypoint.
writer_neg_or_zero_sigma, //!< Zero or negative sigma occurs. See @ref writer::Binary.
writer_buffer_overflow, //!< Buffer size is too small for a new entry occurs. See @ref writer::Binary.
Expand Down Expand Up @@ -99,6 +100,8 @@ struct std::formatter<centipede::ErrorCode>
return std::format_to(ctx.out(), "Reader: Filename is either empty or invalid!");
case invalid:
return std::format_to(ctx.out(), "Error due to no evaluation!");
case incomplete:
return std::format_to(ctx.out(), "Operation incomplete!");
default:
break;
}
Expand Down
182 changes: 182 additions & 0 deletions source/centipede/util/progress_indicator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#include <cstddef>
#include <functional>
#include <indicators/color.hpp>
#include <indicators/font_style.hpp>
#include <indicators/progress_bar.hpp>
#include <indicators/setting.hpp>
#include <ranges>
#include <utility>
#include <vector>

namespace centipede::progress
{
// TODO:
// Overload ProgressAdaptor () to:
// 1) iterate over n elements (instead of increment_fun)
// 2) iterate by 1 (for standard ranges)
// ProgressAdaptor constructor that takes some config struct (to config the prog bar)
// Error Handling!
// Ehm, testing?
class ProgressAdaptor;

using IncrementFunT = std::function<std::size_t()>;

template <typename RangeT>
requires std::ranges::range<RangeT>
using BaseView = std::views::all_t<RangeT>;

struct ProgressClosure : std::ranges::range_adaptor_closure<ProgressClosure>
{
ProgressAdaptor* adaptor;
std::size_t total_size_n;
IncrementFunT increment_fun;

template <typename RangeT>
requires std::ranges::range<RangeT>
auto operator()(RangeT&& range)
{
return (*adaptor)(std::forward<RangeT>(range), total_size_n, increment_fun);
}
};

class ProgressAdaptor
{
public:
template <typename RangeT>
requires std::ranges::range<RangeT>
auto operator()(RangeT&& range, std::size_t total_size_n, IncrementFunT increment_fun)
{
return ProgressView<BaseView<RangeT>>{
this, std::views::all(std::forward<RangeT>(range)), total_size_n, std::move(increment_fun)
};
}

template <typename RangeT>
requires std::ranges::range<RangeT>
auto operator()(RangeT&& range, std::size_t total_size_n)
{
return ProgressView<BaseView<RangeT>>{ this,
std::views::all(std::forward<RangeT>(range)),
total_size_n,
std::move([]() -> std::size_t { return 1; }) };
}

auto operator()(std::size_t total_size_n)
{
return ProgressClosure{ {}, this, total_size_n, []() -> std::size_t { return 1; } };
}

auto operator()(std::size_t total_size_n, IncrementFunT increment_fun)
{
return ProgressClosure{ {}, this, total_size_n, std::move(increment_fun) };
}

template <typename RangeT>
requires std::ranges::range<RangeT>
struct ProgressView
{
using BaseView = std::views::all_t<RangeT>;
using IteratorType = std::ranges::iterator_t<RangeT>;
using SentinelType = std::ranges::sentinel_t<RangeT>;

ProgressView(ProgressAdaptor* progress_adaptor,
BaseView base_view,
std::size_t total_size_n,
IncrementFunT increment_fun)
: base_view_(std::move(base_view))
, total_size_n_(total_size_n)
, increment_fun_(increment_fun)
, progress_adaptor_(progress_adaptor)
{
}

auto begin()
{
return Iterator{
progress_adaptor_, this, std::ranges::begin(base_view_), std::ranges::end(base_view_)
};
}

auto end() { return Sentinel{}; }
struct Sentinel
{
};

class Iterator
{
public:
Iterator(ProgressAdaptor* progress_adaptor,
ProgressView* progress_view,
IteratorType current_it,
SentinelType end_it)
: progress_adaptor_(progress_adaptor)
, progress_view_(progress_view)
, current_it_(current_it)
, end_it_(end_it)
{
}

auto operator++()
{
++current_it_;
++element_count_;
add_progress();
return *this;
}

auto operator*() { return *current_it_; }

bool operator==(Sentinel)
{
return current_it_ == end_it_ || element_count_ >= progress_view_->total_size_n_;
}

bool operator!=(Sentinel sentinel) { return !(*this == sentinel); }

bool operator==(Sentinel) const
{
return current_it_ == end_it_ || element_count_ >= progress_view_->total_size_n_;
}

bool operator!=(Sentinel sentinel) const { return !(*this == sentinel); }

void add_progress()
{
count_n_ += progress_view_->increment_fun_();
const auto percent = 100 * count_n_ / progress_view_->total_size_n_;
progress_adaptor_->bar_.set_progress(percent);
if (percent == 100)
{
progress_adaptor_->bar_.mark_as_completed();
}
}

private:
ProgressAdaptor* progress_adaptor_;
ProgressView* progress_view_;
IteratorType current_it_;
SentinelType end_it_;
std::size_t element_count_{};
std::size_t count_n_{};
};

private:
BaseView base_view_;
std::size_t total_size_n_;
IncrementFunT increment_fun_;
ProgressAdaptor* progress_adaptor_;
};

private:
indicators::ProgressBar bar_{ indicators::option::BarWidth{ 50 },
indicators::option::Start{ "[" },
indicators::option::Fill{ "=" },
indicators::option::Lead{ ">" },
indicators::option::Remainder{ " " },
indicators::option::End{ "]" },
indicators::option::ForegroundColor{ indicators::Color::green },
indicators::option::ShowPercentage{ true },
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{ indicators::FontStyle::bold } } };
};
} // namespace centipede::progress
23 changes: 20 additions & 3 deletions test/integration_tests/test_reader.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#include "centipede/reader/binary.hpp"
#include "centipede/util/error_types.hpp"
#include "centipede/util/progress_indicator.hpp"
#include <array>
#include <cstdlib>
#include <print>
#include <ranges>

auto main() -> int
{
static_assert(std::ranges::range<centipede::reader::Binary>);
static_assert(std::ranges::input_range<centipede::reader::Binary>);
auto reader = centipede::reader::Binary{ centipede::reader::Binary::Config{ .in_filename = "output.bin" } };
auto init_err = reader.init();
if (not init_err.has_value())
Expand All @@ -12,14 +18,19 @@ auto main() -> int
return EXIT_FAILURE;
}

for ([[maybe_unused]] const auto& entry : reader)
auto progress_adaptor = centipede::progress::ProgressAdaptor{};
for ([[maybe_unused]] const auto& entry :
reader | progress_adaptor(reader.get_file_size(), [&reader]() { return reader.get_last_entry_bytes(); }))
{
}

if (not reader.is_ok())
{
std::println(stderr, "Error: {}", reader.get_status());
return EXIT_FAILURE;
if (reader.get_status() != centipede::ErrorCode::incomplete)
{
std::println(stderr, "Error: {}", reader.get_status());
return EXIT_FAILURE;
}
}

if (reader.get_n_entries() == 0U)
Expand All @@ -28,5 +39,11 @@ auto main() -> int
return EXIT_FAILURE;
}

auto array = std::array{ 1, 2, 3, 4 };

for ([[maybe_unused]] auto elem : array | progress_adaptor(array.size()))
{
}

return EXIT_SUCCESS;
}
Loading