14 #include <string_view> 28 void ensureAccTill(
size_t i)
const {
34 for (
auto iter = std::next(sz_.begin(), accDirty_ - 1),
35 e = std::next(sz_.begin(), i);
37 acc_[accDirty_] = acc_[accDirty_ - 1] + *iter;
43 inline bool isAsciiOnly()
const {
47 inline bool isFixedCursor()
const {
54 std::vector<size_t> sz_;
56 mutable std::vector<size_t> acc_ = {0};
57 mutable size_t accDirty_ = 0;
63 InputBuffer::~InputBuffer() =
default;
81 std::string_view view(s, length);
84 throw std::invalid_argument(
"Invalid UTF-8 string");
86 if (d->isAsciiOnly() && utf8Length != view.size()) {
87 throw std::invalid_argument(
88 "ascii only buffer only accept ascii only string");
90 if (d->maxSize_ && (utf8Length +
size() > d->maxSize_)) {
93 d->input_.insert(std::next(d->input_.begin(),
cursorByChar()), view.begin(),
95 if (!d->isAsciiOnly()) {
96 auto pos = d->cursor_;
97 for (
auto chrView : utf8::MakeUTF8StringViewRange(view)) {
98 d->sz_.insert(std::next(d->sz_.begin(), pos), chrView.size());
102 d->acc_.resize(d->sz_.size() + 1);
103 auto newDirty = d->cursor_ > 0 ? d->cursor_ - 1 : 0;
104 if (d->accDirty_ > newDirty) {
105 d->accDirty_ = newDirty;
108 d->cursor_ += utf8Length;
114 if (d->isAsciiOnly()) {
117 if (d->cursor_ ==
size()) {
118 return d->input_.size();
120 d->ensureAccTill(d->cursor_);
121 return d->acc_[d->cursor_];
131 return d->isAsciiOnly() ? d->input_.size() : d->sz_.size();
136 if (d->isFixedCursor()) {
137 if (cursor !=
size()) {
138 throw std::out_of_range(
139 "only valid position of cursor is size() for fixed cursor");
144 if (d->cursor_ >
size()) {
145 throw std::out_of_range(
"cursor position out of range");
162 if (from < to && to <=
size()) {
163 if (d->isFixedCursor() && to !=
size()) {
169 if (d->isAsciiOnly()) {
171 lengthByChar = to - from;
173 d->ensureAccTill(to);
174 fromByChar = d->acc_[from];
175 lengthByChar = d->acc_[to] - fromByChar;
176 d->sz_.erase(std::next(d->sz_.begin(), from),
177 std::next(d->sz_.begin(), to));
179 d->acc_.resize(d->sz_.size() + 1);
181 if (d->cursor_ > from) {
182 if (d->cursor_ <= to) {
185 d->cursor_ -= to - from;
188 d->input_.erase(fromByChar, lengthByChar);
195 throw std::out_of_range(
"out of range");
197 if (d->isAsciiOnly()) {
201 return {d->acc_[i], d->acc_[i] + d->sz_[i]};
204 std::string_view InputBuffer::viewAt(
size_t i)
const {
205 auto [start, end] =
rangeAt(i);
206 return std::string_view(
userInput()).substr(start, end - start);
212 throw std::out_of_range(
"out of range");
214 if (d->isAsciiOnly()) {
219 d->input_.begin() + d->acc_[i] + d->sz_[i]);
224 if (d->isAsciiOnly()) {
232 d->input_.shrink_to_fit();
233 d->sz_.shrink_to_fit();
234 d->acc_.shrink_to_fit();
bool type(const char *s, size_t length)
Type a C-String with length into buffer.
Whether the input buffer only supports cursor at the end of buffer.
size_t size() const
Size of buffer, by number of utf8 character.
std::string UCS4ToUTF8(uint32_t code)
Convert UCS4 to UTF8 string.
size_t length(Iter start, Iter end)
Return the number UTF-8 characters in the string iterator range.
size_t cursorByChar() const
Cursor position by char (byte).
virtual void erase(size_t from, size_t to)
Erase a range of character.
InputBuffer(InputBufferOptions options=InputBufferOption::NoOption)
Create a input buffer with options.
void shrinkToFit()
Save memory by call shrink to fit to internal buffer.
C++ Utility functions for handling utf8 strings.
const std::string & userInput() const
Utf8 string in the buffer.
InputBufferOptions options() const
Get the buffer option.
virtual bool typeImpl(const char *s, size_t length)
Type a certain length of utf8 character to the buffer.
size_t lengthValidated(Iter start, Iter end)
Validate and return the number UTF-8 characters in the string iterator range.
constexpr size_t INVALID_LENGTH
Possible return value of lengthValidated if the string is not valid.
uint32_t getChar(Iter iter, Iter end)
Get next UCS4 char from iter, do not cross end.
uint32_t charAt(size_t i) const
UCS-4 char in the buffer. Will raise exception if i is out of range.
size_t sizeAt(size_t i) const
Byte size at position i.
std::pair< size_t, size_t > rangeAt(size_t i) const
Byte range for character at position i.
virtual void setCursor(size_t cursor)
Set cursor position, by character.
Class provides bit flag support for Enum.
size_t maxSize() const
Get the max size of the buffer.
size_t cursor() const
Cursor position by utf8 character.
void setMaxSize(size_t s)
Set max size of the buffer.
The input buffer is ascii character only, non ascii char will raise exception.