diff options
author | Lucas CHOLLET <lucas.chollet@free.fr> | 2023-01-14 12:11:29 -0500 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2023-01-16 17:28:32 +0330 |
commit | 4952cdfe2ba2de4831a64f8b0a920870e9d1bc39 (patch) | |
tree | 7468d4bcbc4db333e77a151fdc47f4c30990f4d7 /Userland | |
parent | fc413711eeb17558dff5138a67360f24ef87e34e (diff) | |
download | serenity-4952cdfe2ba2de4831a64f8b0a920870e9d1bc39.zip |
Spreadsheet: Move to a non-owning model for `Stream` in `Writer::XSV`
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Applications/Spreadsheet/ExportDialog.cpp | 22 | ||||
-rw-r--r-- | Userland/Applications/Spreadsheet/ExportDialog.h | 10 | ||||
-rw-r--r-- | Userland/Applications/Spreadsheet/Writers/CSV.h | 14 | ||||
-rw-r--r-- | Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp | 10 | ||||
-rw-r--r-- | Userland/Applications/Spreadsheet/Writers/XSV.h | 78 |
5 files changed, 75 insertions, 59 deletions
diff --git a/Userland/Applications/Spreadsheet/ExportDialog.cpp b/Userland/Applications/Spreadsheet/ExportDialog.cpp index d706c80e3c..d185b1259a 100644 --- a/Userland/Applications/Spreadsheet/ExportDialog.cpp +++ b/Userland/Applications/Spreadsheet/ExportDialog.cpp @@ -88,7 +88,7 @@ CSVExportDialogPage::CSVExportDialogPage(Sheet const& sheet) update_preview(); } -auto CSVExportDialogPage::make_writer(Core::Stream::Handle<Core::Stream::Stream> stream) -> ErrorOr<NonnullOwnPtr<XSV>> +auto CSVExportDialogPage::generate(Core::Stream::Stream& stream, GenerationType type) -> ErrorOr<void> { auto delimiter = TRY([this]() -> ErrorOr<DeprecatedString> { if (m_delimiter_other_radio->is_checked()) { @@ -150,15 +150,25 @@ auto CSVExportDialogPage::make_writer(Core::Stream::Handle<Core::Stream::Stream> if (should_quote_all_fields) behaviors = behaviors | Writer::WriterBehavior::QuoteAll; - return try_make<XSV>(move(stream), m_data, move(traits), *headers, behaviors); + switch (type) { + case GenerationType::Normal: + TRY((Writer::XSV<decltype(m_data), Vector<DeprecatedString>>::generate(stream, m_data, move(traits), *headers, behaviors))); + break; + case GenerationType::Preview: + TRY((Writer::XSV<decltype(m_data), decltype(*headers)>::generate_preview(stream, m_data, move(traits), *headers, behaviors))); + break; + default: + VERIFY_NOT_REACHED(); + } + + return {}; } void CSVExportDialogPage::update_preview() { auto maybe_error = [this]() -> ErrorOr<void> { Core::Stream::AllocatingMemoryStream memory_stream; - auto writer = TRY(make_writer(Core::Stream::Handle<Core::Stream::Stream>(memory_stream))); - TRY(writer->generate_preview()); + TRY(generate(memory_stream, GenerationType::Preview)); auto buffer = TRY(memory_stream.read_until_eof()); m_data_preview_text_editor->set_text(StringView(buffer)); m_data_preview_text_editor->update(); @@ -185,8 +195,8 @@ ErrorOr<void> ExportDialog::make_and_run_for(StringView mime, NonnullOwnPtr<Core if (wizard->exec() != GUI::Dialog::ExecResult::OK) return Error::from_string_literal("CSV Export was cancelled"); - auto writer = TRY(page.make_writer(move(file))); - return writer->generate(); + TRY(page.generate(*file, CSVExportDialogPage::GenerationType::Normal)); + return {}; }; auto export_worksheet = [&]() -> ErrorOr<void> { diff --git a/Userland/Applications/Spreadsheet/ExportDialog.h b/Userland/Applications/Spreadsheet/ExportDialog.h index da73500443..2f07f87653 100644 --- a/Userland/Applications/Spreadsheet/ExportDialog.h +++ b/Userland/Applications/Spreadsheet/ExportDialog.h @@ -18,12 +18,16 @@ class Sheet; class Workbook; struct CSVExportDialogPage { - using XSV = Writer::XSV<Vector<Vector<DeprecatedString>>, Vector<DeprecatedString>>; - explicit CSVExportDialogPage(Sheet const&); NonnullRefPtr<GUI::WizardPage> page() { return *m_page; } - ErrorOr<NonnullOwnPtr<XSV>> make_writer(Core::Stream::Handle<Core::Stream::Stream>); + + enum class GenerationType { + Normal, + Preview + }; + + ErrorOr<void> generate(Core::Stream::Stream&, GenerationType); protected: void update_preview(); diff --git a/Userland/Applications/Spreadsheet/Writers/CSV.h b/Userland/Applications/Spreadsheet/Writers/CSV.h index 6a6e2fe801..fb0cbd4ca7 100644 --- a/Userland/Applications/Spreadsheet/Writers/CSV.h +++ b/Userland/Applications/Spreadsheet/Writers/CSV.h @@ -12,12 +12,18 @@ namespace Writer { -template<typename ContainerType> -class CSV : public XSV<ContainerType> { +class CSV { public: - CSV(Core::Stream::Handle<Core::Stream::Stream> output, ContainerType const& data, Vector<StringView> headers = {}, WriterBehavior behaviors = default_behaviors()) - : XSV<ContainerType>(move(output), data, { ",", "\"", WriterTraits::Repeat }, move(headers), behaviors) + template<typename ContainerType> + static ErrorOr<void> generate(Core::Stream::Stream& output, ContainerType const& data, Vector<StringView> headers = {}, WriterBehavior behaviors = default_behaviors()) { + return XSV<ContainerType>::generate(output, data, { ",", "\"", WriterTraits::Repeat }, move(headers), behaviors); + } + + template<typename ContainerType> + static ErrorOr<void> generate_preview(Core::Stream::Stream& output, ContainerType const& data, Vector<StringView> headers = {}, WriterBehavior behaviors = default_behaviors()) + { + return XSV<ContainerType>::generate_preview(output, data, { ",", "\"", WriterTraits::Repeat }, move(headers), behaviors); } }; diff --git a/Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp b/Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp index 978eb20801..f47c98ee8a 100644 --- a/Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp +++ b/Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp @@ -7,7 +7,6 @@ #include <LibTest/TestCase.h> #include "../CSV.h" -#include "../XSV.h" #include <LibCore/MemoryStream.h> TEST_CASE(can_write) @@ -19,8 +18,7 @@ TEST_CASE(can_write) }; Core::Stream::AllocatingMemoryStream stream; - auto csv = Writer::CSV(Core::Stream::Handle<Core::Stream::Stream>(stream), data); - MUST(csv.generate()); + MUST(Writer::CSV::generate(stream, data)); auto expected_output = R"~(1,2,3 4,5,6 @@ -40,8 +38,7 @@ TEST_CASE(can_write_with_header) }; Core::Stream::AllocatingMemoryStream stream; - auto csv = Writer::CSV(Core::Stream::Handle<Core::Stream::Stream>(stream), data, { "A"sv, "B\""sv, "C"sv }); - MUST(csv.generate()); + MUST(Writer::CSV::generate(stream, data, { "A"sv, "B\""sv, "C"sv })); auto expected_output = R"~(A,"B""",C 1,2,3 @@ -61,8 +58,7 @@ TEST_CASE(can_write_with_different_behaviors) }; Core::Stream::AllocatingMemoryStream stream; - auto csv = Writer::CSV(Core::Stream::Handle<Core::Stream::Stream>(stream), data, { "A"sv, "B\""sv, "C"sv }, Writer::WriterBehavior::QuoteOnlyInFieldStart | Writer::WriterBehavior::WriteHeaders); - MUST(csv.generate()); + MUST(Writer::CSV::generate(stream, data, { "A"sv, "B\""sv, "C"sv }, Writer::WriterBehavior::QuoteOnlyInFieldStart | Writer::WriterBehavior::WriteHeaders)); auto expected_output = R"~(A,B",C Well,Hello",Friends diff --git a/Userland/Applications/Spreadsheet/Writers/XSV.h b/Userland/Applications/Spreadsheet/Writers/XSV.h index 4fac47920b..f81a17d4ed 100644 --- a/Userland/Applications/Spreadsheet/Writers/XSV.h +++ b/Userland/Applications/Spreadsheet/Writers/XSV.h @@ -42,59 +42,48 @@ constexpr WriterBehavior default_behaviors() template<typename ContainerType, typename HeaderType = Vector<StringView>> class XSV { public: - XSV(Core::Stream::Handle<Core::Stream::Stream> output, ContainerType const& data, WriterTraits traits, HeaderType headers = {}, WriterBehavior behaviors = default_behaviors()) - : m_data(data) - , m_traits(move(traits)) - , m_behaviors(behaviors) - , m_names(headers) - , m_output(move(output)) - { - if (!headers.is_empty()) - m_behaviors = m_behaviors | WriterBehavior::WriteHeaders; - } - - virtual ~XSV() = default; - - ErrorOr<void> generate() + static ErrorOr<void> generate(Core::Stream::Stream& output, ContainerType const& data, WriterTraits traits, HeaderType headers = {}, WriterBehavior behaviors = default_behaviors()) { - auto with_headers = has_flag(m_behaviors, WriterBehavior::WriteHeaders); + auto writer = XSV(output, data, traits, headers, behaviors); + auto with_headers = has_flag(writer.m_behaviors, WriterBehavior::WriteHeaders); if (with_headers) { - TRY(write_row(m_names)); - TRY(m_output->write_entire_buffer({ "\n", 1 })); + TRY(writer.write_row(writer.m_names)); + TRY(writer.m_output.write_entire_buffer({ "\n", 1 })); } - for (auto&& row : m_data) { + for (auto&& row : writer.m_data) { if (with_headers) { - if (row.size() != m_names.size()) + if (row.size() != writer.m_names.size()) return Error::from_string_literal("Header count does not match given column count"); } - TRY(write_row(row)); - TRY(m_output->write_entire_buffer({ "\n", 1 })); + TRY(writer.write_row(row)); + TRY(writer.m_output.write_entire_buffer({ "\n", 1 })); } return {}; } - ErrorOr<void> generate_preview() + static ErrorOr<void> generate_preview(Core::Stream::Stream& output, ContainerType const& data, WriterTraits traits, HeaderType headers = {}, WriterBehavior behaviors = default_behaviors()) { + auto writer = XSV(output, data, traits, headers, behaviors); auto lines_written = 0; constexpr auto max_preview_lines = 8; - auto with_headers = has_flag(m_behaviors, WriterBehavior::WriteHeaders); + auto with_headers = has_flag(writer.m_behaviors, WriterBehavior::WriteHeaders); if (with_headers) { - TRY(write_row(m_names)); - TRY(m_output->write_entire_buffer({ "\n", 1 })); + TRY(writer.write_row(writer.m_names)); + TRY(writer.m_output.write_entire_buffer({ "\n", 1 })); ++lines_written; } - for (auto&& row : m_data) { + for (auto&& row : writer.m_data) { if (with_headers) { - if (row.size() != m_names.size()) + if (row.size() != writer.m_names.size()) return Error::from_string_literal("Header count does not match given column count"); } - TRY(write_row(row)); - TRY(m_output->write_entire_buffer({ "\n", 1 })); + TRY(writer.write_row(row)); + TRY(writer.m_output.write_entire_buffer({ "\n", 1 })); ++lines_written; if (lines_written >= max_preview_lines) @@ -104,13 +93,24 @@ public: } private: + XSV(Core::Stream::Stream& output, ContainerType const& data, WriterTraits traits, HeaderType headers = {}, WriterBehavior behaviors = default_behaviors()) + : m_data(data) + , m_traits(move(traits)) + , m_behaviors(behaviors) + , m_names(headers) + , m_output(output) + { + if (!headers.is_empty()) + m_behaviors = m_behaviors | WriterBehavior::WriteHeaders; + } + template<typename T> ErrorOr<void> write_row(T&& row) { bool first = true; for (auto&& entry : row) { if (!first) { - TRY(m_output->write_entire_buffer(m_traits.separator.bytes())); + TRY(m_output.write_entire_buffer(m_traits.separator.bytes())); } first = false; TRY(write_entry(entry)); @@ -136,33 +136,33 @@ private: if (safe_to_write_normally) { if (!string.is_empty()) - TRY(m_output->write_entire_buffer(string.bytes())); + TRY(m_output.write_entire_buffer(string.bytes())); return {}; } - TRY(m_output->write_entire_buffer(m_traits.quote.bytes())); + TRY(m_output.write_entire_buffer(m_traits.quote.bytes())); GenericLexer lexer(string); while (!lexer.is_eof()) { if (lexer.consume_specific(m_traits.quote)) { switch (m_traits.quote_escape) { case WriterTraits::Repeat: - TRY(m_output->write_entire_buffer(m_traits.quote.bytes())); - TRY(m_output->write_entire_buffer(m_traits.quote.bytes())); + TRY(m_output.write_entire_buffer(m_traits.quote.bytes())); + TRY(m_output.write_entire_buffer(m_traits.quote.bytes())); break; case WriterTraits::Backslash: - TRY(m_output->write_entire_buffer({ "\\", 1 })); - TRY(m_output->write_entire_buffer(m_traits.quote.bytes())); + TRY(m_output.write_entire_buffer({ "\\", 1 })); + TRY(m_output.write_entire_buffer(m_traits.quote.bytes())); break; } continue; } auto ch = lexer.consume(); - TRY(m_output->write_entire_buffer({ &ch, 1 })); + TRY(m_output.write_entire_buffer({ &ch, 1 })); } - TRY(m_output->write_entire_buffer(m_traits.quote.bytes())); + TRY(m_output.write_entire_buffer(m_traits.quote.bytes())); return {}; } @@ -170,7 +170,7 @@ private: WriterTraits m_traits; WriterBehavior m_behaviors; HeaderType m_names; - Core::Stream::Handle<Core::Stream::Stream> m_output; + Core::Stream::Stream& m_output; }; } |