mirror of
https://github.com/NixOS/nix.git
synced 2025-11-11 21:16:02 +01:00
Merge branch 'more-stringviews' of https://github.com/pennae/nix
This commit is contained in:
commit
cd35bbbeef
29 changed files with 247 additions and 161 deletions
|
|
@ -259,7 +259,7 @@ Hash::Hash(std::string_view rest, HashType type, bool isSRI)
|
|||
throw BadHash("hash '%s' has wrong length for hash type '%s'", rest, printHashType(this->type));
|
||||
}
|
||||
|
||||
Hash newHashAllowEmpty(std::string hashStr, std::optional<HashType> ht)
|
||||
Hash newHashAllowEmpty(std::string_view hashStr, std::optional<HashType> ht)
|
||||
{
|
||||
if (hashStr.empty()) {
|
||||
if (!ht)
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ public:
|
|||
};
|
||||
|
||||
/* Helper that defaults empty hashes to the 0 hash. */
|
||||
Hash newHashAllowEmpty(std::string hashStr, std::optional<HashType> ht);
|
||||
Hash newHashAllowEmpty(std::string_view hashStr, std::optional<HashType> ht);
|
||||
|
||||
/* Print a hash in base-16 if it's MD5, or base-32 otherwise. */
|
||||
string printHash16or32(const Hash & hash);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <set>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace nix {
|
||||
|
|
@ -47,4 +48,63 @@ struct Explicit {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/* This wants to be a little bit like rust's Cow type.
|
||||
Some parts of the evaluator benefit greatly from being able to reuse
|
||||
existing allocations for strings, but have to be able to also use
|
||||
newly allocated storage for values.
|
||||
|
||||
We do not define implicit conversions, even with ref qualifiers,
|
||||
since those can easily become ambiguous to the reader and can degrade
|
||||
into copying behaviour we want to avoid. */
|
||||
class BackedStringView {
|
||||
private:
|
||||
std::variant<std::string, std::string_view> data;
|
||||
|
||||
/* Needed to introduce a temporary since operator-> must return
|
||||
a pointer. Without this we'd need to store the view object
|
||||
even when we already own a string. */
|
||||
class Ptr {
|
||||
private:
|
||||
std::string_view view;
|
||||
public:
|
||||
Ptr(std::string_view view): view(view) {}
|
||||
const std::string_view * operator->() const { return &view; }
|
||||
};
|
||||
|
||||
public:
|
||||
BackedStringView(std::string && s): data(std::move(s)) {}
|
||||
BackedStringView(std::string_view sv): data(sv) {}
|
||||
template<size_t N>
|
||||
BackedStringView(const char (& lit)[N]): data(std::string_view(lit)) {}
|
||||
|
||||
BackedStringView(const BackedStringView &) = delete;
|
||||
BackedStringView & operator=(const BackedStringView &) = delete;
|
||||
|
||||
/* We only want move operations defined since the sole purpose of
|
||||
this type is to avoid copies. */
|
||||
BackedStringView(BackedStringView && other) = default;
|
||||
BackedStringView & operator=(BackedStringView && other) = default;
|
||||
|
||||
bool isOwned() const
|
||||
{
|
||||
return std::holds_alternative<std::string>(data);
|
||||
}
|
||||
|
||||
std::string toOwned() &&
|
||||
{
|
||||
return isOwned()
|
||||
? std::move(std::get<std::string>(data))
|
||||
: std::string(std::get<std::string_view>(data));
|
||||
}
|
||||
|
||||
std::string_view operator*() const
|
||||
{
|
||||
return isOwned()
|
||||
? std::get<std::string>(data)
|
||||
: std::get<std::string_view>(data);
|
||||
}
|
||||
Ptr operator->() const { return Ptr(**this); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ void replaceEnv(std::map<std::string, std::string> newEnv)
|
|||
}
|
||||
|
||||
|
||||
Path absPath(Path path, std::optional<Path> dir, bool resolveSymlinks)
|
||||
Path absPath(Path path, std::optional<PathView> dir, bool resolveSymlinks)
|
||||
{
|
||||
if (path[0] != '/') {
|
||||
if (!dir) {
|
||||
|
|
@ -95,12 +95,12 @@ Path absPath(Path path, std::optional<Path> dir, bool resolveSymlinks)
|
|||
if (!getcwd(buf, sizeof(buf)))
|
||||
#endif
|
||||
throw SysError("cannot get cwd");
|
||||
dir = buf;
|
||||
path = concatStrings(buf, "/", path);
|
||||
#ifdef __GNU__
|
||||
free(buf);
|
||||
#endif
|
||||
}
|
||||
path = *dir + "/" + path;
|
||||
} else
|
||||
path = concatStrings(*dir, "/", path);
|
||||
}
|
||||
return canonPath(path, resolveSymlinks);
|
||||
}
|
||||
|
|
@ -172,7 +172,7 @@ Path canonPath(PathView path, bool resolveSymlinks)
|
|||
}
|
||||
|
||||
|
||||
Path dirOf(const Path & path)
|
||||
Path dirOf(const PathView path)
|
||||
{
|
||||
Path::size_type pos = path.rfind('/');
|
||||
if (pos == string::npos)
|
||||
|
|
@ -1344,9 +1344,11 @@ std::string toLower(const std::string & s)
|
|||
}
|
||||
|
||||
|
||||
std::string shellEscape(const std::string & s)
|
||||
std::string shellEscape(const std::string_view s)
|
||||
{
|
||||
std::string r = "'";
|
||||
std::string r;
|
||||
r.reserve(s.size() + 2);
|
||||
r += "'";
|
||||
for (auto & i : s)
|
||||
if (i == '\'') r += "'\\''"; else r += i;
|
||||
r += '\'';
|
||||
|
|
@ -1751,7 +1753,7 @@ void bind(int fd, const std::string & path)
|
|||
|
||||
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
||||
Pid pid = startProcess([&]() {
|
||||
auto dir = dirOf(path);
|
||||
Path dir = dirOf(path);
|
||||
if (chdir(dir.c_str()) == -1)
|
||||
throw SysError("chdir to '%s' failed", dir);
|
||||
std::string base(baseNameOf(path));
|
||||
|
|
@ -1780,7 +1782,7 @@ void connect(int fd, const std::string & path)
|
|||
|
||||
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
||||
Pid pid = startProcess([&]() {
|
||||
auto dir = dirOf(path);
|
||||
Path dir = dirOf(path);
|
||||
if (chdir(dir.c_str()) == -1)
|
||||
throw SysError("chdir to '%s' failed", dir);
|
||||
std::string base(baseNameOf(path));
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ void clearEnv();
|
|||
specified directory, or the current directory otherwise. The path
|
||||
is also canonicalised. */
|
||||
Path absPath(Path path,
|
||||
std::optional<Path> dir = {},
|
||||
std::optional<PathView> dir = {},
|
||||
bool resolveSymlinks = false);
|
||||
|
||||
/* Canonicalise a path by removing all `.' or `..' components and
|
||||
|
|
@ -62,7 +62,7 @@ Path canonPath(PathView path, bool resolveSymlinks = false);
|
|||
everything before the final `/'. If the path is the root or an
|
||||
immediate child thereof (e.g., `/foo'), this means `/'
|
||||
is returned.*/
|
||||
Path dirOf(const Path & path);
|
||||
Path dirOf(const PathView path);
|
||||
|
||||
/* Return the base name of the given canonical path, i.e., everything
|
||||
following the final `/' (trailing slashes are removed). */
|
||||
|
|
@ -148,6 +148,9 @@ Path getDataDir();
|
|||
/* Create a directory and all its parents, if necessary. Returns the
|
||||
list of created directories, in order of creation. */
|
||||
Paths createDirs(const Path & path);
|
||||
inline Paths createDirs(PathView path) {
|
||||
return createDirs(Path(path));
|
||||
}
|
||||
|
||||
/* Create a symlink. */
|
||||
void createSymlink(const Path & target, const Path & link,
|
||||
|
|
@ -187,6 +190,7 @@ public:
|
|||
void cancel();
|
||||
void reset(const Path & p, bool recursive = true);
|
||||
operator Path() const { return path; }
|
||||
operator PathView() const { return path; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -491,7 +495,7 @@ std::string toLower(const std::string & s);
|
|||
|
||||
|
||||
/* Escape a string as a shell word. */
|
||||
std::string shellEscape(const std::string & s);
|
||||
std::string shellEscape(const std::string_view s);
|
||||
|
||||
|
||||
/* Exception handling in destructors: print an error message, then
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue