summaryrefslogtreecommitdiffstats
path: root/src/base/intern_string.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-07 04:48:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-07 04:48:35 +0000
commit207df6fc406e81bfeebdff7f404bd242ff3f099f (patch)
treea1a796b056909dd0a04ffec163db9363a8757808 /src/base/intern_string.cc
parentReleasing progress-linux version 0.11.2-1~progress7.99u1. (diff)
downloadlnav-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.cc166
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;
+}