diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-07 04:48:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-07 04:48:35 +0000 |
commit | 207df6fc406e81bfeebdff7f404bd242ff3f099f (patch) | |
tree | a1a796b056909dd0a04ffec163db9363a8757808 /src/base/intern_string.cc | |
parent | Releasing progress-linux version 0.11.2-1~progress7.99u1. (diff) | |
download | lnav-207df6fc406e81bfeebdff7f404bd242ff3f099f.tar.xz lnav-207df6fc406e81bfeebdff7f404bd242ff3f099f.zip |
Merging upstream version 0.12.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/base/intern_string.cc')
-rw-r--r-- | src/base/intern_string.cc | 166 |
1 files changed, 165 insertions, 1 deletions
diff --git a/src/base/intern_string.cc b/src/base/intern_string.cc index 676d2bc..010da52 100644 --- a/src/base/intern_string.cc +++ b/src/base/intern_string.cc @@ -37,6 +37,7 @@ #include "config.h" #include "pcrepp/pcre2pp.hh" +#include "ww898/cp_utf8.hpp" #include "xxHash/xxhash.h" const static int TABLE_SIZE = 4095; @@ -224,7 +225,9 @@ string_fragment::split_lines() const start = index + 1; } } - retval.emplace_back(this->sf_string, start, this->sf_end); + if (retval.empty() || start < this->sf_end) { + retval.emplace_back(this->sf_string, start, this->sf_end); + } return retval; } @@ -301,3 +304,164 @@ string_fragment::to_string_with_case_style(case_style style) const return retval; } + +std::string +string_fragment::to_unquoted_string() const +{ + auto sub_sf = *this; + + if (sub_sf.startswith("r") || sub_sf.startswith("u")) { + sub_sf = sub_sf.consume_n(1).value(); + } + if (sub_sf.length() >= 2 + && ((sub_sf.startswith("\"") && sub_sf.endswith("\"")) + || (sub_sf.startswith("'") && sub_sf.endswith("'")))) + { + std::string retval; + + sub_sf.sf_begin += 1; + sub_sf.sf_end -= 1; + retval.reserve(this->length()); + + auto in_escape = false; + for (auto ch : sub_sf) { + if (in_escape) { + switch (ch) { + case 'n': + retval.push_back('\n'); + break; + case 't': + retval.push_back('\t'); + break; + case 'r': + retval.push_back('\r'); + break; + default: + retval.push_back(ch); + break; + } + in_escape = false; + } else if (ch == '\\') { + in_escape = true; + } else { + retval.push_back(ch); + } + } + + return retval; + } + + return this->to_string(); +} + +uint32_t +string_fragment::front_codepoint() const +{ + size_t index = 0; + auto read_res = ww898::utf::utf8::read( + [this, &index]() { return this->data()[index++]; }); + if (read_res.isErr()) { + return this->data()[0]; + } + return read_res.unwrap(); +} + +Result<ssize_t, const char*> +string_fragment::codepoint_to_byte_index(ssize_t cp_index) const +{ + ssize_t retval = 0; + + while (cp_index > 0) { + if (retval >= this->length()) { + return Err("index is beyond the end of the string"); + } + auto ch_len = TRY(ww898::utf::utf8::char_size([this, retval]() { + return std::make_pair(this->data()[retval], + this->length() - retval - 1); + })); + + retval += ch_len; + cp_index -= 1; + } + + return Ok(retval); +} + +string_fragment +string_fragment::sub_cell_range(int cell_start, int cell_end) const +{ + int byte_index = this->sf_begin; + nonstd::optional<int> byte_start; + nonstd::optional<int> byte_end; + int cell_index = 0; + + while (byte_index < this->sf_end) { + if (cell_start == cell_index) { + byte_start = byte_index; + } + if (!byte_end && cell_index >= cell_end) { + byte_end = byte_index; + break; + } + auto read_res = ww898::utf::utf8::read( + [this, &byte_index]() { return this->sf_string[byte_index++]; }); + if (read_res.isErr()) { + byte_index += 1; + } else { + auto ch = read_res.unwrap(); + + switch (ch) { + case '\t': + do { + cell_index += 1; + } while (cell_index % 8); + break; + default: + cell_index += wcwidth(read_res.unwrap()); + break; + } + } + } + if (cell_start == cell_index) { + byte_start = byte_index; + } + if (!byte_end) { + byte_end = byte_index; + } + + if (byte_start && byte_end) { + return this->sub_range(byte_start.value(), byte_end.value()); + } + + return string_fragment{}; +} + +size_t +string_fragment::column_width() const +{ + auto index = this->sf_begin; + size_t retval = 0; + + while (index < this->sf_end) { + auto read_res = ww898::utf::utf8::read( + [this, &index]() { return this->sf_string[index++]; }); + if (read_res.isErr()) { + retval += 1; + } else { + auto ch = read_res.unwrap(); + + switch (ch) { + case '\t': + do { + retval += 1; + } while (retval % 8); + break; + default: + retval += wcwidth(read_res.unwrap()); + break; + } + } + } + + return retval; +} |