*: Implement detailed progress reporting when creating
Ditto!
This commit is contained in:
parent
e82d693dfc
commit
cf9d84cb24
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// EuropaTools
|
||||
//
|
||||
// (C) 2021-2022 modeco80 <lily.modeco80@protonmail.ch>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
//
|
||||
|
||||
#ifndef EUROPA_IO_PAKPROGRESSREPORTSINK_H
|
||||
#define EUROPA_IO_PAKPROGRESSREPORTSINK_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace europa::io {
|
||||
|
||||
/**
|
||||
* Interface for the writer to output detailed progress information.
|
||||
*/
|
||||
struct PakProgressReportSink {
|
||||
|
||||
struct PakEvent {
|
||||
enum class Type {
|
||||
FillInHeader, ///< Filling in header
|
||||
WritingHeader, ///< Writing header
|
||||
|
||||
WritingToc ///< Writing archive TOC
|
||||
};
|
||||
|
||||
Type type;
|
||||
};
|
||||
|
||||
struct FileEvent {
|
||||
enum class Type {
|
||||
FileBeginWrite, ///< File has began write to package
|
||||
FileEndWrite, ///< File writing finished
|
||||
};
|
||||
|
||||
Type type;
|
||||
std::string filename;
|
||||
};
|
||||
|
||||
virtual ~PakProgressReportSink() = default;
|
||||
|
||||
virtual void OnEvent(const PakEvent& event) = 0;
|
||||
virtual void OnEvent(const FileEvent& event) = 0;
|
||||
};
|
||||
|
||||
|
||||
} // namespace europa::io
|
||||
|
||||
#endif // EUROPA_IO_PAKPROGRESSREPORTSINK_H
|
|
@ -10,6 +10,7 @@
|
|||
#define EUROPA_IO_PAKWRITER_H
|
||||
|
||||
#include <europa/io/PakFile.hpp>
|
||||
#include <europa/io/PakProgressReportSink.hpp>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
@ -30,7 +31,7 @@ namespace europa::io {
|
|||
/**
|
||||
* Write the resulting archive to the given output stream.
|
||||
*/
|
||||
void Write(std::ostream& os);
|
||||
void Write(std::ostream& os, PakProgressReportSink& sink);
|
||||
|
||||
private:
|
||||
structs::PakHeader pakHeader {};
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace europa::io {
|
|||
// - Composable operations (WriteTOC, WriteFile, WriteHeader)
|
||||
// - Add IProgressReportSink reporting
|
||||
|
||||
void PakWriter::Write(std::ostream& os) {
|
||||
void PakWriter::Write(std::ostream& os, PakProgressReportSink& sink) {
|
||||
|
||||
// This essentially converts our map we use for faster insertion
|
||||
// into a flat array we can sort easily.
|
||||
|
@ -93,15 +93,32 @@ namespace europa::io {
|
|||
for(auto& [filename, file] : sortedFiles) {
|
||||
//std::cout << "PakWriteFile \"" << filename << "\"\n Size " << file.GetTOCEntry().size << "\n";
|
||||
|
||||
|
||||
sink.OnEvent({
|
||||
PakProgressReportSink::FileEvent::Type::FileBeginWrite,
|
||||
filename
|
||||
});
|
||||
|
||||
file.GetTOCEntry().offset = os.tellp();
|
||||
os.write(reinterpret_cast<const char*>(file.GetData().data()), file.GetData().size());
|
||||
|
||||
// Flush on file writing
|
||||
os.flush();
|
||||
|
||||
|
||||
sink.OnEvent({
|
||||
PakProgressReportSink::FileEvent::Type::FileEndWrite,
|
||||
filename
|
||||
});
|
||||
}
|
||||
|
||||
pakHeader.tocOffset = os.tellp();
|
||||
|
||||
|
||||
sink.OnEvent({
|
||||
PakProgressReportSink::PakEvent::Type::WritingToc
|
||||
});
|
||||
|
||||
// Write the TOC
|
||||
for(auto& [filename, file] : sortedFiles) {
|
||||
file.FillTOCEntry();
|
||||
|
@ -115,10 +132,21 @@ namespace europa::io {
|
|||
impl::WriteStreamType(os, file.GetTOCEntry());
|
||||
}
|
||||
|
||||
|
||||
sink.OnEvent({
|
||||
PakProgressReportSink::PakEvent::Type::FillInHeader
|
||||
});
|
||||
|
||||
|
||||
// Fill out the rest of the header.
|
||||
pakHeader.fileCount = archiveFiles.size();
|
||||
pakHeader.tocSize = static_cast<std::uint32_t>(os.tellp()) - (pakHeader.tocOffset - 1);
|
||||
|
||||
|
||||
sink.OnEvent({
|
||||
PakProgressReportSink::PakEvent::Type::WritingHeader
|
||||
});
|
||||
|
||||
// As the last step, write it.
|
||||
os.seekp(0, std::ostream::beg);
|
||||
impl::WriteStreamType(os, pakHeader);
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace eupak {
|
|||
|
||||
div *= unit;
|
||||
|
||||
exp++; // TODO: break if too big
|
||||
exp++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,65 @@
|
|||
|
||||
namespace eupak::tasks {
|
||||
|
||||
struct CreateArchiveReportSink : public europa::io::PakProgressReportSink {
|
||||
|
||||
CreateArchiveReportSink(int fileCount = 0)
|
||||
: europa::io::PakProgressReportSink() {
|
||||
indicators::show_console_cursor(false);
|
||||
progress.set_option(indicators::option::MaxProgress { fileCount });
|
||||
}
|
||||
|
||||
~CreateArchiveReportSink() {
|
||||
indicators::show_console_cursor(true);
|
||||
}
|
||||
|
||||
void OnEvent(const PakEvent& event) override {
|
||||
using enum PakEvent::Type;
|
||||
switch(event.type) {
|
||||
case WritingHeader:
|
||||
progress.set_option(indicators::option::PostfixText {"Writing header"});
|
||||
progress.print_progress();
|
||||
break;
|
||||
|
||||
case FillInHeader:
|
||||
progress.set_option(indicators::option::PostfixText {"Filling in header"});
|
||||
progress.print_progress();
|
||||
break;
|
||||
|
||||
case WritingToc:
|
||||
progress.set_option(indicators::option::PostfixText {"Writing TOC"});
|
||||
progress.print_progress();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnEvent(const FileEvent& event) override {
|
||||
using enum FileEvent::Type;
|
||||
switch(event.type) {
|
||||
case FileBeginWrite:
|
||||
progress.set_option(indicators::option::PostfixText {"Writing " + event.filename});
|
||||
progress.print_progress();
|
||||
break;
|
||||
|
||||
case FileEndWrite:
|
||||
progress.set_option(indicators::option::PostfixText {"Written " + event.filename});
|
||||
progress.tick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
indicators::ProgressBar progress {
|
||||
indicators::option::BarWidth { 50 },
|
||||
indicators::option::ForegroundColor { indicators::Color::yellow },
|
||||
indicators::option::ShowPercentage { true },
|
||||
indicators::option::ShowElapsedTime { true },
|
||||
indicators::option::ShowRemainingTime { true },
|
||||
|
||||
indicators::option::PrefixText { "Writing archive " }
|
||||
};
|
||||
};
|
||||
|
||||
int CreateTask::Run(Arguments&& args) {
|
||||
europa::io::PakWriter writer;
|
||||
|
||||
|
@ -41,7 +100,7 @@ namespace eupak::tasks {
|
|||
indicators::option::ShowElapsedTime { true },
|
||||
indicators::option::ShowRemainingTime { true },
|
||||
|
||||
indicators::option::PrefixText { "Creating archive " }
|
||||
indicators::option::PrefixText { "Adding files to archive " }
|
||||
};
|
||||
|
||||
indicators::show_console_cursor(false);
|
||||
|
@ -91,6 +150,8 @@ namespace eupak::tasks {
|
|||
currFile++;
|
||||
}
|
||||
|
||||
indicators::show_console_cursor(true);
|
||||
|
||||
std::ofstream ofs(args.outputFile.string(), std::ofstream::binary);
|
||||
|
||||
if(!ofs) {
|
||||
|
@ -98,8 +159,10 @@ namespace eupak::tasks {
|
|||
return 1;
|
||||
}
|
||||
|
||||
writer.Write(ofs);
|
||||
indicators::show_console_cursor(true);
|
||||
|
||||
CreateArchiveReportSink sink(fileCount);
|
||||
|
||||
writer.Write(ofs, sink);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue