7 #include "arg_router/utility/utf8/double_width.hpp"
8 #include "arg_router/utility/utf8/grapheme_cluster_break.hpp"
9 #include "arg_router/utility/utf8/line_break.hpp"
10 #include "arg_router/utility/utf8/whitespace.hpp"
11 #include "arg_router/utility/utf8/zero_width.hpp"
13 #include <string_view>
20 template <std::
size_t N>
21 [[nodiscard]] constexpr std::optional<code_point::range> find_range(
22 const std::array<code_point::range, N>& table,
25 auto first = table.begin();
29 const auto step = len / 2;
30 auto halfway = first + step;
32 if (cp < halfway->first()) {
34 }
else if (cp <= halfway->last()) {
88 constexpr
explicit range_t(std::string_view str) noexcept : str_{str} {}
90 std::string_view str_;
98 [[nodiscard]] constexpr
static range_t range(std::string_view str) noexcept
107 constexpr
iterator() noexcept : current_{0}, trailing_window_{} {}
114 constexpr
explicit iterator(std::string_view str) noexcept :
115 current_{0}, str_{str}, trailing_window_{}
117 fill_trailing_window();
129 if (str_.empty() && other.str_.empty()) {
132 return (str_.data() == other.str_.data()) && (str_.size() == other.str_.size());
142 return !(*
this == other);
151 return str_.substr(0, current_);
161 str_.remove_prefix(current_);
182 constexpr
static auto trailing_window_size = std::size_t{AR_UTF8_TRAILING_WINDOW_SIZE};
187 auto result = grapheme_cluster_break_class::any;
198 for (
auto rule : no_break_rules::grapheme_cluster<trailing_window_size>) {
199 if (rule(trailing_window_, next_class)) {
207 constexpr
void fill_trailing_window() noexcept
210 for (
auto& p : trailing_window_) {
211 p = grapheme_cluster_break_class::any;
215 constexpr
void rotate_trailing_window() noexcept
218 auto it = trailing_window_.rbegin();
221 if (it == trailing_window_.rend()) {
228 constexpr
void update_current() noexcept
237 for (
auto it = code_point::iterator{str_}; it != code_point::iterator{}; ++it) {
246 rotate_trailing_window();
247 trailing_window_.front() = extract_class(*this_cp);
250 auto next_break_class = grapheme_cluster_break_class::any;
254 if (next_it != code_point::iterator{}) {
257 next_break_class = extract_class(*next_cp);
262 if (should_break(next_break_class)) {
268 std::size_t current_;
269 std::string_view str_;
270 std::array<grapheme_cluster_break_class, trailing_window_size> trailing_window_;
278 [[nodiscard]]
inline constexpr std::size_t
count(std::string_view str) noexcept
289 [[nodiscard]]
inline constexpr
bool is_whitespace(std::string_view str) noexcept
321 [[nodiscard]]
inline constexpr std::size_t
terminal_width(std::string_view str) noexcept
323 auto width = std::size_t{0};
361 constexpr
line_iterator() noexcept : max_columns_{0}, line_break_byte_{0}, trailing_window_{} {}
371 str_{str}, max_columns_{
max_columns}, line_break_byte_{0}, trailing_window_{}
373 if (max_columns_ == 0) {
374 str_ = std::string_view{};
377 fill_trailing_window();
385 [[nodiscard]] constexpr std::size_t
max_columns() const noexcept {
return max_columns_; }
395 if (str_.empty() && other.str_.empty()) {
398 return (str_.data() == other.str_.data()) && (str_.size() == other.str_.size()) &&
399 (max_columns_ == other.max_columns_) && (line_break_byte_ == other.line_break_byte_);
409 return !(*
this == other);
418 return str_.substr(0, line_break_byte_);
440 constexpr
static auto trailing_window_size = std::size_t{AR_UTF8_TRAILING_WINDOW_SIZE};
444 auto result = line_break_class::any;
453 [[nodiscard]] constexpr
bool should_break(
line_break_class next_class) noexcept
455 for (
auto rule : no_break_rules::line_break<trailing_window_size>) {
456 if (rule(trailing_window_, next_class)) {
464 constexpr
void fill_trailing_window() noexcept
467 for (
auto& p : trailing_window_) {
468 p = line_break_class::any;
472 constexpr
void rotate_trailing_window() noexcept
475 auto it = trailing_window_.rbegin();
478 if (it == trailing_window_.rend()) {
485 constexpr
void consume() noexcept
492 if (line_break_byte_ != 0) {
493 str_.remove_prefix(line_break_byte_);
494 line_break_byte_ = 0;
497 auto bytes = std::size_t{0};
504 str_.remove_prefix(bytes);
513 auto column = std::size_t{0};
514 auto bytes = std::size_t{0};
515 auto line_break_column = std::size_t{0};
516 auto line_break_byte = std::size_t{0};
517 for (
auto it = code_point::iterator{str_}; it != code_point::iterator{}; ++it) {
520 if (column > max_columns_) {
521 if (line_break_column == 0) {
524 line_break_byte_ = bytes;
526 line_break_byte_ = line_break_byte;
539 rotate_trailing_window();
540 trailing_window_.front() = extract_class(*this_cp);
543 auto next_break_class = line_break_class::any;
547 if (next_it != code_point::iterator{}) {
550 next_break_class = extract_class(*next_cp);
555 if (should_break(next_break_class)) {
556 line_break_column = column;
557 line_break_byte = bytes;
562 line_break_byte_ = str_.size();
565 std::string_view str_;
566 std::size_t max_columns_;
567 std::size_t line_break_byte_;
568 std::array<line_break_class, trailing_window_size> trailing_window_;
constexpr static range_t range(std::string_view str) noexcept
constexpr static iterator end() noexcept
constexpr iterator begin() noexcept
std::string_view::difference_type difference_type
const value_type & reference
constexpr static range_t range(std::string_view str) noexcept
constexpr iterator(std::string_view str) noexcept
std::forward_iterator_tag iterator_category
constexpr iterator operator++(int) noexcept
std::string_view value_type
constexpr bool operator!=(iterator other) const noexcept
constexpr iterator & operator++() noexcept
constexpr bool operator==(iterator other) const noexcept
constexpr iterator() noexcept
const value_type * pointer
constexpr value_type operator*() const noexcept
constexpr value_type operator*() const noexcept
constexpr line_iterator(std::string_view str, std::size_t max_columns) noexcept
constexpr std::size_t max_columns() const noexcept
std::string_view::difference_type difference_type
constexpr bool operator==(line_iterator other) const noexcept
std::string_view value_type
constexpr line_iterator operator++(int) noexcept
const value_type & reference
const value_type * pointer
std::forward_iterator_tag iterator_category
constexpr line_iterator() noexcept
constexpr bool operator!=(line_iterator other) const noexcept
constexpr std::optional< type > decode(std::string_view str) noexcept
constexpr std::size_t size(std::string_view str) noexcept
constexpr std::size_t terminal_width(std::string_view str) noexcept
constexpr bool contains_whitespace(std::string_view str) noexcept
constexpr auto line_break_table
constexpr auto grapheme_cluster_break_table
constexpr auto zero_width_table
constexpr auto whitespace_table
grapheme_cluster_break_class
constexpr bool is_whitespace(std::string_view str) noexcept
constexpr std::size_t count(std::string_view str) noexcept
constexpr auto double_width_table