@@ -39,7 +39,7 @@ constexpr std::size_t length(std::string_view const text);
39
39
// /
40
40
template <std::size_t Capacity>
41
41
struct literal {
42
- char buffer[Capacity]{};
42
+ char buffer[Capacity + 1 ]{};
43
43
44
44
constexpr literal (std::string_view const text) { format_to (buffer, text, Capacity); }
45
45
@@ -226,6 +226,7 @@ struct attribute_t {
226
226
template <typename Out>
227
227
struct pen_t {
228
228
Out out;
229
+ std::size_t capacity{std::string_view::npos};
229
230
230
231
std::size_t written{};
231
232
@@ -244,14 +245,26 @@ struct pen_t {
244
245
return 1 ;
245
246
}
246
247
248
+ static constexpr bool has_close (style_t const style) {
249
+ switch (style) {
250
+ case style_t ::reset:
251
+ case style_t ::clear: return false ;
252
+ default : return true ;
253
+ }
254
+ }
255
+
256
+ constexpr bool full () const { return written + 1 >= capacity; }
257
+
247
258
constexpr pen_t & write_digit (std::uint32_t const digit) {
259
+ if (full ()) { return *this ; }
248
260
auto const ch = static_cast <char >(digit + ' 0' );
249
261
++written;
250
262
return write (std::string_view (&ch, 1 ));
251
263
}
252
264
253
265
constexpr pen_t & write (std::string_view const text) {
254
266
for (char const ch : text) {
267
+ if (full ()) { return *this ; }
255
268
*out++ = ch;
256
269
++written;
257
270
}
@@ -283,7 +296,7 @@ struct pen_t {
283
296
constexpr pen_t & write (attr_op_t <style_t > style) {
284
297
if (style.t == style_t ::clear) { write ({style_t ::reset}); }
285
298
write (attribute_start_v);
286
- if (style.op == op_type::close) {
299
+ if (style.op == op_type::close && has_close (style. t ) ) {
287
300
if (style.t == style_t ::bold) { style.t = style_t ::dim; }
288
301
write (" 2" );
289
302
}
@@ -300,8 +313,7 @@ struct null_writer {
300
313
};
301
314
302
315
template <typename Out>
303
- constexpr pen_t <Out>& write (pen_t <Out>& out_pen, std::string_view const text, std::size_t capacity = std::string_view::npos) {
304
- auto vacant = [capacity, &out_pen] { return capacity == std::string_view::npos || out_pen.written < capacity; };
316
+ constexpr pen_t <Out>& write (pen_t <Out>& out_pen, std::string_view const text) {
305
317
auto write_token = [&out_pen](std::string_view const token) -> pen_t <Out>& {
306
318
if (token.front () == ' <' && token.back () == ' >' ) {
307
319
auto attr = attribute_t {};
@@ -316,16 +328,16 @@ constexpr pen_t<Out>& write(pen_t<Out>& out_pen, std::string_view const text, st
316
328
};
317
329
auto tokenizer = tokenizer_t {text};
318
330
auto token = std::string_view{};
319
- while (vacant () && tokenizer (token)) { write_token (token); }
331
+ while (!out_pen. full () && tokenizer (token)) { write_token (token); }
320
332
return out_pen;
321
333
}
322
334
} // namespace detail
323
335
} // namespace forest
324
336
325
337
template <typename Out>
326
338
constexpr Out forest::format_to (Out out, std::string_view const text, std::size_t capacity) {
327
- auto pen = detail::pen_t <Out>{out};
328
- return detail::write (pen, text, capacity ).out ;
339
+ auto pen = detail::pen_t <Out>{out, capacity };
340
+ return detail::write (pen, text).out ;
329
341
}
330
342
331
343
constexpr std::size_t forest::length (std::string_view const text) {
0 commit comments