use more string_view in utils
there's a couple places that can be easily converted from using strings to using string_views instead. gives a slight (~1%) boost to system eval. # before nix eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' Time (mean ± σ): 2.946 s ± 0.026 s [User: 2.655 s, System: 0.209 s] Range (min … max): 2.905 s … 2.995 s 20 runs # after Time (mean ± σ): 2.928 s ± 0.024 s [User: 2.638 s, System: 0.211 s] Range (min … max): 2.893 s … 2.970 s 20 runs
This commit is contained in:
parent
e61c4bc25a
commit
44c92a1667
|
@ -22,6 +22,7 @@ typedef std::map<string, string> StringMap;
|
||||||
/* Paths are just strings. */
|
/* Paths are just strings. */
|
||||||
|
|
||||||
typedef string Path;
|
typedef string Path;
|
||||||
|
typedef std::string_view PathView;
|
||||||
typedef list<Path> Paths;
|
typedef list<Path> Paths;
|
||||||
typedef set<Path> PathSet;
|
typedef set<Path> PathSet;
|
||||||
|
|
||||||
|
|
|
@ -106,16 +106,16 @@ Path absPath(Path path, std::optional<Path> dir, bool resolveSymlinks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path canonPath(const Path & path, bool resolveSymlinks)
|
Path canonPath(PathView path, bool resolveSymlinks)
|
||||||
{
|
{
|
||||||
assert(path != "");
|
assert(path != "");
|
||||||
|
|
||||||
string s;
|
string s;
|
||||||
|
s.reserve(256);
|
||||||
|
|
||||||
if (path[0] != '/')
|
if (path[0] != '/')
|
||||||
throw Error("not an absolute path: '%1%'", path);
|
throw Error("not an absolute path: '%1%'", path);
|
||||||
|
|
||||||
string::const_iterator i = path.begin(), end = path.end();
|
|
||||||
string temp;
|
string temp;
|
||||||
|
|
||||||
/* Count the number of times we follow a symlink and stop at some
|
/* Count the number of times we follow a symlink and stop at some
|
||||||
|
@ -125,33 +125,37 @@ Path canonPath(const Path & path, bool resolveSymlinks)
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
/* Skip slashes. */
|
/* Skip slashes. */
|
||||||
while (i != end && *i == '/') i++;
|
while (!path.empty() && path[0] == '/') path.remove_prefix(1);
|
||||||
if (i == end) break;
|
if (path.empty()) break;
|
||||||
|
|
||||||
/* Ignore `.'. */
|
/* Ignore `.'. */
|
||||||
if (*i == '.' && (i + 1 == end || i[1] == '/'))
|
if (path == "." || path.substr(0, 2) == "./")
|
||||||
i++;
|
path.remove_prefix(1);
|
||||||
|
|
||||||
/* If `..', delete the last component. */
|
/* If `..', delete the last component. */
|
||||||
else if (*i == '.' && i + 1 < end && i[1] == '.' &&
|
else if (path == ".." || path.substr(0, 3) == "../")
|
||||||
(i + 2 == end || i[2] == '/'))
|
|
||||||
{
|
{
|
||||||
if (!s.empty()) s.erase(s.rfind('/'));
|
if (!s.empty()) s.erase(s.rfind('/'));
|
||||||
i += 2;
|
path.remove_prefix(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Normal component; copy it. */
|
/* Normal component; copy it. */
|
||||||
else {
|
else {
|
||||||
s += '/';
|
s += '/';
|
||||||
while (i != end && *i != '/') s += *i++;
|
if (const auto slash = path.find('/'); slash == string::npos) {
|
||||||
|
s += path;
|
||||||
|
path = {};
|
||||||
|
} else {
|
||||||
|
s += path.substr(0, slash);
|
||||||
|
path = path.substr(slash + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* If s points to a symlink, resolve it and continue from there */
|
/* If s points to a symlink, resolve it and continue from there */
|
||||||
if (resolveSymlinks && isLink(s)) {
|
if (resolveSymlinks && isLink(s)) {
|
||||||
if (++followCount >= maxFollow)
|
if (++followCount >= maxFollow)
|
||||||
throw Error("infinite symlink recursion in path '%1%'", path);
|
throw Error("infinite symlink recursion in path '%1%'", path);
|
||||||
temp = readLink(s) + string(i, end);
|
temp = concatStrings(readLink(s), path);
|
||||||
i = temp.begin();
|
path = temp;
|
||||||
end = temp.end();
|
|
||||||
if (!temp.empty() && temp[0] == '/') {
|
if (!temp.empty() && temp[0] == '/') {
|
||||||
s.clear(); /* restart for symlinks pointing to absolute path */
|
s.clear(); /* restart for symlinks pointing to absolute path */
|
||||||
} else {
|
} else {
|
||||||
|
@ -164,7 +168,7 @@ Path canonPath(const Path & path, bool resolveSymlinks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.empty() ? "/" : s;
|
return s.empty() ? "/" : std::move(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1229,23 +1233,22 @@ void _interrupted()
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
template<class C> C tokenizeString(std::string_view s, const string & separators)
|
template<class C> C tokenizeString(std::string_view s, std::string_view separators)
|
||||||
{
|
{
|
||||||
C result;
|
C result;
|
||||||
string::size_type pos = s.find_first_not_of(separators, 0);
|
string::size_type pos = s.find_first_not_of(separators, 0);
|
||||||
while (pos != string::npos) {
|
while (pos != string::npos) {
|
||||||
string::size_type end = s.find_first_of(separators, pos + 1);
|
string::size_type end = s.find_first_of(separators, pos + 1);
|
||||||
if (end == string::npos) end = s.size();
|
if (end == string::npos) end = s.size();
|
||||||
string token(s, pos, end - pos);
|
result.insert(result.end(), string(s, pos, end - pos));
|
||||||
result.insert(result.end(), token);
|
|
||||||
pos = s.find_first_not_of(separators, end);
|
pos = s.find_first_not_of(separators, end);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template Strings tokenizeString(std::string_view s, const string & separators);
|
template Strings tokenizeString(std::string_view s, std::string_view separators);
|
||||||
template StringSet tokenizeString(std::string_view s, const string & separators);
|
template StringSet tokenizeString(std::string_view s, std::string_view separators);
|
||||||
template vector<string> tokenizeString(std::string_view s, const string & separators);
|
template vector<string> tokenizeString(std::string_view s, std::string_view separators);
|
||||||
|
|
||||||
|
|
||||||
string chomp(std::string_view s)
|
string chomp(std::string_view s)
|
||||||
|
|
|
@ -56,7 +56,7 @@ Path absPath(Path path,
|
||||||
double or trailing slashes. Optionally resolves all symlink
|
double or trailing slashes. Optionally resolves all symlink
|
||||||
components such that each component of the resulting path is *not*
|
components such that each component of the resulting path is *not*
|
||||||
a symbolic link. */
|
a symbolic link. */
|
||||||
Path canonPath(const Path & path, bool resolveSymlinks = false);
|
Path canonPath(PathView path, bool resolveSymlinks = false);
|
||||||
|
|
||||||
/* Return the directory part of the given canonical path, i.e.,
|
/* Return the directory part of the given canonical path, i.e.,
|
||||||
everything before the final `/'. If the path is the root or an
|
everything before the final `/'. If the path is the root or an
|
||||||
|
@ -368,15 +368,19 @@ MakeError(FormatError, Error);
|
||||||
|
|
||||||
|
|
||||||
/* String tokenizer. */
|
/* String tokenizer. */
|
||||||
template<class C> C tokenizeString(std::string_view s, const string & separators = " \t\n\r");
|
template<class C> C tokenizeString(std::string_view s, std::string_view separators = " \t\n\r");
|
||||||
|
|
||||||
|
|
||||||
/* Concatenate the given strings with a separator between the
|
/* Concatenate the given strings with a separator between the
|
||||||
elements. */
|
elements. */
|
||||||
template<class C>
|
template<class C>
|
||||||
string concatStringsSep(const string & sep, const C & ss)
|
string concatStringsSep(const std::string_view sep, const C & ss)
|
||||||
{
|
{
|
||||||
|
size_t size = 0;
|
||||||
|
// need a cast to string_view since this is also called with Symbols
|
||||||
|
for (const auto & s : ss) size += sep.size() + std::string_view(s).size();
|
||||||
string s;
|
string s;
|
||||||
|
s.reserve(size);
|
||||||
for (auto & i : ss) {
|
for (auto & i : ss) {
|
||||||
if (s.size() != 0) s += sep;
|
if (s.size() != 0) s += sep;
|
||||||
s += i;
|
s += i;
|
||||||
|
@ -384,6 +388,14 @@ string concatStringsSep(const string & sep, const C & ss)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class ... Parts>
|
||||||
|
auto concatStrings(Parts && ... parts)
|
||||||
|
-> std::enable_if_t<(... && std::is_convertible_v<Parts, std::string_view>), string>
|
||||||
|
{
|
||||||
|
std::string_view views[sizeof...(parts)] = { parts... };
|
||||||
|
return concatStringsSep({}, views);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Add quotes around a collection of strings. */
|
/* Add quotes around a collection of strings. */
|
||||||
template<class C> Strings quoteStrings(const C & c)
|
template<class C> Strings quoteStrings(const C & c)
|
||||||
|
|
Loading…
Reference in a new issue