diff options
author | 2021-10-05 03:34:45 +1100 | |
---|---|---|
committer | 2021-10-05 03:34:45 +1100 | |
commit | aeb9eae87469e67bc6a91caf3840c34c11d959fc (patch) | |
tree | 45bffedf374dbce47caca633ad7bda547592e6c9 /src/lib/util/ioprocs.cpp | |
parent | 33723892a3f06e678d817b36aef84364c32848ec (diff) |
util: Further API cleanups: (#8661)
* Turned `core_file` into an implementation of `random_read_write`.
* Turned PNG errors into a standard error category.
* Added a helper for generating what look like derived classes on-the-fly.
Diffstat (limited to 'src/lib/util/ioprocs.cpp')
-rw-r--r-- | src/lib/util/ioprocs.cpp | 354 |
1 files changed, 0 insertions, 354 deletions
diff --git a/src/lib/util/ioprocs.cpp b/src/lib/util/ioprocs.cpp index 1f52a3daf97..0dcea206571 100644 --- a/src/lib/util/ioprocs.cpp +++ b/src/lib/util/ioprocs.cpp @@ -736,296 +736,6 @@ public: } }; - -// helper class for holding a core_file and closing it (or not) as necessary - -class core_file_adapter_base : public virtual random_access -{ -public: - virtual ~core_file_adapter_base() - { - if (m_close) - delete m_file; - } - - virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override - { - if (!m_file->seek(offset, whence)) - return std::error_condition(); - else - return std::errc::invalid_argument; // TODO: better error reporting for core_file - } - - virtual std::error_condition tell(std::uint64_t &result) noexcept override - { - // no error reporting - result = m_file->tell(); - return std::error_condition(); - } - - virtual std::error_condition length(std::uint64_t &result) noexcept override - { - // no error reporting - result = m_file->size(); - return std::error_condition(); - } - -protected: - core_file_adapter_base(core_file::ptr &&file) noexcept : m_file(file.release()), m_close(true) - { - assert(m_file); - } - - core_file_adapter_base(core_file &file) noexcept : m_file(&file), m_close(false) - { - } - - core_file &file() noexcept - { - return *m_file; - } - -private: - core_file *const m_file; - bool const m_close; -}; - - -// core_file read implementation - -class core_file_read_adapter : public core_file_adapter_base, public virtual random_read -{ -public: - core_file_read_adapter(core_file::ptr &&file) noexcept : core_file_adapter_base(std::move(file)) - { - } - - core_file_read_adapter(core_file &file) noexcept : core_file_adapter_base(file) - { - } - - virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override - { - // TODO: should the client have to deal with reading less than expected even if EOF isn't hit? - if (std::numeric_limits<std::uint32_t>::max() < length) - { - actual = 0U; - return std::errc::invalid_argument; - } - - // no way to distinguish between EOF and error - actual = file().read(buffer, std::uint32_t(length)); - return std::error_condition(); - } - - virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override - { - actual = 0U; - - // TODO: should the client have to deal with reading less than expected even if EOF isn't hit? - if (std::numeric_limits<std::uint32_t>::max() < length) - return std::errc::invalid_argument; - - // no error reporting for tell - std::uint64_t const oldpos = file().tell(); - if (file().seek(offset, SEEK_SET)) - { - file().seek(oldpos, SEEK_SET); - return std::errc::invalid_argument; // TODO: better error reporting for core_file - } - - // no way to distinguish between EOF and error - actual = file().read(buffer, std::uint32_t(length)); - - if (!file().seek(oldpos, SEEK_SET)) - return std::error_condition(); - else - return std::errc::invalid_argument; // TODO: better error reporting for core_file - } -}; - - -// core_file read/write implementation - -class core_file_read_write_adapter : public core_file_read_adapter, public random_read_write -{ -public: - using core_file_read_adapter::core_file_read_adapter; - - virtual std::error_condition finalize() noexcept override - { - return std::error_condition(); - } - - virtual std::error_condition flush() noexcept override - { - return file().flush(); - } - - virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override - { - actual = 0U; - while (length) - { - std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length); - std::uint32_t const written = file().write(buffer, chunk); - actual += written; - if (written < chunk) - return std::errc::io_error; // TODO: better error reporting for core_file - buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written; - length -= written; - } - return std::error_condition(); - } - - virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override - { - actual = 0U; - - // no error reporting for tell - std::uint64_t const oldpos = file().tell(); - if (file().seek(offset, SEEK_SET)) - { - file().seek(oldpos, SEEK_SET); - return std::errc::invalid_argument; // TODO: better error reporting for core_file - } - - std::error_condition err; - while (!err && length) - { - std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length); - std::uint32_t const written = file().write(buffer, chunk); - actual += written; - if (written < chunk) - { - err = std::errc::io_error; // TODO: better error reporting for core_file - } - else - { - buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written; - length -= written; - } - } - - if (!file().seek(oldpos, SEEK_SET) || err) - return err; - else - return std::errc::invalid_argument; // TODO: better error reporting for core_file - } -}; - - -// core_file helper that fills space when writing past the end-of-file - -class core_file_read_write_filler : public random_read_fill_wrapper<core_file_read_write_adapter> -{ -public: - core_file_read_write_filler(core_file::ptr &&file, std::uint8_t fill) noexcept : random_read_fill_wrapper<core_file_read_write_adapter>(std::move(file)) - { - set_filler(fill); - } - - core_file_read_write_filler(core_file &file, std::uint8_t fill) noexcept : random_read_fill_wrapper<core_file_read_write_adapter>(file) - { - set_filler(fill); - } - - virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override - { - // no error reporting for tell or size - std::uint64_t const offset = file().tell(); - std::uint64_t endpos = file().size(); - if (endpos < offset) - { - if (file().seek(endpos, SEEK_SET)) - { - file().seek(offset, SEEK_SET); - actual = 0U; - return std::errc::invalid_argument; // TODO: better error reporting for core_file - } - std::uint8_t block[1024]; - std::fill_n( - block, - std::min<std::common_type_t<std::size_t, std::uint64_t> >(std::size(block), offset - endpos), - get_filler()); - do - { - std::uint32_t const chunk = std::min<std::common_type_t<std::size_t, std::uint64_t> >(sizeof(block), offset - endpos); - std::uint32_t const filled = file().write(block, chunk); - endpos += filled; - if (chunk != filled) - { - file().seek(offset, SEEK_SET); - actual = 0U; - return std::errc::io_error; // TODO: better error reporting for core_file - } - } - while (endpos < offset); - } - - return core_file_read_write_adapter::write(buffer, length, actual); - } - - virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override - { - actual = 0U; - - // no error reporting for tell - std::uint64_t const oldpos = file().tell(); - if (file().seek(0, SEEK_END)) - { - file().seek(oldpos, SEEK_SET); - return std::errc::invalid_argument; // TODO: better error reporting for core_file - } - std::uint64_t endpos = file().tell(); - - std::error_condition err; - if (endpos > offset) - { - if (file().seek(offset, SEEK_SET)) - err = std::errc::invalid_argument; // TODO: better error reporting for core_file - } - else if (endpos < offset) - { - std::uint8_t block[1024]; - std::fill_n( - block, - std::min<std::common_type_t<std::size_t, std::uint64_t> >(std::size(block), offset - endpos), - get_filler()); - do - { - std::uint32_t const chunk = std::min<std::common_type_t<std::size_t, std::uint64_t> >(sizeof(block), offset - endpos); - std::uint32_t const filled = file().write(block, chunk); - endpos += filled; - if (chunk != filled) - err = std::errc::io_error; // TODO: better error reporting for core_file - } - while (!err && (endpos < offset)); - } - - while (!err && length) - { - std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length); - std::uint32_t const written = file().write(buffer, chunk); - actual += written; - if (written < chunk) - { - err = std::errc::io_error; // TODO: better error reporting for core_file - } - else - { - buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written; - length -= written; - } - } - - if (!file().seek(oldpos, SEEK_SET) || err) - return err; - else - return std::errc::invalid_argument; // TODO: better error reporting for core_file - } -}; - } // anonymous namespace @@ -1181,68 +891,4 @@ random_read_write::ptr osd_file_read_write(osd_file &file) noexcept return random_read_write::ptr(new (std::nothrow) osd_file_read_write_adapter(file)); } - -// creating core_file read adapters - -random_read::ptr core_file_read(core_file::ptr &&file) noexcept -{ - random_read::ptr result; - if (file) - result.reset(new (std::nothrow) core_file_read_adapter(std::move(file))); - return result; -} - -random_read::ptr core_file_read(core_file::ptr &&file, std::uint8_t filler) noexcept -{ - std::unique_ptr<random_read_fill_wrapper<core_file_read_adapter> > result; - if (file) - result.reset(new (std::nothrow) decltype(result)::element_type(std::move(file))); - if (result) - result->set_filler(filler); - return result; -} - -random_read::ptr core_file_read(core_file &file) noexcept -{ - return random_read::ptr(new (std::nothrow) core_file_read_adapter(file)); -} - -random_read::ptr core_file_read(core_file &file, std::uint8_t filler) noexcept -{ - std::unique_ptr<random_read_fill_wrapper<core_file_read_adapter> > result; - result.reset(new (std::nothrow) decltype(result)::element_type(file)); - if (result) - result->set_filler(filler); - return result; -} - - -// creating core_file read/write adapters - -random_read_write::ptr core_file_read_write(core_file::ptr &&file) noexcept -{ - random_read_write::ptr result; - if (file) - result.reset(new (std::nothrow) core_file_read_write_adapter(std::move(file))); - return result; -} - -random_read_write::ptr core_file_read_write(core_file::ptr &&file, std::uint8_t filler) noexcept -{ - random_read_write::ptr result; - if (file) - result.reset(new (std::nothrow) core_file_read_write_filler(std::move(file), filler)); - return result; -} - -random_read_write::ptr core_file_read_write(core_file &file) noexcept -{ - return random_read_write::ptr(new (std::nothrow) core_file_read_write_adapter(file)); -} - -random_read_write::ptr core_file_read_write(core_file &file, std::uint8_t filler) noexcept -{ - return random_read_write::ptr(new (std::nothrow) core_file_read_write_filler(file, filler)); -} - } // namespace util |