@@ -39,7 +39,7 @@ constexpr std::size_t length(std::string_view const text);
3939// /
4040template <std::size_t Capacity>
4141struct literal {
42- char buffer[Capacity]{};
42+ char buffer[Capacity + 1 ]{};
4343
4444 constexpr literal (std::string_view const text) { format_to (buffer, text, Capacity); }
4545
@@ -226,6 +226,7 @@ struct attribute_t {
226226template <typename Out>
227227struct pen_t {
228228 Out out;
229+ std::size_t capacity{std::string_view::npos};
229230
230231 std::size_t written{};
231232
@@ -244,14 +245,26 @@ struct pen_t {
244245 return 1 ;
245246 }
246247
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+
247258 constexpr pen_t & write_digit (std::uint32_t const digit) {
259+ if (full ()) { return *this ; }
248260 auto const ch = static_cast <char >(digit + ' 0' );
249261 ++written;
250262 return write (std::string_view (&ch, 1 ));
251263 }
252264
253265 constexpr pen_t & write (std::string_view const text) {
254266 for (char const ch : text) {
267+ if (full ()) { return *this ; }
255268 *out++ = ch;
256269 ++written;
257270 }
@@ -283,7 +296,7 @@ struct pen_t {
283296 constexpr pen_t & write (attr_op_t <style_t > style) {
284297 if (style.t == style_t ::clear) { write ({style_t ::reset}); }
285298 write (attribute_start_v);
286- if (style.op == op_type::close) {
299+ if (style.op == op_type::close && has_close (style. t ) ) {
287300 if (style.t == style_t ::bold) { style.t = style_t ::dim; }
288301 write (" 2" );
289302 }
@@ -300,8 +313,7 @@ struct null_writer {
300313};
301314
302315template <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) {
305317 auto write_token = [&out_pen](std::string_view const token) -> pen_t <Out>& {
306318 if (token.front () == ' <' && token.back () == ' >' ) {
307319 auto attr = attribute_t {};
@@ -316,16 +328,16 @@ constexpr pen_t<Out>& write(pen_t<Out>& out_pen, std::string_view const text, st
316328 };
317329 auto tokenizer = tokenizer_t {text};
318330 auto token = std::string_view{};
319- while (vacant () && tokenizer (token)) { write_token (token); }
331+ while (!out_pen. full () && tokenizer (token)) { write_token (token); }
320332 return out_pen;
321333}
322334} // namespace detail
323335} // namespace forest
324336
325337template <typename Out>
326338constexpr 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 ;
329341}
330342
331343constexpr std::size_t forest::length (std::string_view const text) {
0 commit comments