summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2015-03-10 19:33:46 +0000
committerMaxime Coste <frrrwww@gmail.com>2015-03-10 19:50:22 +0000
commit3c1a325b6f7c67c530d99aaaedf5f8c96f2b2de6 (patch)
treef6cdaf2eec33dee178e3c888f5120ea43479b157
parenta0cf75ec39c679776b28b178a4299cf0ad204a1c (diff)
Refactor String, use a common StringOps interface, hide std::string
-rw-r--r--src/buffer_utils.cc4
-rw-r--r--src/client.cc5
-rw-r--r--src/client.hh1
-rw-r--r--src/command_manager.cc4
-rw-r--r--src/commands.cc31
-rw-r--r--src/display_buffer.cc4
-rw-r--r--src/file.cc14
-rw-r--r--src/highlighters.cc9
-rw-r--r--src/hook_manager.cc2
-rw-r--r--src/id_map.hh2
-rw-r--r--src/input_handler.cc18
-rw-r--r--src/insert_completer.cc15
-rw-r--r--src/keys.cc6
-rw-r--r--src/main.cc24
-rw-r--r--src/ncurses_ui.cc2
-rw-r--r--src/normal.cc12
-rw-r--r--src/option_types.hh4
-rw-r--r--src/parameters_parser.cc8
-rw-r--r--src/regex.cc3
-rw-r--r--src/regex.hh16
-rw-r--r--src/register_manager.cc2
-rw-r--r--src/shell_manager.cc4
-rw-r--r--src/string.cc5
-rw-r--r--src/string.hh290
24 files changed, 232 insertions, 253 deletions
diff --git a/src/buffer_utils.cc b/src/buffer_utils.cc
index 88f7d4f8..eda4d9d4 100644
--- a/src/buffer_utils.cc
+++ b/src/buffer_utils.cc
@@ -53,7 +53,7 @@ Buffer* create_buffer_from_data(StringView data, StringView name,
const char* pos = data.begin();
if (data.length() >= 3 and
- data[0] == '\xEF' and data[1] == '\xBB' and data[2] == '\xBF')
+ data[0_byte] == '\xEF' and data[1_byte] == '\xBB' and data[2_byte] == '\xBF')
{
bom = true;
pos = data.begin() + 3;
@@ -81,7 +81,7 @@ Buffer* create_buffer_from_data(StringView data, StringView name,
if (buffer)
buffer->reload(std::move(lines), fs_timestamp);
else
- buffer = new Buffer{name, flags, std::move(lines), fs_timestamp};
+ buffer = new Buffer{name.str(), flags, std::move(lines), fs_timestamp};
OptionManager& options = buffer->options();
options.get_local_option("eolformat").set<String>(crlf ? "crlf" : "lf");
diff --git a/src/client.cc b/src/client.cc
index 74a9aff2..ae18ebe4 100644
--- a/src/client.cc
+++ b/src/client.cc
@@ -257,6 +257,11 @@ StringView Client::get_env_var(const String& name) const
return it->second;
}
+StringView Client::get_env_var(StringView name) const
+{
+ return get_env_var(name.str());
+}
+
void Client::on_option_changed(const Option& option)
{
if (option.name() == "ui_options")
diff --git a/src/client.hh b/src/client.hh
index 0f7eeb40..8a8c309f 100644
--- a/src/client.hh
+++ b/src/client.hh
@@ -51,6 +51,7 @@ public:
void change_buffer(Buffer& buffer);
StringView get_env_var(const String& name) const;
+ StringView get_env_var(StringView name) const;
private:
void on_option_changed(const Option& option) override;
diff --git a/src/command_manager.cc b/src/command_manager.cc
index 67e33c1e..459fcc22 100644
--- a/src/command_manager.cc
+++ b/src/command_manager.cc
@@ -119,7 +119,7 @@ String get_until_delimiter(StringView base, ByteCount& pos,
}
++pos;
}
- return base.substr(start, pos - start);
+ return base.substr(start, pos - start).str();
}
struct unknown_expand : parse_error
@@ -313,7 +313,7 @@ String eval_token(const Token& token, Context& context,
return ShellManager::instance().eval(content, context, shell_params,
env_vars);
case Token::Type::RegisterExpand:
- return context.main_sel_register_value(content);
+ return context.main_sel_register_value(content).str();
case Token::Type::OptionExpand:
return context.options()[content].get_as_string();
case Token::Type::ValExpand:
diff --git a/src/commands.cc b/src/commands.cc
index 08a9e3a6..97e19bd8 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -47,7 +47,7 @@ Buffer* open_fifo(StringView name, StringView filename, bool scroll)
if (fd < 0)
throw runtime_error("unable to open " + filename);
- return create_fifo_buffer(name, fd, scroll);
+ return create_fifo_buffer(name.str(), fd, scroll);
}
const PerArgumentCommandCompleter filename_completer({
@@ -69,9 +69,9 @@ static CandidateList complete_buffer_name(StringView prefix, ByteCount cursor_po
StringView match_name = name;
if (not include_dirs and buffer->flags() & Buffer::Flags::File)
{
- ByteCount pos = name.find_last_of('/');
- if (pos != (int)String::npos)
- match_name = name.substr(pos+1);
+ auto it = find(reversed(name), '/');
+ if (it != name.rend())
+ match_name = StringView{it.base() + 2, name.end()};
}
if (prefix_match(match_name, prefix))
prefix_result.push_back(name);
@@ -434,7 +434,7 @@ const CommandDesc namebuf_cmd = {
Completions complete_highlighter(const Context& context,
StringView arg, ByteCount pos_in_token, bool only_group)
{
- const bool shared = not arg.empty() and arg[0] == '/';
+ const bool shared = not arg.empty() and arg[0_byte] == '/';
if (shared)
{
auto& group = DefinedHighlighters::instance();
@@ -480,7 +480,7 @@ Highlighter& get_highlighter(const Context& context, StringView path)
throw runtime_error("group path should not be empty");
Highlighter* root = nullptr;
- if (path[0] == '/')
+ if (path[0_byte] == '/')
{
root = &DefinedHighlighters::instance();
path = path.substr(1_byte);
@@ -603,12 +603,12 @@ const CommandDesc add_hook_cmd = {
if (regex_match(param.begin(), param.end(), regex))
CommandManager::instance().execute(command, context, {},
- { { "hook_param", param } });
+ { { "hook_param", param.str() } });
};
StringView group;
if (parser.has_option("group"))
group = parser.option_value("group");
- get_scope(parser[0], context).hooks().add_hook(parser[1], group, hook_func);
+ get_scope(parser[0], context).hooks().add_hook(parser[1], group.str(), hook_func);
}
};
@@ -866,7 +866,7 @@ const CommandDesc debug_cmd = {
{
size_t count = domain_allocated_bytes[domain];
total += count;
- write_debug(" "_sv + domain_name((MemoryDomain)domain) + ": " + to_string(count));
+ write_debug(" "_str + domain_name((MemoryDomain)domain) + ": " + to_string(count));
}
write_debug(" Total: " + to_string(total));
#if defined(__GLIBC__) || defined(__CYGWIN__)
@@ -1254,7 +1254,7 @@ const CommandDesc prompt_cmd = {
{
if (params[1].length() != 1)
throw runtime_error("register name should be a single character");
- const char reg = params[1][0];
+ const char reg = params[1][0_byte];
const String& command = params[2];
String initstr;
@@ -1267,7 +1267,7 @@ const CommandDesc prompt_cmd = {
{
if (event != PromptEvent::Validate)
return;
- RegisterManager::instance()[reg] = ConstArrayView<String>(str);
+ RegisterManager::instance()[reg] = ConstArrayView<String>(str.str());
CommandManager::instance().execute(command, context);
});
@@ -1344,12 +1344,11 @@ const CommandDesc info_cmd = {
if (parser.has_option("anchor"))
{
auto anchor = parser.option_value("anchor");
- size_t dot = anchor.find_first_of('.');
- if (dot == String::npos)
+ auto dot = find(anchor, '.');
+ if (dot == anchor.end())
throw runtime_error("expected <line>.<column> for anchor");
- ByteCount dotb = (int)dot;
- ByteCoord coord{str_to_int(anchor.substr(0, dotb))-1,
- str_to_int(anchor.substr(dotb+1))-1};
+ ByteCoord coord{str_to_int({anchor.begin(), dot})-1,
+ str_to_int({dot+1, anchor.end()})-1};
pos = context.window().display_position(coord);
style = InfoStyle::Inline;
if (parser.has_option("placement"))
diff --git a/src/display_buffer.cc b/src/display_buffer.cc
index a56fe612..3bcf37b2 100644
--- a/src/display_buffer.cc
+++ b/src/display_buffer.cc
@@ -49,7 +49,7 @@ void DisplayAtom::trim_begin(CharCount count)
m_begin = utf8::advance(m_buffer->iterator_at(m_begin),
m_buffer->iterator_at(m_end), count).coord();
else
- m_text = m_text.substr(count);
+ m_text = m_text.substr(count).str();
check_invariant();
}
@@ -59,7 +59,7 @@ void DisplayAtom::trim_end(CharCount count)
m_end = utf8::advance(m_buffer->iterator_at(m_end),
m_buffer->iterator_at(m_begin), -count).coord();
else
- m_text = m_text.substr(0, m_text.char_length() - count);
+ m_text = m_text.substr(0, m_text.char_length() - count).str();
check_invariant();
}
diff --git a/src/file.cc b/src/file.cc
index a12b40ce..ec409df8 100644
--- a/src/file.cc
+++ b/src/file.cc
@@ -26,8 +26,8 @@ namespace Kakoune
String parse_filename(StringView filename)
{
- if (filename.length() >= 1 and filename[0] == '~' and
- (filename.length() == 1 or filename[1] == '/'))
+ if (filename.length() >= 1 and filename[0_byte] == '~' and
+ (filename.length() == 1 or filename[1_byte] == '/'))
return parse_filename("$HOME"_str + filename.substr(1_byte));
ByteCount pos = 0;
@@ -90,7 +90,7 @@ String real_path(StringView filename)
auto it = find(existing.rbegin(), existing.rend(), '/');
if (it == existing.rend())
- return filename;
+ return filename.str();
existing = StringView{existing.begin(), it.base()-1};
non_existing = StringView{it.base(), filename.end()};
@@ -105,7 +105,7 @@ String compact_path(StringView filename)
getcwd(cwd, 1024);
String real_cwd = real_path(cwd) + "/";
if (prefix_match(real_filename, real_cwd))
- return real_filename.substr(real_cwd.length());
+ return real_filename.substr(real_cwd.length()).str();
const char* home = getenv("HOME");
if (home)
@@ -258,14 +258,14 @@ void write_buffer_to_backup_file(Buffer& buffer)
String find_file(StringView filename, ConstArrayView<String> paths)
{
struct stat buf;
- if (filename.length() > 1 and filename[0] == '/')
+ if (filename.length() > 1 and filename[0_byte] == '/')
{
if (stat(filename.zstr(), &buf) == 0 and S_ISREG(buf.st_mode))
return filename.str();
return "";
}
if (filename.length() > 2 and
- filename[0] == '~' and filename[1] == '/')
+ filename[0_byte] == '~' and filename[1_byte] == '/')
{
String candidate = getenv("HOME") + filename.substr(1_byte).str();
if (stat(candidate.c_str(), &buf) == 0 and S_ISREG(buf.st_mode))
@@ -386,7 +386,7 @@ Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
Vector<String> res;
for (auto dir : split(getenv("PATH"), ':'))
{
- String dirname = dir;
+ String dirname = dir.str();
if (not dirname.empty() and dirname.back() != '/')
dirname += '/';
diff --git a/src/highlighters.cc b/src/highlighters.cc
index 3cd00a75..900835cf 100644
--- a/src/highlighters.cc
+++ b/src/highlighters.cc
@@ -264,9 +264,9 @@ public:
if (not regex_match(it->begin(), it->end(), res, face_spec_ex))
throw runtime_error("wrong face spec: '" + *it +
"' expected <capture>:<facespec>");
- get_face(res[2].str()); // throw if wrong face spec
- int capture = str_to_int(res[1].str());
- faces.emplace_back(capture, res[2].str());
+ get_face({res[2].first, res[2].second}); // throw if wrong face spec
+ int capture = str_to_int({res[1].first, res[1].second});
+ faces.emplace_back(capture, String{res[2].first, res[2].second});
}
String id = "hlregex'" + params[0] + "'";
@@ -711,7 +711,8 @@ void expand_unprintable(const Context& context, HighlightFlags flags, DisplayBuf
{
std::ostringstream oss;
oss << "U+" << std::hex << cp;
- String str = oss.str();
+ const auto& stdstr = oss.str();
+ String str{stdstr.begin(), stdstr.end()};
if (it.coord() != atom_it->begin())
atom_it = ++line.split(atom_it, it.coord());
if (next.coord() < atom_it->end())
diff --git a/src/hook_manager.cc b/src/hook_manager.cc
index cc4c1ec6..d7879c61 100644
--- a/src/hook_manager.cc
+++ b/src/hook_manager.cc
@@ -51,7 +51,7 @@ void HookManager::run_hook(StringView hook_name,
for (auto& hook : hook_list_it->second)
{
if (not hook.first.empty() and not disabled_hooks.empty() and
- regex_match(hook.first, disabled_hooks))
+ regex_match(hook.first.begin(), hook.first.end(), disabled_hooks))
continue;
try
diff --git a/src/id_map.hh b/src/id_map.hh
index e6f2f7b0..72d1c2f0 100644
--- a/src/id_map.hh
+++ b/src/id_map.hh
@@ -65,7 +65,7 @@ public:
if (it != m_content.end())
return it->second;
- append({ id, Value{} });
+ append({ id.str(), Value{} });
return (m_content.end()-1)->second;
}
diff --git a/src/input_handler.cc b/src/input_handler.cc
index 23717f88..1e6d0cad 100644
--- a/src/input_handler.cc
+++ b/src/input_handler.cc
@@ -154,7 +154,7 @@ public:
if (m_params.reg != '"')
{
atoms.push_back({ "; reg=", Face(Colors::Yellow) });
- atoms.push_back({ StringView(m_params.reg), Face(Colors::Green) });
+ atoms.push_back({ StringView(m_params.reg).str(), Face(Colors::Green) });
}
return atoms;
}
@@ -325,12 +325,12 @@ public:
m_display_pos = m_cursor_pos + 1 - width;
if (m_cursor_pos == m_line.char_length())
- return DisplayLine{{ {m_line.substr(m_display_pos, width-1), get_face("StatusLine")},
+ return DisplayLine{{ {m_line.substr(m_display_pos, width-1).str(), get_face("StatusLine")},
{" "_str, get_face("StatusCursor")} }};
else
- return DisplayLine({ { m_line.substr(m_display_pos, m_cursor_pos - m_display_pos), get_face("StatusLine") },
- { m_line.substr(m_cursor_pos,1), get_face("StatusCursor") },
- { m_line.substr(m_cursor_pos+1, width - m_cursor_pos + m_display_pos - 1), get_face("StatusLine") } });
+ return DisplayLine({ { m_line.substr(m_display_pos, m_cursor_pos - m_display_pos).str(), get_face("StatusLine") },
+ { m_line.substr(m_cursor_pos,1).str(), get_face("StatusCursor") },
+ { m_line.substr(m_cursor_pos+1, width - m_cursor_pos + m_display_pos - 1).str(), get_face("StatusLine") } });
}
private:
CharCount m_cursor_pos = 0;
@@ -473,7 +473,7 @@ String common_prefix(ConstArrayView<String> strings)
while (common_len < len and str[common_len] == res[common_len])
++common_len;
if (common_len != res.length())
- res = res.substr(0, common_len);
+ res = res.substr(0, common_len).str();
}
return res;
}
@@ -484,7 +484,7 @@ public:
Prompt(InputHandler& input_handler, StringView prompt,
String initstr, Face face, Completer completer,
PromptCallback callback)
- : InputMode(input_handler), m_prompt(prompt), m_prompt_face(face),
+ : InputMode(input_handler), m_prompt(prompt.str()), m_prompt_face(face),
m_completer(completer), m_callback(callback),
m_autoshowcompl{context().options()["autoshowcompl"].get<bool>()}
{
@@ -600,7 +600,7 @@ public:
String prefix = common_prefix(candidates);
if (m_completions.end - m_completions.start > prefix.length())
prefix = line.substr(m_completions.start,
- m_completions.end - m_completions.start);
+ m_completions.end - m_completions.start).str();
if (not prefix.empty())
{
@@ -742,7 +742,7 @@ private:
History::iterator it;
while ((it = find(history, entry)) != history.end())
history.erase(it);
- history.push_back(entry);
+ history.push_back(entry.str());
}
};
UnorderedMap<String, Prompt::History, MemoryDomain::History> Prompt::ms_history;
diff --git a/src/insert_completer.cc b/src/insert_completer.cc
index 45f9681f..5d76023d 100644
--- a/src/insert_completer.cc
+++ b/src/insert_completer.cc
@@ -119,7 +119,7 @@ InsertCompletion complete_word(const Buffer& buffer, ByteCoord cursor_pos)
ComplAndDescList result;
result.reserve(matches.size());
for (auto& m : matches)
- result.emplace_back(m, "");
+ result.emplace_back(m.str(), "");
return { begin.coord(), cursor_pos, std::move(result), buffer.timestamp() };
}
@@ -158,7 +158,7 @@ InsertCompletion complete_filename(const Buffer& buffer, ByteCoord cursor_pos,
if (not dir.empty() and dir.back() != '/')
dir += '/';
for (auto& filename : Kakoune::complete_filename(dir + prefix, Regex{}))
- res.emplace_back(filename.substr(dir.length()), "");
+ res.emplace_back(filename.substr(dir.length()).str(), "");
}
}
if (res.empty())
@@ -178,16 +178,17 @@ InsertCompletion complete_option(const Buffer& buffer, ByteCoord cursor_pos,
MatchResults<String::const_iterator> match;
if (regex_match(desc.begin(), desc.end(), match, re))
{
- ByteCoord coord{ str_to_int(match[1].str()) - 1, str_to_int(match[2].str()) - 1 };
+ ByteCoord coord{ str_to_int({match[1].first, match[1].second}) - 1,
+ str_to_int({match[2].first, match[2].second}) - 1 };
if (not buffer.is_valid(coord))
return {};
auto end = coord;
if (match[3].matched)
{
- ByteCount len = str_to_int(match[3].str());
+ ByteCount len = str_to_int({match[3].first, match[3].second});
end = buffer.advance(coord, len);
}
- size_t timestamp = (size_t)str_to_int(match[4].str());
+ size_t timestamp = (size_t)str_to_int({match[4].first, match[4].second});
auto changes = buffer.changes_since(timestamp);
if (find_if(changes, [&](const Buffer::Change& change){
return change.begin < coord;
@@ -204,7 +205,7 @@ InsertCompletion complete_option(const Buffer& buffer, ByteCoord cursor_pos,
{
auto splitted = split(*it, '@');
if (not splitted.empty() and prefix_match(splitted[0], prefix))
- res.emplace_back(splitted[0], splitted.size() > 1 ? splitted[1] : "");
+ res.emplace_back(splitted[0].str(), splitted.size() > 1 ? splitted[1].str() : "");
}
return { coord, end, std::move(res), timestamp };
}
@@ -222,7 +223,7 @@ InsertCompletion complete_line(const Buffer& buffer, ByteCoord cursor_pos)
continue;
ByteCount len = buffer[l].length();
if (len > cursor_pos.column and std::equal(prefix.begin(), prefix.end(), buffer[l].begin()))
- res.emplace_back(buffer[l].substr(0_byte, len-1), "");
+ res.emplace_back(buffer[l].substr(0_byte, len-1).str(), "");
}
if (res.empty())
return {};
diff --git a/src/keys.cc b/src/keys.cc
index b328252c..7dd45383 100644
--- a/src/keys.cc
+++ b/src/keys.cc
@@ -64,9 +64,9 @@ KeyList parse_keys(StringView str)
Key::Modifiers modifier = Key::Modifiers::None;
StringView desc{it.base()+1, end_it.base()};
- if (desc.length() > 2 and desc[1] == '-')
+ if (desc.length() > 2 and desc[1_byte] == '-')
{
- switch(tolower(desc[0]))
+ switch(tolower(desc[0_byte]))
{
case 'c': modifier = Key::Modifiers::Control; break;
case 'a': modifier = Key::Modifiers::Alt; break;
@@ -82,7 +82,7 @@ KeyList parse_keys(StringView str)
result.push_back(canonicalize_ifn({ modifier, name_it->key }));
else if (desc.char_length() == 1)
result.push_back(Key{ modifier, desc[0_char] });
- else if (tolower(desc[0]) == 'f' and desc.length() <= 3)
+ else if (tolower(desc[0_byte]) == 'f' and desc.length() <= 3)
{
int val = str_to_int(desc.substr(1_byte));
if (val >= 1 and val <= 12)
diff --git a/src/main.cc b/src/main.cc
index af77ba44..f022361d 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -37,10 +37,10 @@ void run_unit_tests();
String runtime_directory()
{
String bin_path = get_kak_binary_path();
- size_t last_slash = bin_path.find_last_of('/');
- if (last_slash == String::npos)
+ auto it = find(reversed(bin_path), '/');
+ if (it == bin_path.rend())
throw runtime_error("unable to determine runtime directory");
- return bin_path.substr(0_byte, (int)last_slash) + "/../share/kak";
+ return StringView{bin_path.begin(), it.base()-1} + "/../share/kak";
}
void register_env_vars()
@@ -54,7 +54,7 @@ void register_env_vars()
{ return context.buffer().display_name(); }
}, {
"buffile",
- [](StringView name, const Context& context) -> String
+ [](StringView name, const Context& context)
{ return context.buffer().name(); }
}, {
"buflist",
@@ -85,19 +85,19 @@ void register_env_vars()
{ return context.options()[name.substr(4_byte)].get_as_string(); }
}, {
"reg_.+",
- [](StringView name, const Context& context) -> String
- { return context.main_sel_register_value(name.substr(4_byte)); }
+ [](StringView name, const Context& context)
+ { return context.main_sel_register_value(name.substr(4_byte)).str(); }
}, {
"client_env_.+",
- [](StringView name, const Context& context) -> String
- { return context.client().get_env_var(name.substr(11_byte)); }
+ [](StringView name, const Context& context)
+ { return context.client().get_env_var(name.substr(11_byte)).str(); }
}, {
"session",
- [](StringView name, const Context& context) -> String
+ [](StringView name, const Context& context)
{ return Server::instance().session(); }
}, {
"client",
- [](StringView name, const Context& context) -> String
+ [](StringView name, const Context& context)
{ return context.name(); }
}, {
"cursor_line",
@@ -356,7 +356,7 @@ int run_server(StringView session, StringView init_command,
write_debug("*** This is the debug buffer, where debug info will be written ***");
- Server server(session.empty() ? to_string(getpid()) : String{session});
+ Server server(session.empty() ? to_string(getpid()) : session.str());
if (not ignore_kakrc) try
{
@@ -385,7 +385,7 @@ int run_server(StringView session, StringView init_command,
for (auto& file : reversed(files))
{
if (not create_buffer_from_file(file))
- new Buffer(file, Buffer::Flags::New | Buffer::Flags::File);
+ new Buffer(file.str(), Buffer::Flags::New | Buffer::Flags::File);
}
}
catch (Kakoune::runtime_error& error)
diff --git a/src/ncurses_ui.cc b/src/ncurses_ui.cc
index 9e401985..13de9fd2 100644
--- a/src/ncurses_ui.cc
+++ b/src/ncurses_ui.cc
@@ -591,7 +591,7 @@ void NCursesUI::menu_show(ConstArrayView<String> items,
const CharCount maxlen = min((int)maxsize.column-2, 200);
for (auto& item : items)
{
- m_items.push_back(item.substr(0_char, maxlen));
+ m_items.push_back(item.substr(0_char, maxlen).str());
longest = max(longest, m_items.back().char_length());
}
longest += 1;
diff --git a/src/normal.cc b/src/normal.cc
index 8893b8f5..4d16bad0 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -375,7 +375,7 @@ void pipe(Context& context, NormalParams)
real_cmd = context.main_sel_register_value("|");
else
{
- RegisterManager::instance()['|'] = String{cmdline};
+ RegisterManager::instance()['|'] = cmdline.str();
real_cmd = cmdline;
}
@@ -397,7 +397,7 @@ void pipe(Context& context, NormalParams)
{}, EnvVarMap{});
if ((insert_eol or sel.max() == buffer.back_coord()) and
str.back() == '\n')
- str = str.substr(0, str.length()-1);
+ str = str.substr(0, str.length()-1).str();
strings.push_back(std::move(str));
}
ScopedEdition edition(context);
@@ -428,7 +428,7 @@ void insert_output(Context& context, NormalParams)
real_cmd = context.main_sel_register_value("|");
else
{
- RegisterManager::instance()['|'] = String{cmdline};
+ RegisterManager::instance()['|'] = cmdline.str();
real_cmd = cmdline;
}
@@ -617,7 +617,7 @@ void search(Context& context, NormalParams)
if (ex.empty())
ex = Regex{context.main_sel_register_value("/").str()};
else if (event == PromptEvent::Validate)
- RegisterManager::instance()['/'] = String{ex.str()};
+ RegisterManager::instance()['/'] = ex.str();
if (not ex.empty() and not ex.str().empty())
select_next_match<direction, mode>(context.buffer(), context.selections(), ex);
});
@@ -674,7 +674,7 @@ void select_regex(Context& context, NormalParams)
if (ex.empty())
ex = Regex{context.main_sel_register_value("/").str()};
else if (event == PromptEvent::Validate)
- RegisterManager::instance()['/'] = String{ex.str()};
+ RegisterManager::instance()['/'] = ex.str();
if (not ex.empty() and not ex.str().empty())
select_all_matches(context.selections(), ex);
});
@@ -686,7 +686,7 @@ void split_regex(Context& context, NormalParams)
if (ex.empty())
ex = Regex{context.main_sel_register_value("/").str()};
else if (event == PromptEvent::Validate)
- RegisterManager::instance()['/'] = String{ex.str()};
+ RegisterManager::instance()['/'] = ex.str();
if (not ex.empty() and not ex.str().empty())
split_selections(context.selections(), ex);
});
diff --git a/src/option_types.hh b/src/option_types.hh
index ef611ae4..0f204b70 100644
--- a/src/option_types.hh
+++ b/src/option_types.hh
@@ -14,8 +14,8 @@
namespace Kakoune
{
-inline String option_to_string(StringView opt) { return opt; }
-inline void option_from_string(StringView str, String& opt) { opt = str; }
+inline String option_to_string(StringView opt) { return opt.str(); }
+inline void option_from_string(StringView str, String& opt) { opt = str.str(); }
inline String option_to_string(int opt) { return to_string(opt); }
inline void option_from_string(StringView str, int& opt) { opt = str_to_int(str); }
diff --git a/src/parameters_parser.cc b/src/parameters_parser.cc
index 06c081e0..e86d7101 100644
--- a/src/parameters_parser.cc
+++ b/src/parameters_parser.cc
@@ -21,7 +21,7 @@ ParametersParser::ParametersParser(ParameterList params,
{
if (not only_pos and params[i] == "--")
only_pos = true;
- else if (not only_pos and params[i][0] == '-')
+ else if (not only_pos and params[i][0_byte] == '-')
{
auto it = m_desc.switches.find(params[i].substr(1_byte));
if (it == m_desc.switches.end())
@@ -30,7 +30,7 @@ ParametersParser::ParametersParser(ParameterList params,
if (it->second.takes_arg)
{
++i;
- if (i == params.size() or params[i][0] == '-')
+ if (i == params.size() or params[i][0_byte] == '-')
throw missing_option_value(it->first);
}
}
@@ -51,7 +51,7 @@ bool ParametersParser::has_option(const String& name) const
kak_assert(m_desc.switches.find(name) != m_desc.switches.end());
for (auto& param : m_params)
{
- if (param[0] == '-' and param.substr(1_byte) == name)
+ if (param[0_byte] == '-' and param.substr(1_byte) == name)
return true;
if (param == "--")
@@ -70,7 +70,7 @@ const String& ParametersParser::option_value(const String& name) const
for (size_t i = 0; i < m_params.size(); ++i)
{
- if (m_params[i][0] == '-' and m_params[i].substr(1_byte) == name)
+ if (m_params[i][0_byte] == '-' and m_params[i].substr(1_byte) == name)
return m_params[i+1];
if (m_params[i] == "--")
diff --git a/src/regex.cc b/src/regex.cc
index d2c8f615..23916036 100644
--- a/src/regex.cc
+++ b/src/regex.cc
@@ -7,7 +7,8 @@ namespace Kakoune
String option_to_string(const Regex& re)
{
- return String{re.str()};
+ const auto& str = re.str();
+ return String{str.begin(), str.end()};
}
void option_from_string(StringView str, Regex& re)
diff --git a/src/regex.hh b/src/regex.hh
index aa71f669..8d87427e 100644
--- a/src/regex.hh
+++ b/src/regex.hh
@@ -29,15 +29,27 @@ struct Regex : std::regex
bool operator==(const Regex& other) { return m_str == other.m_str; }
bool operator!=(const Regex& other) { return m_str != other.m_str; }
- StringView str() const { return m_str; }
+ const String& str() const { return m_str; }
private:
String m_str;
};
namespace regex_ns = std;
#else
+struct Regex : boost::regex
+{
+ Regex() = default;
+
+ explicit Regex(StringView re, flag_type flags = ECMAScript)
+ : boost::regex(re.begin(), re.end(), flags) {}
+
+ template<typename Iterator>
+ Regex(Iterator begin, Iterator end, flag_type flags = ECMAScript)
+ : boost::regex(begin, end, flags) {}
+
+ String str() const { auto s = boost::regex::str(); return {s.begin(), s.end()}; }
+};
namespace regex_ns = boost;
-using Regex = boost::regex;
#endif
template<typename Iterator>
diff --git a/src/register_manager.cc b/src/register_manager.cc
index 7a071ae3..7990c13b 100644
--- a/src/register_manager.cc
+++ b/src/register_manager.cc
@@ -59,7 +59,7 @@ private:
Register& RegisterManager::operator[](StringView reg)
{
if (reg.length() == 1)
- return (*this)[reg[0]];
+ return (*this)[reg[0_byte]];
static const IdMap<Codepoint> reg_names = {
{ "slash", '/' },
diff --git a/src/shell_manager.cc b/src/shell_manager.cc
index d10c4ad5..6b82ba91 100644
--- a/src/shell_manager.cc
+++ b/src/shell_manager.cc
@@ -23,7 +23,7 @@ ShellManager::ShellManager()
new_path = path + ":"_str;
String kak_path = get_kak_binary_path();
- StringView kak_dir = kak_path.substr(0_byte, (int)kak_path.find_last_of('/'));
+ StringView kak_dir{kak_path.begin(), find(reversed(kak_path), '/').base()-1};
new_path += kak_dir;
setenv("PATH", new_path.c_str(), 1);
}
@@ -111,7 +111,7 @@ String ShellManager::pipe(StringView input,
StringView name = StringView(match[1].first, match[1].second);
kak_assert(name.length() > 0);
- auto local_var = env_vars.find(name);
+ auto local_var = env_vars.find(name.str());
if (local_var != env_vars.end())
setenv(("kak_" + name).c_str(), local_var->second.c_str(), 1);
else
diff --git a/src/string.cc b/src/string.cc
index beeb4a74..5da03901 100644
--- a/src/string.cc
+++ b/src/string.cc
@@ -9,11 +9,6 @@
namespace Kakoune
{
-bool operator<(StringView lhs, StringView rhs)
-{
- return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
-}
-
Vector<String> split(StringView str, char separator, char escape)
{
Vector<String> res;
diff --git a/src/string.hh b/src/string.hh
index 74df3fd7..4fb24c1e 100644
--- a/src/string.hh
+++ b/src/string.hh
@@ -14,56 +14,133 @@ namespace Kakoune
class StringView;
-using StringBase = std::basic_string<char, std::char_traits<char>,
- Allocator<char, MemoryDomain::String>>;
-
-constexpr ByteCount strlen(const char* s)
+template<typename Type, typename CharType>
+class StringOps
{
- return *s == 0 ? 0 : strlen(s+1) + 1;
-}
+public:
+ using value_type = CharType;
+
+ friend bool operator==(const Type& lhs, const Type& rhs)
+ {
+ return lhs.length() == rhs.length() and
+ std::equal(lhs.begin(), lhs.end(), rhs.begin());
+ }
+
+ friend bool operator!=(const Type& lhs, const Type& rhs)
+ {
+ return lhs.length() != rhs.length() or
+ not std::equal(lhs.begin(), lhs.end(), rhs.begin());
+ }
+
+ friend bool operator<(const Type& lhs, const Type& rhs)
+ {
+ return std::lexicographical_compare(lhs.begin(), lhs.end(),
+ rhs.begin(), rhs.end());
+ }
+
+ friend inline size_t hash_value(const Type& str)
+ {
+ return hash_data(str.data(), (int)str.length());
+ }
+
+ using iterator = CharType*;
+ using const_iterator = const CharType*;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ [[gnu::always_inline]]
+ iterator begin() { return type().data(); }
+
+ [[gnu::always_inline]]
+ const_iterator begin() const { return type().data(); }
+
+ [[gnu::always_inline]]
+ iterator end() { return type().data() + (int)type().length(); }
+
+ [[gnu::always_inline]]
+ const_iterator end() const { return type().data() + (int)type().length(); }
+
+ reverse_iterator rbegin() { return reverse_iterator{end()}; }
+ const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; }
+
+ reverse_iterator rend() { return reverse_iterator{begin()}; }
+ const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; }
+
+ CharType& front() { return *type().data(); }
+ const CharType& front() const { return *type().data(); }
+ CharType& back() { return type().data()[(int)type().length() - 1]; }
+ const CharType& back() const { return type().data()[(int)type().length() - 1]; }
+
+ [[gnu::always_inline]]
+ CharType& operator[](ByteCount pos) { return type().data()[(int)pos]; }
+
+ [[gnu::always_inline]]
+ const CharType& operator[](ByteCount pos) const
+ { return type().data()[(int)pos]; }
-class String : public StringBase
+ Codepoint operator[](CharCount pos) const
+ { return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); }
+
+ CharCount char_length() const { return utf8::distance(begin(), end()); }
+
+ [[gnu::always_inline]]
+ bool empty() const { return type().length() == 0_byte; }
+
+ ByteCount byte_count_to(CharCount count) const
+ { return utf8::advance(begin(), end(), (int)count) - begin(); }
+
+ CharCount char_count_to(ByteCount count) const
+ { return utf8::distance(begin(), begin() + (int)count); }
+
+ StringView substr(ByteCount from, ByteCount length = INT_MAX) const;
+ StringView substr(CharCount from, CharCount length = INT_MAX) const;
+
+private:
+ Type& type() { return *static_cast<Type*>(this); }
+ const Type& type() const { return *static_cast<const Type*>(this); }
+};
+
+class String : public StringOps<String, char>
{
public:
+ using Content = std::basic_string<char, std::char_traits<char>,
+ Allocator<char, MemoryDomain::String>>;
+
String() {}
- String(const char* content) : StringBase(content) {}
- String(StringBase content) : StringBase(std::move(content)) {}
- template<typename Char, typename Traits, typename Alloc>
- String(const std::basic_string<Char, Traits, Alloc>& content) : StringBase(content.begin(), content.end()) {}
- explicit String(char content, CharCount count = 1) : StringBase((size_t)(int)count, content) {}
+ String(const char* content) : m_data(content) {}
+ String(Content content) : m_data(std::move(content)) {}
+ explicit String(char content, CharCount count = 1) : m_data((size_t)(int)count, content) {}
explicit String(Codepoint cp, CharCount count = 1)
{
while (count-- > 0)
- utf8::dump(back_inserter(*this), cp);
+ utf8::dump(std::back_inserter(*this), cp);
}
template<typename Iterator>
- String(Iterator begin, Iterator end) : StringBase(begin, end) {}
+ String(Iterator begin, Iterator end) : m_data(begin, end) {}
- StringBase& stdstr() { return *this; }
- const StringBase& stdstr() const { return *this; }
+ [[gnu::always_inline]]
+ char* data() { return &m_data[0]; }
[[gnu::always_inline]]
- char operator[](ByteCount pos) const { return StringBase::operator[]((int)pos); }
+ const char* data() const { return m_data.data(); }
+
[[gnu::always_inline]]
- char& operator[](ByteCount pos) { return StringBase::operator[]((int)pos); }
- Codepoint operator[](CharCount pos) { return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); }
+ ByteCount length() const { return ByteCount{(int)m_data.length()}; }
[[gnu::always_inline]]
- ByteCount length() const { return ByteCount{(int)StringBase::length()}; }
- CharCount char_length() const { return utf8::distance(begin(), end()); }
- ByteCount byte_count_to(CharCount count) const { return utf8::advance(begin(), end(), (int)count) - begin(); }
- CharCount char_count_to(ByteCount count) const { return utf8::distance(begin(), begin() + (int)count); }
+ const char* c_str() const { return m_data.c_str(); }
+
+ void append(const char* data, ByteCount count) { m_data.append(data, (size_t)(int)count); }
- String& operator+=(const String& other) { StringBase::operator+=(other); return *this; }
- String& operator+=(const char* other) { StringBase::operator+=(other); return *this; }
- String& operator+=(char other) { StringBase::operator+=(other); return *this; }
- String& operator+=(Codepoint cp) { utf8::dump(back_inserter(*this), cp); return *this; }
+ void push_back(char c) { m_data.push_back(c); }
+ void resize(ByteCount size) { m_data.resize((size_t)(int)size); }
+ void reserve(ByteCount size) { m_data.reserve((size_t)(int)size); }
- StringView substr(ByteCount pos, ByteCount length = INT_MAX) const;
- StringView substr(CharCount pos, CharCount length = INT_MAX) const;
+private:
+ Content m_data;
};
-class StringView
+class StringView : public StringOps<StringView, const char>
{
public:
constexpr StringView() : m_data{nullptr}, m_length{0} {}
@@ -71,50 +148,17 @@ public:
: m_data{data}, m_length{length} {}
constexpr StringView(const char* data) : m_data{data}, m_length{strlen(data)} {}
constexpr StringView(const char* begin, const char* end) : m_data{begin}, m_length{(int)(end - begin)} {}
- template<typename Char, typename Traits, typename Alloc>
- StringView(const std::basic_string<Char, Traits, Alloc>& str) : m_data{str.data()}, m_length{(int)str.length()} {}
+ StringView(const String& str) : m_data{str.data()}, m_length{(int)str.length()} {}
StringView(const char& c) : m_data(&c), m_length(1) {}
- friend bool operator==(StringView lhs, StringView rhs);
-
[[gnu::always_inline]]
const char* data() const { return m_data; }
- using iterator = const char*;
- using reverse_iterator = std::reverse_iterator<const char*>;
-
- [[gnu::always_inline]]
- iterator begin() const { return m_data; }
- [[gnu::always_inline]]
- iterator end() const { return m_data + (int)m_length; }
-
- reverse_iterator rbegin() const { return reverse_iterator{m_data + (int)m_length}; }
- reverse_iterator rend() const { return reverse_iterator{m_data}; }
-
- char front() const { return *m_data; }
- char back() const { return m_data[(int)m_length - 1]; }
-
- [[gnu::always_inline]]
- char operator[](ByteCount pos) const { return m_data[(int)pos]; }
- Codepoint operator[](CharCount pos) { return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); }
-
[[gnu::always_inline]]
ByteCount length() const { return m_length; }
- CharCount char_length() const { return utf8::distance(begin(), end()); }
-
- [[gnu::always_inline]]
- bool empty() { return m_length == 0_byte; }
-
- ByteCount byte_count_to(CharCount count) const;
- CharCount char_count_to(ByteCount count) const;
-
- StringView substr(ByteCount from, ByteCount length = INT_MAX) const;
- StringView substr(CharCount from, CharCount length = INT_MAX) const;
String str() const { return String{begin(), end()}; }
- operator String() const { return str(); } // to remove
-
struct ZeroTerminatedString
{
ZeroTerminatedString(const char* begin, const char* end)
@@ -122,53 +166,37 @@ public:
if (*end == '\0')
unowned = begin;
else
- owned = StringBase(begin, end);
+ owned = String::Content(begin, end);
}
operator const char*() const { return unowned ? unowned : owned.c_str(); }
private:
- StringBase owned;
+ String::Content owned;
const char* unowned = nullptr;
};
ZeroTerminatedString zstr() const { return ZeroTerminatedString{begin(), end()}; }
private:
+ static constexpr ByteCount strlen(const char* s)
+ {
+ return *s == 0 ? 0 : strlen(s+1) + 1;
+ }
+
const char* m_data;
ByteCount m_length;
};
-inline bool operator==(StringView lhs, StringView rhs)
-{
- return lhs.m_length == rhs.m_length and
- std::equal(lhs.begin(), lhs.end(), rhs.begin());
-}
-
-inline bool operator!=(StringView lhs, StringView rhs)
-{
- return not (lhs == rhs);
-}
-
-bool operator<(StringView lhs, StringView rhs);
-
-inline ByteCount StringView::byte_count_to(CharCount count) const
-{
- return utf8::advance(begin(), end(), (int)count) - begin();
-}
-
-inline CharCount StringView::char_count_to(ByteCount count) const
-{
- return utf8::distance(begin(), begin() + (int)count);
-}
-
-inline StringView StringView::substr(ByteCount from, ByteCount length) const
+template<typename Type, typename CharType>
+inline StringView StringOps<Type, CharType>::substr(ByteCount from, ByteCount length) const
{
if (length < 0)
length = INT_MAX;
- return StringView{ m_data + (int)from, std::min(m_length - from, length) };
+ return StringView{ type().data() + (int)from, std::min(type().length() - from, length) };
}
-inline StringView StringView::substr(CharCount from, CharCount length) const
+template<typename Type, typename CharType>
+inline StringView StringOps<Type, CharType>::substr(CharCount from, CharCount length) const
{
if (length < 0)
length = INT_MAX;
@@ -176,70 +204,21 @@ inline StringView StringView::substr(CharCount from, CharCount length) const
return StringView{ beg, utf8::advance(beg, end(), length) };
}
-inline StringView String::substr(ByteCount pos, ByteCount length) const
-{
- return StringView{*this}.substr(pos, length);
-}
-
-inline StringView String::substr(CharCount pos, CharCount length) const
-{
- return StringView{*this}.substr(pos, length);
-}
-
inline String& operator+=(String& lhs, StringView rhs)
{
- lhs.append(rhs.data(), (size_t)(int)rhs.length());
+ lhs.append(rhs.data(), rhs.length());
return lhs;
}
-inline String operator+(const String& lhs, const String& rhs)
-{
- String res = lhs;
- res += rhs;
- return res;
-}
-
inline String operator+(StringView lhs, StringView rhs)
{
- String res{lhs.begin(), lhs.end()};
- res += rhs;
- return res;
-}
-
-inline String operator+(const String& lhs, StringView rhs)
-{
- String res = lhs;
+ String res;
+ res.reserve((int)(lhs.length() + rhs.length()));
+ res += lhs;
res += rhs;
return res;
}
-inline String operator+(StringView lhs, const String& rhs)
-{
- String res{lhs.begin(), lhs.end()};
- res.append(rhs);
- return res;
-}
-
-inline String operator+(const char* lhs, StringView rhs)
-{
- return StringView{lhs} + rhs;
-}
-
-inline String operator+(StringView lhs, const char* rhs)
-{
- return lhs + StringView{rhs};
-}
-
-inline String operator+(const char* lhs, const String& rhs)
-{
- return StringView{lhs} + rhs;
-}
-
-inline String operator+(const String& lhs, const char* rhs)
-{
- return lhs + StringView{rhs};
-}
-
Vector<String> split(StringView str, char separator, char escape);
Vector<StringView> split(StringView str, char separator);
@@ -266,16 +245,11 @@ inline String operator"" _str(const char* str, size_t)
return String(str);
}
-inline StringView operator"" _sv(const char* str, size_t len)
-{
- return StringView(str, (int)len);
-}
-
inline String codepoint_to_str(Codepoint cp)
{
- StringBase str;
- utf8::dump(back_inserter(str), cp);
- return String(str);
+ String str;
+ utf8::dump(std::back_inserter(str), cp);
+ return str;
}
int str_to_int(StringView str);
@@ -301,16 +275,6 @@ String expand_tabs(StringView line, CharCount tabstop, CharCount col = 0);
Vector<StringView> wrap_lines(StringView text, CharCount max_width);
-inline size_t hash_value(const Kakoune::String& str)
-{
- return hash_data(str.data(), (int)str.length());
-}
-
-inline size_t hash_value(const Kakoune::StringView& str)
-{
- return hash_data(str.data(), (int)str.length());
-}
-
}
#endif // string_hh_INCLUDED