LibSWOC++ 1.5.14
Solid Wall of C++
Loading...
Searching...
No Matches
BufferWriter.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright Apache Software Foundation 2019
7
8#pragma once
9
10#include <cstdlib>
11#include <utility>
12#include <cstring>
13#include <vector>
14#include <string>
15#include <iosfwd>
16#include <string_view>
17
18#include "swoc/swoc_version.h"
19#include "swoc/TextView.h"
20#include "swoc/MemSpan.h"
21#include "swoc/bwf_fwd.h"
22
23namespace swoc { inline namespace SWOC_VERSION_NS {
24
36public:
42 virtual BufferWriter &write(char c) = 0;
43
54 virtual BufferWriter &write(void const *data, size_t length);
55
67
69 virtual const char *data() const = 0;
70
73 virtual bool error() const = 0;
74
81 virtual char *aux_data();
82
84 virtual size_t capacity() const = 0;
85
87 virtual size_t extent() const = 0;
88
90 size_t size() const;
91
93 size_t remaining() const;
94
107
122 virtual bool commit(size_t n) = 0;
123
132 virtual BufferWriter &discard(size_t n) = 0;
133
138 virtual BufferWriter &restrict(size_t n) = 0;
139
146 virtual BufferWriter &restore(size_t n) = 0;
147
162 virtual BufferWriter &copy(size_t dst, size_t src, size_t n) = 0;
163
164 // Force virtual destructor.
165 virtual ~BufferWriter();
166
180 template <typename... Args> BufferWriter &print(const TextView &fmt, Args &&...args);
181
193 template <typename... Args> BufferWriter &print_v(const TextView &fmt, const std::tuple<Args...> &args);
194
202 template <typename... Args> BufferWriter &print(const bwf::Format &fmt, Args &&...args);
203
215 template <typename... Args> BufferWriter &print_v(const bwf::Format &fmt, const std::tuple<Args...> &args);
216
242 template <typename Binding, typename Extractor>
243 BufferWriter &print_nfv(Binding &&names, Extractor &&ex, bwf::ArgPack const &args);
244
255 template <typename Binding, typename Extractor> BufferWriter &print_nfv(Binding const &names, Extractor &&ex);
256
265 template <typename Binding> BufferWriter &print_n(Binding const &names, TextView const &fmt);
266
276 template <typename T> BufferWriter &format(bwf::Spec const &spec, T &&t);
277
287 template <typename T> BufferWriter &format(bwf::Spec const &spec, T const &t);
288
296 virtual std::ostream &operator>>(std::ostream &stream) const = 0;
297};
298
303 using super_type = BufferWriter;
304 using self_type = FixedBufferWriter;
305
306public:
311 FixedBufferWriter(char *buffer, size_t capacity);
312
314 FixedBufferWriter(MemSpan<void> const &span);
315
317 FixedBufferWriter(MemSpan<char> const &span);
318
322 FixedBufferWriter(std::nullptr_t);
323
324 FixedBufferWriter(const FixedBufferWriter &) = delete;
325
326 FixedBufferWriter &operator=(const FixedBufferWriter &) = delete;
327
330
332 FixedBufferWriter &operator=(FixedBufferWriter &&that);
333
335 self_type &assign(MemSpan<char> const &span);
336
338 FixedBufferWriter &write(char c) override;
339
341 FixedBufferWriter &write(const void *data, size_t length) override;
342
343 // Bring in non-overridden methods.
344 using super_type::write;
345
347 const char *data() const override;
348
350 bool error() const override;
351
353 char *aux_data() override;
354
356 size_t capacity() const override;
357
359 size_t extent() const override;
360
362 bool commit(size_t n) override;
363
365 self_type &discard(size_t n) override;
366
368 self_type &restrict(size_t n) override;
369
371 self_type &restore(size_t n) override;
372
374 FixedBufferWriter &copy(size_t dst, size_t src, size_t n) override;
375
382 self_type &clear();
383
384 self_type &detach();
385
387 swoc::TextView view() const;
388
390 operator std::string_view() const;
391
393 operator swoc::TextView() const;
394
396 std::ostream &operator>>(std::ostream &stream) const override;
397
399 template <typename... Rest> self_type &print(TextView fmt, Rest &&...rest);
400
401 template <typename... Args> self_type &print_v(TextView fmt, std::tuple<Args...> const &args);
402
403 template <typename... Args> self_type &print(bwf::Format const &fmt, Args &&...args);
404
405 template <typename... Args> self_type &print_v(bwf::Format const &fmt, std::tuple<Args...> const &args);
407
408protected:
409 // Used for derived classes where we don't want to throw exceptions.
410 FixedBufferWriter(char *buffer, size_t capacity, bool noexcept_flag) noexcept;
411
412 char *const _buffer;
413 size_t _capacity;
414 size_t _attempted = 0;
415};
416
440template <size_t N> class LocalBufferWriter : public FixedBufferWriter {
441 using self_type = LocalBufferWriter;
442 using super_type = FixedBufferWriter;
443
444public:
446 LocalBufferWriter() noexcept;
447
448 LocalBufferWriter(const LocalBufferWriter &that) = delete;
449
450 LocalBufferWriter &operator=(const LocalBufferWriter &that) = delete;
451
452protected:
453 char _arr[N];
454};
455
456// --------------- Implementation --------------------
457
458inline BufferWriter::~BufferWriter() {}
459
460inline BufferWriter &
461BufferWriter::write(const void *data, size_t length) {
462 const char *d = static_cast<const char *>(data);
463
464 while (length--) {
465 this->write(*(d++));
466 }
467 return *this;
468}
469
470#if 0
471inline BufferWriter &
472BufferWriter::write(const std::string_view &sv) {
473 return this->write(sv.data(), sv.size());
474}
475#endif
476
477inline BufferWriter &
479 return this->write(span.data(), span.size());
480}
481
482inline char *
484 return nullptr;
485}
486
487inline size_t
489 return std::min(this->extent(), this->capacity());
490}
491
492inline size_t
494 return this->capacity() - this->size();
495}
496
497// --- FixedBufferWriter ---
499 if (_capacity != 0 && buffer == nullptr) {
500 throw(std::invalid_argument{"FixedBufferWriter created with null buffer and non-zero size."});
501 };
502}
503
504inline FixedBufferWriter::FixedBufferWriter(char *buffer, size_t capacity, bool /* noexcept_flag */) noexcept : _buffer(buffer), _capacity(capacity) {
505}
506
508 : _buffer{static_cast<char *>(span.data())}, _capacity{span.size()} {}
509
510inline FixedBufferWriter::FixedBufferWriter(MemSpan<char> const &span) : _buffer{span.begin()}, _capacity{span.size()} {}
511
512inline FixedBufferWriter::FixedBufferWriter(std::nullptr_t) : _buffer(nullptr), _capacity(0) {}
513
514inline FixedBufferWriter::self_type &
515FixedBufferWriter::detach() {
516 const_cast<char *&>(_buffer) = nullptr;
517 _capacity = 0;
518 _attempted = 0;
519 return *this;
520}
521
524 that.detach();
525}
526
527inline FixedBufferWriter::self_type &
529 const_cast<char *&>(_buffer) = span.data();
530 _capacity = span.size();
531 _attempted = 0;
532 return *this;
533}
534
535inline FixedBufferWriter &
536FixedBufferWriter::operator=(FixedBufferWriter &&that) {
537 const_cast<char *&>(_buffer) = that._buffer;
538 _capacity = that._capacity;
539 _attempted = that._attempted;
540 that.detach();
541 return *this;
542}
543
544inline FixedBufferWriter &
546 if (_attempted < _capacity) {
547 _buffer[_attempted] = c;
548 }
549 ++_attempted;
550
551 return *this;
552}
553
554inline FixedBufferWriter &
555FixedBufferWriter::write(const void *data, size_t length) {
556 const size_t newSize = _attempted + length;
557
558 if (_buffer) {
559 if (newSize <= _capacity) {
560 std::memcpy(_buffer + _attempted, data, length);
561 } else if (_attempted < _capacity) {
562 std::memcpy(_buffer + _attempted, data, _capacity - _attempted);
563 }
564 }
565 _attempted = newSize;
566
567 return *this;
568}
569
571inline const char *
573 return _buffer;
574}
575
576inline bool
578 return _attempted > _capacity;
579}
580
581inline char *
583 return error() ? nullptr : _buffer + _attempted;
584}
585
586inline bool
588 _attempted += n;
589
590 return true;
591}
592
593inline size_t
595 return _capacity;
596}
597
598inline size_t
600 return _attempted;
601}
602
603inline auto FixedBufferWriter::restrict(size_t n) -> self_type & {
604 if (n > _capacity) {
605 throw(std::invalid_argument{"FixedBufferWriter restrict value more than capacity"});
606 }
607 _capacity -= n;
608 return *this;
609}
610
611inline auto
612FixedBufferWriter::restore(size_t n) -> self_type & {
613 if (error()) {
615 }
616 _capacity += n;
617 return *this;
618}
619
620inline auto
621FixedBufferWriter::discard(size_t n) -> self_type & {
622 _attempted -= std::min(_attempted, n);
623 return *this;
624}
625
626inline auto
627FixedBufferWriter::clear() -> self_type & {
628 _attempted = 0;
629 return *this;
630}
631
632inline auto
633FixedBufferWriter::copy(size_t dst, size_t src, size_t n) -> self_type & {
634 auto limit = std::min<size_t>(_capacity, _attempted); // max offset of region possible.
635 MemSpan<char> src_span{_buffer + src, std::min(limit, src + n)};
636 MemSpan<char> dst_span{_buffer + dst, std::min(limit, dst + n)};
637 std::memmove(dst_span.data(), src_span.data(), std::min(dst_span.size(), src_span.size()));
638 return *this;
639}
640
641inline swoc::TextView
643 return {_buffer, size()};
644}
645
646inline FixedBufferWriter::operator std::string_view() const {
647 return this->view();
648}
649
650inline FixedBufferWriter::operator swoc::TextView() const {
651 return this->view();
652}
653
654// --- LocalBufferWriter ---
655template <size_t N> LocalBufferWriter<N>::LocalBufferWriter() noexcept : super_type(_arr, N, true) {}
656
657}} // namespace swoc::SWOC_VERSION_NS
658
660namespace std {
661inline ostream &
662operator<<(ostream &s, swoc::BufferWriter const &w) {
663 return w >> s;
664}
665} // end namespace std
virtual bool commit(size_t n)=0
virtual BufferWriter & copy(size_t dst, size_t src, size_t n)=0
virtual bool error() const =0
BufferWriter & print(const TextView &fmt, Args &&...args)
Definition bwf_base.h:927
virtual std::ostream & operator>>(std::ostream &stream) const =0
BufferWriter & print_nfv(Binding &&names, Extractor &&ex, bwf::ArgPack const &args)
Definition bwf_base.h:865
BufferWriter & format(bwf::Spec const &spec, T &&t)
Definition bwf_base.h:1346
virtual BufferWriter & discard(size_t n)=0
BufferWriter & print_n(Binding const &names, TextView const &fmt)
Definition bwf_base.h:957
virtual BufferWriter & restore(size_t n)=0
virtual BufferWriter & restrict(size_t n)=0
BufferWriter & print_v(const TextView &fmt, const std::tuple< Args... > &args)
Definition bwf_base.h:939
virtual size_t capacity() const =0
virtual size_t extent() const =0
size_t remaining() const
virtual BufferWriter & write(char c)=0
virtual const char * data() const =0
MemSpan< char > aux_span()
Definition bwf_base.h:962
size_t size() const
virtual char * aux_data()
FixedBufferWriter(char *buffer, size_t capacity)
operator swoc::TextView() const
Provide a string_view of all successfully written characters as a user conversion.
size_t extent() const override
Get the total output sent to the writer.
swoc::TextView view() const
char * aux_data() override
self_type & restrict(size_t n) override
Reduce the capacity by n.
bool error() const override
self_type & restore(size_t n) override
Restore n bytes of the capacity.
size_t _capacity
Size of output buffer.
size_t capacity() const override
Get the total capacity of the output buffer.
FixedBufferWriter & copy(size_t dst, size_t src, size_t n) override
Copy data in the buffer.
self_type & assign(MemSpan< char > const &span)
Reset buffer.
const char * data() const override
Return the output buffer.
FixedBufferWriter & write(char c) override
Write a single character c to the buffer.
std::ostream & operator>>(std::ostream &stream) const override
Output the buffer contents to the stream.
Definition bw_format.cc:741
size_t _attempted
Number of characters written, including those discarded due error condition.
bool commit(size_t n) override
Advance the used part of the output buffer.
self_type & discard(size_t n) override
Drop n characters from the end of the buffer.
char *const _buffer
Output buffer.
LocalBufferWriter() noexcept
Construct an empty writer.
char _arr[N]
output buffer.
T * data() const
Definition MemSpan.h:1154
constexpr size_t size() const
Number of elements in the span.
Definition MemSpan.h:1178
STL namespace.
For template deduction guides.
Definition ArenaWriter.cc:9