diff --git a/cdoc/Crypto.cpp b/cdoc/Crypto.cpp index 0a1525ea..81ac0c3c 100644 --- a/cdoc/Crypto.cpp +++ b/cdoc/Crypto.cpp @@ -449,7 +449,7 @@ EncryptionConsumer::EncryptionConsumer(DataConsumer &dst, const EVP_CIPHER *ciph } result_t -EncryptionConsumer::write(const uint8_t *src, size_t size) +EncryptionConsumer::write(const uint8_t *src, size_t size) noexcept try { if(!src || size == 0) return OK; @@ -460,10 +460,12 @@ EncryptionConsumer::write(const uint8_t *src, size_t size) if(SSL_FAILED(EVP_CipherUpdate(ctx.get(), buf.data(), &len, src, int(size)), "EVP_CipherUpdate")) return CRYPTO_ERROR; return dst.write(buf.data(), size_t(len)); +} catch(...) { + return OUTPUT_STREAM_ERROR; } result_t -EncryptionConsumer::writeAAD(const std::vector &data) +EncryptionConsumer::writeAAD(const std::vector &data) noexcept { int len = 0; if(SSL_FAILED(EVP_CipherUpdate(ctx.get(), nullptr, &len, data.data(), int(data.size())), "EVP_CipherUpdate")) @@ -472,7 +474,7 @@ EncryptionConsumer::writeAAD(const std::vector &data) } result_t -EncryptionConsumer::close() +EncryptionConsumer::close() noexcept try { buf.resize(std::max(buf.size(), size_t(EVP_CIPHER_CTX_block_size(ctx.get())))); int len = int(buf.size()); @@ -498,6 +500,8 @@ EncryptionConsumer::close() return IO_ERROR; } return OK; +} catch(...) { + return OUTPUT_STREAM_ERROR; } DecryptionSource::DecryptionSource(DataSource &src, const std::string &method, const std::vector &key, size_t ivLen) @@ -531,7 +535,7 @@ result_t DecryptionSource::updateAAD(const std::vector &data) return OK; } -result_t DecryptionSource::read(unsigned char *dst, size_t size) +result_t DecryptionSource::read(unsigned char *dst, size_t size) noexcept { if (error != OK) return error; diff --git a/cdoc/Crypto.h b/cdoc/Crypto.h index 5304d494..a8b980e4 100644 --- a/cdoc/Crypto.h +++ b/cdoc/Crypto.h @@ -114,10 +114,10 @@ struct EncryptionConsumer final : public DataConsumer { EncryptionConsumer(DataConsumer &dst, const std::string &method, const Crypto::Key &key); EncryptionConsumer(DataConsumer &dst, const EVP_CIPHER *cipher, const Crypto::Key &key); CDOC_DISABLE_MOVE_COPY(EncryptionConsumer) - result_t write(const uint8_t *src, size_t size) final; - result_t writeAAD(const std::vector &data); - result_t close() final; - bool isError() final { return error != OK || dst.isError(); } + result_t write(const uint8_t *src, size_t size) noexcept final; + result_t writeAAD(const std::vector &data) noexcept; + result_t close() noexcept final; + bool isError() noexcept final { return error != OK || dst.isError(); } private: unique_free_t ctx; @@ -131,11 +131,11 @@ struct DecryptionSource final : public DataSource { DecryptionSource(DataSource &src, const EVP_CIPHER *cipher, const std::vector &key, size_t ivLen = 0); CDOC_DISABLE_MOVE_COPY(DecryptionSource) - result_t read(unsigned char* dst, size_t size) final; + result_t read(unsigned char* dst, size_t size) noexcept final; result_t updateAAD(const std::vector& data); result_t close(); - bool isError() final { return error != OK || src.isError(); } - bool isEof() final { return src.isEof(); } + bool isError() noexcept final { return error != OK || src.isError(); } + bool isEof() noexcept final { return src.isEof(); } private: unique_free_t ctx; diff --git a/cdoc/DDocReader.cpp b/cdoc/DDocReader.cpp index 8756d52b..643c3cfc 100644 --- a/cdoc/DDocReader.cpp +++ b/cdoc/DDocReader.cpp @@ -47,13 +47,16 @@ struct DDocFileListConsumer : public libcdoc::MultiDataConsumer { std::vector &files; DDocFileListConsumer(std::vector &_files): files(_files) {} - int64_t write(const uint8_t *src, size_t size) final { + int64_t write(const uint8_t *src, size_t size) noexcept final try { DDOCReader::File& file = files.back(); file.data.insert(file.data.end(), src, src + size); return size; + } catch(...) { + return OUTPUT_STREAM_ERROR; } - libcdoc::result_t close() final { return libcdoc::OK; } - bool isError() final { return false; } + + libcdoc::result_t close() noexcept final { return libcdoc::OK; } + bool isError() noexcept final { return false; } libcdoc::result_t open(const std::string& name, int64_t /*size*/) final { files.push_back({name, "application/octet-stream", {}}); return libcdoc::OK; diff --git a/cdoc/Io.cpp b/cdoc/Io.cpp index c7368c84..2860f741 100644 --- a/cdoc/Io.cpp +++ b/cdoc/Io.cpp @@ -18,6 +18,8 @@ #include "Io.h" +#include + namespace libcdoc { static constexpr size_t BLOCK_SIZE = 65536; @@ -55,16 +57,15 @@ DataSource::getLastErrorStr(result_t code) const } int64_t -DataConsumer::writeAll(DataSource& src) +DataConsumer::writeAll(DataSource& src) noexcept { - static const size_t BUF_SIZE = 64 * 1024; - uint8_t buf[BUF_SIZE]; + std::array buf{}; size_t total_read = 0; while (!src.isEof()) { - int64_t n_read = src.read(buf, BUF_SIZE); + int64_t n_read = src.read(buf.data(), buf.size()); if (n_read < 0) return n_read; if (n_read > 0) { - int64_t n_written = write(buf, n_read); + int64_t n_written = write(buf.data(), n_read); if (n_written < 0) return n_written; total_read += n_written; } @@ -102,22 +103,24 @@ FileListSource::FileListSource(const std::string& base, const std::vector= _files.size())) return WORKFLOW_ERROR; _ifs.read((char *) dst, size); return (_ifs.bad()) ? INPUT_STREAM_ERROR : _ifs.gcount(); +} catch(...) { + return INPUT_STREAM_ERROR; } bool -FileListSource::isError() +FileListSource::isError() noexcept { if ((_current < 0) || (_current >= _files.size())) return OK; return _ifs.bad(); } bool -FileListSource::isEof() +FileListSource::isEof() noexcept { if (_current < 0) return false; if (_current >= _files.size()) return true; diff --git a/cdoc/Io.h b/cdoc/Io.h index c7d3d81a..cdf9fd5c 100644 --- a/cdoc/Io.h +++ b/cdoc/Io.h @@ -48,17 +48,17 @@ struct CDOC_EXPORT DataConsumer { * @param size the number of bytes to write * @return size or error code */ - virtual result_t write(const uint8_t *src, size_t size) = 0; + virtual result_t write(const uint8_t *src, size_t size) noexcept = 0; /** * @brief informs DataConsumer that the writing is finished * @return error code or OK */ - virtual result_t close() = 0; + virtual result_t close() noexcept = 0; /** * @brief checks whether DataSource is in error state * @return true if error state */ - virtual bool isError() = 0; + virtual bool isError() noexcept = 0; /** * @brief get textual description of the last error * @@ -74,7 +74,7 @@ struct CDOC_EXPORT DataConsumer { * @param src a vector * @return vector size or error code */ - result_t write(const std::vector& src) { + result_t write(const std::vector& src) noexcept { return write(src.data(), src.size()); } /** @@ -82,7 +82,7 @@ struct CDOC_EXPORT DataConsumer { * @param src a string * @return string length or error code */ - result_t write(const std::string& src) { + result_t write(const std::string& src) noexcept { return write((const uint8_t *) src.data(), src.size()); } /** @@ -93,7 +93,7 @@ struct CDOC_EXPORT DataConsumer { * @param src the input DataSource * @return the number of bytes copied or error */ - result_t writeAll(DataSource& src); + result_t writeAll(DataSource& src) noexcept; DataConsumer (const DataConsumer&) = delete; DataConsumer& operator= (const DataConsumer&) = delete; @@ -128,17 +128,17 @@ struct CDOC_EXPORT DataSource { * @param size the number of bytes to read * @return the number of bytes read or error code */ - virtual result_t read(uint8_t *dst, size_t size) { return NOT_IMPLEMENTED; } + virtual result_t read(uint8_t *dst, size_t size) noexcept { return NOT_IMPLEMENTED; } /** * @brief check whether DataConsumer is in error state * @return true if error state */ - virtual bool isError() { return true; } + virtual bool isError() noexcept { return true; } /** * @brief check whether DataConsumer is reached to the end of data * @return true if end of stream */ - virtual bool isEof() { return true; } + virtual bool isEof() noexcept { return true; } /** * @brief get textual description of the last error * @@ -169,7 +169,7 @@ struct CDOC_EXPORT DataSource { * @param dst the destination DataConsumer * @return error code or OK */ - result_t readAll(DataConsumer& dst) { + result_t readAll(DataConsumer& dst) noexcept { return dst.writeAll(*this); } @@ -214,14 +214,14 @@ struct CDOC_EXPORT ChainedConsumer : public DataConsumer { ~ChainedConsumer() { if (_owned) delete _dst; } - result_t write(const uint8_t *src, size_t size) override { + result_t write(const uint8_t *src, size_t size) noexcept override { return _dst->write(src, size); } - result_t close() override { + result_t close() noexcept override { if (_owned) return _dst->close(); return OK; } - bool isError() override { + bool isError() noexcept override { return _dst->isError(); } protected: @@ -234,13 +234,13 @@ struct CDOC_EXPORT ChainedSource : public DataSource { ~ChainedSource() { if (_owned) delete _src; } - result_t read(uint8_t *dst, size_t size) { + result_t read(uint8_t *dst, size_t size) noexcept override { return _src->read(dst, size); } - bool isError() { + bool isError() noexcept override { return _src->isError(); } - bool isEof() { + bool isEof() noexcept override { return _src->isEof(); } protected: @@ -264,13 +264,15 @@ struct CDOC_EXPORT IStreamSource : public DataSource { return bool(_ifs->bad()) ? INPUT_STREAM_ERROR : OK; } - result_t read(uint8_t *dst, size_t size) { + result_t read(uint8_t *dst, size_t size) noexcept override try { _ifs->read((char *) dst, size); return (_ifs->bad()) ? INPUT_STREAM_ERROR : _ifs->gcount(); + } catch(...) { + return INPUT_STREAM_ERROR; } - bool isError() { return _ifs->bad(); } - bool isEof() { return _ifs->eof(); } + bool isError() noexcept override { return _ifs->bad(); } + bool isEof() noexcept override { return _ifs->eof(); } protected: std::istream *_ifs; bool _owned; @@ -285,17 +287,17 @@ struct CDOC_EXPORT OStreamConsumer : public DataConsumer { if (_owned) delete _ofs; } - result_t write(const uint8_t *src, size_t size) { + result_t write(const uint8_t *src, size_t size) noexcept override { _ofs->write((const char *) src, size); return (_ofs->bad()) ? OUTPUT_STREAM_ERROR : size; } - result_t close() { + result_t close() noexcept override { _ofs->flush(); return (_ofs->bad()) ? OUTPUT_STREAM_ERROR : OK; } - bool isError() { return _ofs->bad(); } + bool isError() noexcept override { return _ofs->bad(); } protected: std::ostream *_ofs; bool _owned; @@ -310,15 +312,15 @@ struct CDOC_EXPORT VectorSource : public DataSource { return OK; } - result_t read(uint8_t *dst, size_t size) override { + result_t read(uint8_t *dst, size_t size) noexcept override { size = std::min(size, _data.size() - _ptr); std::copy_n(_data.cbegin() + _ptr, size, dst); _ptr += size; return size; } - bool isError() override { return false; } - bool isEof() override { return _ptr >= _data.size(); } + bool isError() noexcept override { return false; } + bool isEof() noexcept override { return _ptr >= _data.size(); } protected: const std::vector& _data; size_t _ptr; @@ -326,12 +328,14 @@ struct CDOC_EXPORT VectorSource : public DataSource { struct CDOC_EXPORT VectorConsumer : public DataConsumer { VectorConsumer(std::vector& data) : _data(data) {} - result_t write(const uint8_t *src, size_t size) override final { + result_t write(const uint8_t *src, size_t size) noexcept final try { _data.insert(_data.end(), src, src + size); return size; + } catch(...) { + return OUTPUT_STREAM_ERROR; } - result_t close() override final { return OK; } - virtual bool isError() override final { return false; } + result_t close() noexcept final { return OK; } + virtual bool isError() noexcept final { return false; } protected: std::vector& _data; }; @@ -340,15 +344,17 @@ struct CDOC_EXPORT FileListConsumer : public MultiDataConsumer { FileListConsumer(const std::string& base_path) { base = base_path; } - result_t write(const uint8_t *src, size_t size) override final { + result_t write(const uint8_t *src, size_t size) noexcept final try { ofs.write((const char *) src, size); return (ofs.bad()) ? OUTPUT_STREAM_ERROR : size; + } catch(...) { + return OUTPUT_STREAM_ERROR; } - result_t close() override final { + result_t close() noexcept final { ofs.close(); return (ofs.bad()) ? OUTPUT_STREAM_ERROR : OK; } - bool isError() override final { + bool isError() noexcept final { return ofs.bad(); } result_t open(const std::string& name, int64_t size) override final { @@ -378,11 +384,11 @@ struct CDOC_EXPORT FileListConsumer : public MultiDataConsumer { struct CDOC_EXPORT FileListSource : public MultiDataSource { FileListSource(const std::string& base, const std::vector& files); - result_t read(uint8_t *dst, size_t size) override final; - bool isError() override final; - bool isEof() override final; - result_t getNumComponents() override final; - result_t next(std::string& name, int64_t& size) override final; + result_t read(uint8_t *dst, size_t size) noexcept final; + bool isError() noexcept final; + bool isEof() noexcept final; + result_t getNumComponents() final; + result_t next(std::string& name, int64_t& size) final; protected: std::filesystem::path _base; const std::vector& _files; diff --git a/cdoc/Tar.cpp b/cdoc/Tar.cpp index 572bf091..e1f79417 100644 --- a/cdoc/Tar.cpp +++ b/cdoc/Tar.cpp @@ -128,20 +128,20 @@ libcdoc::TarConsumer::~TarConsumer() } libcdoc::result_t -libcdoc::TarConsumer::write(const uint8_t *src, size_t size) +libcdoc::TarConsumer::write(const uint8_t *src, size_t size) noexcept { return _dst->write(src, size); } libcdoc::result_t -libcdoc::TarConsumer::writeHeader(const Header &h) { +libcdoc::TarConsumer::writeHeader(const Header &h) noexcept { if(auto rv = _dst->write((const uint8_t *)&h, BLOCKSIZE); rv != BLOCKSIZE) return rv < OK ? rv : OUTPUT_ERROR; return OK; } libcdoc::result_t -libcdoc::TarConsumer::writeHeader(Header &h, int64_t size) { +libcdoc::TarConsumer::writeHeader(Header &h, int64_t size) noexcept { h.chksum.fill(' '); toOctal(h.size, size); toOctal(h.chksum, h.checksum().first); @@ -149,7 +149,7 @@ libcdoc::TarConsumer::writeHeader(Header &h, int64_t size) { } libcdoc::result_t -libcdoc::TarConsumer::writePadding(int64_t size) { +libcdoc::TarConsumer::writePadding(int64_t size) noexcept { static const std::array pad {}; auto padSize = padding(size); if(auto rv = _dst->write(pad.data(), padSize); rv != padSize) @@ -158,7 +158,7 @@ libcdoc::TarConsumer::writePadding(int64_t size) { } libcdoc::result_t -libcdoc::TarConsumer::close() +libcdoc::TarConsumer::close() noexcept { if (_current_size > 0) { if(auto rv = writePadding(_current_size); rv != OK) @@ -176,7 +176,7 @@ libcdoc::TarConsumer::close() } bool -libcdoc::TarConsumer::isError() +libcdoc::TarConsumer::isError() noexcept { return _dst->isError(); } @@ -227,7 +227,7 @@ libcdoc::TarSource::~TarSource() } libcdoc::result_t -libcdoc::TarSource::read(uint8_t *dst, size_t size) +libcdoc::TarSource::read(uint8_t *dst, size_t size) noexcept { if (_error != OK) return _error; if (_pos >= _data_size) { @@ -246,13 +246,13 @@ libcdoc::TarSource::read(uint8_t *dst, size_t size) } bool -libcdoc::TarSource::isError() +libcdoc::TarSource::isError() noexcept { return _error != OK; } bool -libcdoc::TarSource::isEof() +libcdoc::TarSource::isEof() noexcept { return _eof; } diff --git a/cdoc/Tar.h b/cdoc/Tar.h index 9f89186c..0ec7c832 100644 --- a/cdoc/Tar.h +++ b/cdoc/Tar.h @@ -31,14 +31,14 @@ struct TarConsumer final : public MultiDataConsumer TarConsumer(DataConsumer *dst, bool take_ownership); ~TarConsumer(); - libcdoc::result_t write(const uint8_t *src, size_t size) final; - libcdoc::result_t close() final; - bool isError() final; + libcdoc::result_t write(const uint8_t *src, size_t size) noexcept final; + libcdoc::result_t close() noexcept final; + bool isError() noexcept final; libcdoc::result_t open(const std::string& name, int64_t size) final; private: - result_t writeHeader(const Header &h); - result_t writeHeader(Header &h, int64_t size); - result_t writePadding(int64_t size); + result_t writeHeader(const Header &h) noexcept; + result_t writeHeader(Header &h, int64_t size) noexcept; + result_t writePadding(int64_t size) noexcept; DataConsumer *_dst; bool _owned; @@ -51,9 +51,9 @@ struct TarSource : public MultiDataSource public: TarSource(DataSource *src, bool take_ownership); ~TarSource(); - libcdoc::result_t read(uint8_t *dst, size_t size) override final; - bool isError() override final; - bool isEof() override final; + libcdoc::result_t read(uint8_t *dst, size_t size) noexcept final; + bool isError() noexcept final; + bool isEof() noexcept final; libcdoc::result_t getNumComponents() override final { return NOT_IMPLEMENTED; }; libcdoc::result_t next(std::string& name, int64_t& size) override final; private: diff --git a/cdoc/XmlWriter.cpp b/cdoc/XmlWriter.cpp index 0ef87193..13142a6b 100644 --- a/cdoc/XmlWriter.cpp +++ b/cdoc/XmlWriter.cpp @@ -100,7 +100,7 @@ int64_t XMLWriter::writeBase64Element(NS ns, const std::string &name, const std: std::array buf {}; // buffer up to 2 leftover bytes size_t bufSize = 0; Base64Consumer(xmlTextWriterPtr _w) : w(_w) {} - result_t write(const uint8_t *src, size_t size) final { + result_t write(const uint8_t *src, size_t size) noexcept final { if(!src || size == 0) return OK; @@ -132,7 +132,7 @@ int64_t XMLWriter::writeBase64Element(NS ns, const std::string &name, const std: return result_t(size); } - result_t close() final { + result_t close() noexcept final { if (bufSize > 0) { // write remaining 1..2 bytes so base64 padding is applied only at the end if(xmlTextWriterWriteBase64(w, reinterpret_cast(buf.data()), 0, bufSize) == -1) @@ -141,7 +141,7 @@ int64_t XMLWriter::writeBase64Element(NS ns, const std::string &name, const std: bufSize = 0; return OK; } - bool isError() final { return false; } + bool isError() noexcept final { return false; } } base64Consumer {w.get()}; if(auto rv = f(base64Consumer); rv < 0) return rv; diff --git a/cdoc/ZStream.h b/cdoc/ZStream.h index 163a5752..7648904b 100644 --- a/cdoc/ZStream.h +++ b/cdoc/ZStream.h @@ -31,8 +31,7 @@ namespace libcdoc { struct ZConsumer : public ChainedConsumer { static constexpr uint64_t CHUNK = 16LL * 1024LL; z_stream _s {}; - bool _fail = false; - std::vector buf; + bool _fail = false; int flush = Z_NO_FLUSH; ZConsumer(DataConsumer *dst, bool take_ownership = false) : ChainedConsumer(dst, take_ownership) { if (deflateInit(&_s, Z_DEFAULT_COMPRESSION) != Z_OK) _fail = true; @@ -41,7 +40,7 @@ struct ZConsumer : public ChainedConsumer { if (!_fail) deflateEnd(&_s); } - libcdoc::result_t write(const uint8_t *src, size_t size) override final { + libcdoc::result_t write(const uint8_t *src, size_t size) noexcept final { if (_fail) return OUTPUT_ERROR; _s.next_in = (z_const Bytef *) src; _s.avail_in = uInt(size); @@ -64,11 +63,11 @@ struct ZConsumer : public ChainedConsumer { return size; } - virtual bool isError() override final { + virtual bool isError() noexcept final { return _fail || ChainedConsumer::isError(); }; - libcdoc::result_t close() override final { + libcdoc::result_t close() noexcept final { flush = Z_FINISH; write (nullptr, 0); deflateEnd(&_s); @@ -91,17 +90,16 @@ struct ZSource : public ChainedSource { if (!_error) inflateEnd(&_s); } - libcdoc::result_t read(uint8_t *dst, size_t size) override final { + libcdoc::result_t read(uint8_t *dst, size_t size) noexcept final try { if (_error) return _error; _s.next_out = (Bytef *) dst; _s.avail_out = uInt (size); - uint8_t in[CHUNK]; + std::array in{}; int res = Z_OK; while((_s.avail_out > 0) && (res == Z_OK)) { - size_t readlen = CHUNK; - int64_t n_read = _src->read(in, readlen); + int64_t n_read = _src->read(in.data(), in.size()); if (n_read > 0) { - buf.insert(buf.end(), in, in + n_read); + buf.insert(buf.end(), in.begin(), in.begin() + n_read); } else if (n_read != 0) { _error = n_read; return _error; @@ -122,13 +120,15 @@ struct ZSource : public ChainedSource { } } return size - _s.avail_out; - } + } catch(...) { + return INPUT_STREAM_ERROR; + } - virtual bool isError() override final { + virtual bool isError() noexcept final { return (_error != OK) || ChainedSource::isError(); }; - virtual bool isEof() override final { + virtual bool isEof() noexcept final { return (_s.avail_in == 0) && ChainedSource::isEof(); }; }; diff --git a/test/libcdoc_boost.cpp b/test/libcdoc_boost.cpp index f204edfc..39035652 100644 --- a/test/libcdoc_boost.cpp +++ b/test/libcdoc_boost.cpp @@ -19,7 +19,6 @@ #define BOOST_TEST_MODULE "C++ Unit Tests for libcdoc" #include -#include #include #include #include diff --git a/test/pipe.h b/test/pipe.h index 5f1d4e56..1a6b2b2d 100644 --- a/test/pipe.h +++ b/test/pipe.h @@ -23,7 +23,7 @@ struct PipeSource : public libcdoc::DataSource { PipeSource(std::vector& data, bool& eof) : _data(data), _eof(eof) {} - libcdoc::result_t read(uint8_t *dst, size_t size) override { + libcdoc::result_t read(uint8_t *dst, size_t size) noexcept override { size = std::min(size, _data.size()); std::copy(_data.cbegin(), _data.cbegin() + size, dst); if (_buf.size() < 1024) { @@ -44,8 +44,8 @@ } return libcdoc::NOT_IMPLEMENTED; } - bool isError() override { return false; } - bool isEof() override { return _eof; } + bool isError() noexcept override { return false; } + bool isEof() noexcept override { return _eof; } protected: std::vector& _data; bool& _eof; @@ -54,12 +54,12 @@ struct PipeConsumer : public libcdoc::DataConsumer { PipeConsumer(std::vector& data, bool& eof) : _data(data), _eof(eof) { _eof = false; } - libcdoc::result_t write(const uint8_t *src, size_t size) override final { + libcdoc::result_t write(const uint8_t *src, size_t size) noexcept final { _data.insert(_data.end(), src, src + size); return size; } - libcdoc::result_t close() override final { _eof = true; return libcdoc::OK; } - virtual bool isError() override final { return false; } + libcdoc::result_t close() noexcept final { _eof = true; return libcdoc::OK; } + virtual bool isError() noexcept final { return false; } protected: std::vector& _data; bool& _eof;