Sourcemeta Core 0.0.0
Loading...
Searching...
No Matches
html_buffer.h
1#ifndef SOURCEMETA_CORE_HTML_BUFFER_H_
2#define SOURCEMETA_CORE_HTML_BUFFER_H_
3
4#ifndef SOURCEMETA_CORE_HTML_EXPORT
5#include <sourcemeta/core/html_export.h>
6#endif
7
8#include <sourcemeta/core/preprocessor.h>
9
10#include <cassert> // assert
11#include <cstddef> // std::size_t
12#include <cstring> // std::memcpy
13#include <iostream> // std::ostream
14#include <string> // std::string
15#include <string_view> // std::string_view
16#include <utility> // std::cmp_less, std::move
17
18namespace sourcemeta::core {
19
22class SOURCEMETA_CORE_HTML_EXPORT HTMLBuffer {
23public:
24 HTMLBuffer() = default;
25 HTMLBuffer(const HTMLBuffer &) = delete;
26 auto operator=(const HTMLBuffer &) -> HTMLBuffer & = delete;
27 HTMLBuffer(HTMLBuffer &&) = delete;
28 auto operator=(HTMLBuffer &&) -> HTMLBuffer & = delete;
29
32 SOURCEMETA_FORCEINLINE auto reserve(const std::size_t bytes) -> void {
33 if (this->capacity() < bytes) {
34 this->reallocate(bytes);
35 }
36 }
37
39 SOURCEMETA_FORCEINLINE auto append(const char character) -> void {
40 if (this->cursor_ == this->end_) [[unlikely]] {
41 this->grow(1);
42 }
43
44 *this->cursor_ = character;
45 ++this->cursor_;
46 }
47
49 SOURCEMETA_FORCEINLINE auto append(const std::string_view data) -> void {
50 const auto length{data.size()};
51 if (length == 0) {
52 return;
53 }
54
55 if (std::cmp_less(this->end_ - this->cursor_, length)) [[unlikely]] {
56 this->grow(length);
57 }
58
59 std::memcpy(this->cursor_, data.data(), length);
60 this->cursor_ += length;
61 }
62
66 SOURCEMETA_FORCEINLINE auto reserve_additional(const std::size_t bytes)
67 -> void {
68 if (std::cmp_less(this->end_ - this->cursor_, bytes)) [[unlikely]] {
69 this->grow(bytes);
70 }
71 }
72
75 SOURCEMETA_FORCEINLINE auto
76 append_unchecked(const std::string_view data) noexcept -> void {
77 assert(std::cmp_less_equal(data.size(), this->end_ - this->cursor_));
78 if (!data.empty()) {
79 std::memcpy(this->cursor_, data.data(), data.size());
80 this->cursor_ += data.size();
81 }
82 }
83
85 [[nodiscard]] SOURCEMETA_FORCEINLINE auto size() const noexcept
86 -> std::size_t {
87 return static_cast<std::size_t>(this->cursor_ - this->begin_);
88 }
89
91 [[nodiscard]] SOURCEMETA_FORCEINLINE auto back() const noexcept -> char {
92 assert(this->cursor_ != this->begin_);
93 return *(this->cursor_ - 1);
94 }
95
98 SOURCEMETA_FORCEINLINE auto remove_suffix(const std::size_t count) noexcept
99 -> void {
100 assert(count <= this->size());
101 this->cursor_ -= count;
102 }
103
106 [[nodiscard]] SOURCEMETA_FORCEINLINE auto view() const noexcept
107 -> std::string_view {
108 return {this->begin_, this->size()};
109 }
110
112 SOURCEMETA_FORCEINLINE auto clear() noexcept -> void {
113 this->cursor_ = this->begin_;
114 }
115
117 [[nodiscard]] SOURCEMETA_FORCEINLINE auto str() -> const std::string & {
118 this->buffer_.resize(this->size());
119 this->begin_ = this->buffer_.data();
120 this->cursor_ = this->begin_ + this->buffer_.size();
121 this->end_ = this->cursor_;
122 return this->buffer_;
123 }
124
127 [[nodiscard]] SOURCEMETA_FORCEINLINE auto take() -> std::string {
128 this->buffer_.resize(this->size());
129 std::string result{std::move(this->buffer_)};
130 this->buffer_.clear();
131 this->begin_ = nullptr;
132 this->cursor_ = nullptr;
133 this->end_ = nullptr;
134 return result;
135 }
136
138 auto write(std::ostream &stream) -> void;
139
140private:
141 [[nodiscard]] SOURCEMETA_FORCEINLINE auto capacity() const noexcept
142 -> std::size_t {
143 return static_cast<std::size_t>(this->end_ - this->begin_);
144 }
145
146 auto grow(std::size_t needed) -> void;
147 auto reallocate(std::size_t capacity) -> void;
148
149// Exporting symbols that depends on the standard C++ library is considered
150// safe.
151// https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-2-c4275?view=msvc-170&redirectedfrom=MSDN
152#if defined(_MSC_VER)
153#pragma warning(push)
154#pragma warning(disable : 4251)
155#endif
156 std::string buffer_;
157#if defined(_MSC_VER)
158#pragma warning(pop)
159#endif
160 char *begin_{nullptr};
161 char *cursor_{nullptr};
162 char *end_{nullptr};
163};
164
165} // namespace sourcemeta::core
166
167#endif
SOURCEMETA_FORCEINLINE auto size() const noexcept -> std::size_t
Get the number of bytes accumulated so far.
Definition html_buffer.h:85
SOURCEMETA_FORCEINLINE auto append(const std::string_view data) -> void
Append a sequence of characters to the buffer.
Definition html_buffer.h:49
SOURCEMETA_FORCEINLINE auto take() -> std::string
Definition html_buffer.h:127
auto write(std::ostream &stream) -> void
Write the accumulated contents to an output stream.
SOURCEMETA_FORCEINLINE auto reserve_additional(const std::size_t bytes) -> void
Definition html_buffer.h:66
SOURCEMETA_FORCEINLINE auto append(const char character) -> void
Append a single character to the buffer.
Definition html_buffer.h:39
SOURCEMETA_FORCEINLINE auto back() const noexcept -> char
Get the last character of the buffer, which must not be empty.
Definition html_buffer.h:91
SOURCEMETA_FORCEINLINE auto clear() noexcept -> void
Discard the accumulated contents, keeping the capacity for reuse.
Definition html_buffer.h:112
SOURCEMETA_FORCEINLINE auto str() -> const std::string &
Get the accumulated contents of the buffer.
Definition html_buffer.h:117
SOURCEMETA_FORCEINLINE auto view() const noexcept -> std::string_view
Definition html_buffer.h:106
SOURCEMETA_FORCEINLINE auto append_unchecked(const std::string_view data) noexcept -> void
Definition html_buffer.h:76
SOURCEMETA_FORCEINLINE auto reserve(const std::size_t bytes) -> void
Definition html_buffer.h:32
SOURCEMETA_FORCEINLINE auto remove_suffix(const std::size_t count) noexcept -> void
Definition html_buffer.h:98