9
9
#include < AK/DeprecatedString.h>
10
10
#include < AK/GenericLexer.h>
11
11
#include < AK/OwnPtr.h>
12
- #include < AK/Stream.h>
13
12
#include < AK/StringView.h>
14
13
#include < AK/Types.h>
15
14
#include < AK/Vector.h>
15
+ #include < LibCore/Stream.h>
16
16
17
17
namespace Writer {
18
18
@@ -34,17 +34,6 @@ struct WriterTraits {
34
34
} quote_escape { Repeat };
35
35
};
36
36
37
- #define ENUMERATE_WRITE_ERRORS () \
38
- E (None, " No errors" ) \
39
- E (NonConformingColumnCount, " Header count does not match given column count" ) \
40
- E (InternalError, " Internal error" )
41
-
42
- enum class WriteError {
43
- #define E (name, _ ) name,
44
- ENUMERATE_WRITE_ERRORS ()
45
- #undef E
46
- };
47
-
48
37
constexpr WriterBehavior default_behaviors ()
49
38
{
50
39
return WriterBehavior::None;
@@ -53,107 +42,84 @@ constexpr WriterBehavior default_behaviors()
53
42
template <typename ContainerType, typename HeaderType = Vector<StringView>>
54
43
class XSV {
55
44
public:
56
- XSV (OutputStream& output, ContainerType const & data, WriterTraits traits, HeaderType const & headers = {}, WriterBehavior behaviors = default_behaviors())
45
+ XSV (Core::Stream::Handle<Core::Stream::Stream> output, ContainerType const & data, WriterTraits traits, HeaderType headers = {}, WriterBehavior behaviors = default_behaviors())
57
46
: m_data(data)
58
47
, m_traits(move(traits))
59
48
, m_behaviors(behaviors)
60
49
, m_names(headers)
61
- , m_output(output)
50
+ , m_output(move( output) )
62
51
{
63
52
if (!headers.is_empty ())
64
53
m_behaviors = m_behaviors | WriterBehavior::WriteHeaders;
65
54
}
66
55
67
56
virtual ~XSV () = default ;
68
57
69
- bool has_error () const { return m_error != WriteError::None; }
70
- WriteError error () const { return m_error; }
71
- DeprecatedString error_string () const
72
- {
73
- switch (m_error) {
74
- #define E (x, y ) \
75
- case WriteError::x: \
76
- return y;
77
-
78
- ENUMERATE_WRITE_ERRORS ();
79
- #undef E
80
- }
81
- VERIFY_NOT_REACHED ();
82
- }
83
-
84
- void generate ()
58
+ ErrorOr<void > generate ()
85
59
{
86
60
auto with_headers = has_flag (m_behaviors, WriterBehavior::WriteHeaders);
87
61
if (with_headers) {
88
- write_row (m_names);
89
- if (m_output.write ({ " \n " , 1 }) != 1 )
90
- set_error (WriteError::InternalError);
62
+ TRY (write_row (m_names));
63
+ TRY (m_output->write_entire_buffer ({ " \n " , 1 }));
91
64
}
92
65
93
66
for (auto && row : m_data) {
94
67
if (with_headers) {
95
68
if (row.size () != m_names.size ())
96
- set_error (WriteError::NonConformingColumnCount );
69
+ return Error::from_string_literal ( " Header count does not match given column count " );
97
70
}
98
71
99
- write_row (row);
100
- if (m_output.write ({ " \n " , 1 }) != 1 )
101
- set_error (WriteError::InternalError);
72
+ TRY (write_row (row));
73
+ TRY (m_output->write_entire_buffer ({ " \n " , 1 }));
102
74
}
75
+ return {};
103
76
}
104
77
105
- void generate_preview ()
78
+ ErrorOr< void > generate_preview ()
106
79
{
107
80
auto lines_written = 0 ;
108
81
constexpr auto max_preview_lines = 8 ;
109
82
110
83
auto with_headers = has_flag (m_behaviors, WriterBehavior::WriteHeaders);
111
84
if (with_headers) {
112
- write_row (m_names);
113
- if (m_output.write ({ " \n " , 1 }) != 1 )
114
- set_error (WriteError::InternalError);
85
+ TRY (write_row (m_names));
86
+ TRY (m_output->write_entire_buffer ({ " \n " , 1 }));
115
87
++lines_written;
116
88
}
117
89
118
90
for (auto && row : m_data) {
119
91
if (with_headers) {
120
92
if (row.size () != m_names.size ())
121
- set_error (WriteError::NonConformingColumnCount );
93
+ return Error::from_string_literal ( " Header count does not match given column count " );
122
94
}
123
95
124
- write_row (row);
125
- if (m_output.write ({ " \n " , 1 }) != 1 )
126
- set_error (WriteError::InternalError);
96
+ TRY (write_row (row));
97
+ TRY (m_output->write_entire_buffer ({ " \n " , 1 }));
127
98
++lines_written;
128
99
129
100
if (lines_written >= max_preview_lines)
130
101
break ;
131
102
}
103
+ return {};
132
104
}
133
105
134
106
private:
135
- void set_error (WriteError error)
136
- {
137
- if (m_error == WriteError::None)
138
- m_error = error;
139
- }
140
-
141
107
template <typename T>
142
- void write_row (T&& row)
108
+ ErrorOr< void > write_row (T&& row)
143
109
{
144
110
bool first = true ;
145
111
for (auto && entry : row) {
146
112
if (!first) {
147
- if (m_output.write (m_traits.separator .bytes ()) != m_traits.separator .length ())
148
- set_error (WriteError::InternalError);
113
+ TRY (m_output->write_entire_buffer (m_traits.separator .bytes ()));
149
114
}
150
115
first = false ;
151
- write_entry (entry);
116
+ TRY ( write_entry (entry) );
152
117
}
118
+ return {};
153
119
}
154
120
155
121
template <typename T>
156
- void write_entry (T&& entry)
122
+ ErrorOr< void > write_entry (T&& entry)
157
123
{
158
124
auto string = DeprecatedString::formatted (" {}" , FormatIfSupported (entry));
159
125
@@ -169,49 +135,42 @@ class XSV {
169
135
}
170
136
171
137
if (safe_to_write_normally) {
172
- if (m_output. write (string. bytes ()) != string.length ())
173
- set_error (WriteError::InternalError );
174
- return ;
138
+ if (! string.is_empty ())
139
+ TRY (m_output-> write_entire_buffer (string. bytes ()) );
140
+ return {} ;
175
141
}
176
142
177
- if (m_output.write (m_traits.quote .bytes ()) != m_traits.quote .length ())
178
- set_error (WriteError::InternalError);
143
+ TRY (m_output->write_entire_buffer (m_traits.quote .bytes ()));
179
144
180
145
GenericLexer lexer (string);
181
146
while (!lexer.is_eof ()) {
182
147
if (lexer.consume_specific (m_traits.quote )) {
183
148
switch (m_traits.quote_escape ) {
184
149
case WriterTraits::Repeat:
185
- if (m_output.write (m_traits.quote .bytes ()) != m_traits.quote .length ())
186
- set_error (WriteError::InternalError);
187
- if (m_output.write (m_traits.quote .bytes ()) != m_traits.quote .length ())
188
- set_error (WriteError::InternalError);
150
+ TRY (m_output->write_entire_buffer (m_traits.quote .bytes ()));
151
+ TRY (m_output->write_entire_buffer (m_traits.quote .bytes ()));
189
152
break ;
190
153
case WriterTraits::Backslash:
191
- if (m_output.write ({ " \\ " , 1 }) != 1 )
192
- set_error (WriteError::InternalError);
193
- if (m_output.write (m_traits.quote .bytes ()) != m_traits.quote .length ())
194
- set_error (WriteError::InternalError);
154
+ TRY (m_output->write_entire_buffer ({ " \\ " , 1 }));
155
+ TRY (m_output->write_entire_buffer (m_traits.quote .bytes ()));
195
156
break ;
196
157
}
197
158
continue ;
198
159
}
199
160
200
161
auto ch = lexer.consume ();
201
- if (m_output.write ({ &ch, 1 }) != 1 )
202
- set_error (WriteError::InternalError);
162
+ TRY (m_output->write_entire_buffer ({ &ch, 1 }));
203
163
}
204
164
205
- if (m_output. write (m_traits.quote .bytes ()) != m_traits. quote . length ())
206
- set_error (WriteError::InternalError) ;
165
+ TRY (m_output-> write_entire_buffer (m_traits.quote .bytes ()));
166
+ return {} ;
207
167
}
208
168
209
169
ContainerType const & m_data;
210
170
WriterTraits m_traits;
211
171
WriterBehavior m_behaviors;
212
- HeaderType const & m_names;
213
- WriteError m_error { WriteError::None };
214
- OutputStream& m_output;
172
+ HeaderType m_names;
173
+ Core::Stream::Handle<Core::Stream::Stream> m_output;
215
174
};
216
175
217
176
}
0 commit comments