1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 13:27:35 +00:00

Spreadsheet: Generate file previews in memory and save directly to file

When we were asked to make a new preview text, we first generated the
whole file in the /tmp directory and then read the first 8 lines to put
them in a text box. This was doing a bit of unnecessary work at first,
but more importantly, didn't work on a given file descriptor from
FileSystemAccessServer as we were copying a file to a filename instead,
meaning that we also had to unveil the whole home directory.

Anyway, previews will be written now to a MemoryStream by the generator,
which will limit to 8 lines. File saves will omit /tmp entirely,
allowing us to tighten program unveil list a little. :^)
This commit is contained in:
Karol Kosek 2023-01-01 20:10:06 +01:00 committed by Ali Mohammad Pur
parent c74441395b
commit 29a3cdcfb7
4 changed files with 60 additions and 113 deletions

View file

@ -53,17 +53,15 @@ constexpr WriterBehavior default_behaviors()
template<typename ContainerType, typename HeaderType = Vector<StringView>>
class XSV {
public:
XSV(OutputStream& output, ContainerType const& data, WriterTraits const& traits, HeaderType const& headers = {}, WriterBehavior behaviors = default_behaviors())
XSV(OutputStream& output, ContainerType const& data, WriterTraits traits, HeaderType const& headers = {}, WriterBehavior behaviors = default_behaviors())
: m_data(data)
, m_traits(traits)
, m_traits(move(traits))
, m_behaviors(behaviors)
, m_names(headers)
, m_output(output)
{
if (!headers.is_empty())
m_behaviors = m_behaviors | WriterBehavior::WriteHeaders;
generate();
}
virtual ~XSV() = default;
@ -83,13 +81,6 @@ public:
VERIFY_NOT_REACHED();
}
private:
void set_error(WriteError error)
{
if (m_error == WriteError::None)
m_error = error;
}
void generate()
{
auto with_headers = has_flag(m_behaviors, WriterBehavior::WriteHeaders);
@ -111,6 +102,42 @@ private:
}
}
void generate_preview()
{
auto lines_written = 0;
constexpr auto max_preview_lines = 8;
auto with_headers = has_flag(m_behaviors, WriterBehavior::WriteHeaders);
if (with_headers) {
write_row(m_names);
if (m_output.write({ "\n", 1 }) != 1)
set_error(WriteError::InternalError);
++lines_written;
}
for (auto&& row : m_data) {
if (with_headers) {
if (row.size() != m_names.size())
set_error(WriteError::NonConformingColumnCount);
}
write_row(row);
if (m_output.write({ "\n", 1 }) != 1)
set_error(WriteError::InternalError);
++lines_written;
if (lines_written >= max_preview_lines)
break;
}
}
private:
void set_error(WriteError error)
{
if (m_error == WriteError::None)
m_error = error;
}
template<typename T>
void write_row(T&& row)
{
@ -180,7 +207,7 @@ private:
}
ContainerType const& m_data;
WriterTraits const& m_traits;
WriterTraits m_traits;
WriterBehavior m_behaviors;
HeaderType const& m_names;
WriteError m_error { WriteError::None };