Refactor String, use a common StringOps interface, hide std::string

This commit is contained in:
Maxime Coste 2015-03-10 19:33:46 +00:00
parent a0cf75ec39
commit 3c1a325b6f
24 changed files with 236 additions and 257 deletions

View File

@ -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");

View File

@ -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")

View File

@ -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;

View File

@ -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:

View File

@ -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"))

View File

@ -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();
}

View File

@ -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 += '/';

View File

@ -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())

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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 {};

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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);
});

View File

@ -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); }

View File

@ -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] == "--")

View File

@ -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)

View File

@ -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>

View File

@ -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", '/' },

View File

@ -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

View File

@ -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;

View File

@ -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)
{
return *s == 0 ? 0 : strlen(s+1) + 1;
}
class String : public StringBase
template<typename Type, typename CharType>
class StringOps
{
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]; }
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) {}
StringBase& stdstr() { return *this; }
const StringBase& stdstr() const { return *this; }
String(Iterator begin, Iterator end) : m_data(begin, end) {}
[[gnu::always_inline]]
char operator[](ByteCount pos) const { return StringBase::operator[]((int)pos); }
[[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()); }
char* data() { return &m_data[0]; }
[[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* data() const { return m_data.data(); }
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; }
[[gnu::always_inline]]
ByteCount length() const { return ByteCount{(int)m_data.length()}; }
StringView substr(ByteCount pos, ByteCount length = INT_MAX) const;
StringView substr(CharCount pos, CharCount length = INT_MAX) const;
[[gnu::always_inline]]
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); }
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); }
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()};
String res;
res.reserve((int)(lhs.length() + rhs.length()));
res += lhs;
res += rhs;
return res;
}
inline String operator+(const String& lhs, StringView rhs)
{
String 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