refactor(filesystem_writer): avoid use of tellp() on output stream

This commit is contained in:
Marcus Holland-Moritz 2023-12-25 22:01:49 +01:00
parent e461e167fc
commit df09b171c2

View File

@ -49,6 +49,20 @@ namespace dwarfs {
namespace { namespace {
size_t copy_stream(std::istream& is, std::ostream& os) {
std::streambuf* rdbuf = is.rdbuf();
std::streamsize count{0};
std::streamsize transferred;
char buffer[1024];
while ((transferred = rdbuf->sgetn(buffer, sizeof(buffer))) > 0) {
os.write(buffer, transferred);
count += transferred;
}
return count;
}
class compression_progress : public progress::context { class compression_progress : public progress::context {
public: public:
using status = progress::context::status; using status = progress::context::status;
@ -534,7 +548,7 @@ class filesystem_writer_ final : public filesystem_writer::impl {
void write_compressed_section(fs_section sec, void write_compressed_section(fs_section sec,
std::span<uint8_t const> data) override; std::span<uint8_t const> data) override;
void flush() override; void flush() override;
size_t size() const override { return os_.tellp(); } size_t size() const override { return image_size_; }
private: private:
using block_merger_type = using block_merger_type =
@ -563,6 +577,7 @@ class filesystem_writer_ final : public filesystem_writer::impl {
size_t mem_used() const; size_t mem_used() const;
std::ostream& os_; std::ostream& os_;
size_t image_size_{0};
std::istream* header_; std::istream* header_;
worker_group& wg_; worker_group& wg_;
progress& prog_; progress& prog_;
@ -607,8 +622,7 @@ filesystem_writer_<LoggerPolicy>::filesystem_writer_(
if (options_.remove_header) { if (options_.remove_header) {
LOG_WARN << "header will not be written because remove_header is set"; LOG_WARN << "header will not be written because remove_header is set";
} else { } else {
os_ << header_->rdbuf(); image_size_ = header_size_ = copy_stream(*header_, os_);
header_size_ = os_.tellp();
} }
} }
@ -703,6 +717,7 @@ template <typename LoggerPolicy>
void filesystem_writer_<LoggerPolicy>::write(const char* data, size_t size) { void filesystem_writer_<LoggerPolicy>::write(const char* data, size_t size) {
// TODO: error handling :-) // TODO: error handling :-)
os_.write(data, size); os_.write(data, size);
image_size_ += size;
prog_.compressed_size += size; prog_.compressed_size += size;
} }
@ -987,7 +1002,7 @@ void filesystem_writer_<LoggerPolicy>::copy_header(
LOG_WARN << "replacing old header"; LOG_WARN << "replacing old header";
} else { } else {
write(header); write(header);
header_size_ = os_.tellp(); header_size_ = size();
} }
} }
} }
@ -1051,7 +1066,7 @@ void filesystem_writer_<LoggerPolicy>::flush() {
template <typename LoggerPolicy> template <typename LoggerPolicy>
void filesystem_writer_<LoggerPolicy>::push_section_index(section_type type) { void filesystem_writer_<LoggerPolicy>::push_section_index(section_type type) {
section_index_.push_back((static_cast<uint64_t>(type) << 48) | section_index_.push_back((static_cast<uint64_t>(type) << 48) |
static_cast<uint64_t>(os_.tellp() - header_size_)); static_cast<uint64_t>(size() - header_size_));
} }
template <typename LoggerPolicy> template <typename LoggerPolicy>