Delete hasPrefix and hasSuffix from the codebase

These now have equivalents in the standard lib in C++20. This change was
performed with a custom clang-tidy check which I will submit later.
Executed like so:

ninja -C build && run-clang-tidy -checks='-*,nix-*' -load=build/libnix-clang-tidy.so -p .. -fix ../tests | tee -a clang-tidy-result

Change-Id: I62679e315ff9e7ce72a40b91b79c3e9fc01b27e9
This commit is contained in:
Jade Lovelace 2024-03-17 19:14:18 -07:00
parent 706cee5c49
commit 61e21b2557
44 changed files with 91 additions and 147 deletions

View file

@ -172,7 +172,7 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s)
return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
}
else if (hasPrefix(s, "flake:")) {
else if (s.starts_with("flake:")) {
experimentalFeatureSettings.require(Xp::Flakes);
auto flakeRef = parseFlakeRef(std::string(s.substr(6)), {}, true, false);
auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first.storePath;

View file

@ -159,7 +159,7 @@ void MixFlakeOptions::completeFlakeInput(std::string_view prefix)
auto flakeRef = parseFlakeRefWithFragment(expandTilde(flakeRefS), absPath(".")).first;
auto flake = flake::getFlake(*evalState, flakeRef, true);
for (auto & input : flake.inputs)
if (hasPrefix(input.first, prefix))
if (input.first.starts_with(prefix))
completions->add(input.first);
}
}
@ -320,7 +320,7 @@ void completeFlakeRefWithFragment(
auto attrPath = parseAttrPath(*evalState, attrPathS);
std::string lastAttr;
if (!attrPath.empty() && !hasSuffix(attrPathS, ".")) {
if (!attrPath.empty() && !attrPathS.ends_with(".")) {
lastAttr = evalState->symbols[attrPath.back()];
attrPath.pop_back();
}
@ -329,7 +329,7 @@ void completeFlakeRefWithFragment(
if (!attr) continue;
for (auto & attr2 : (*attr)->getAttrs()) {
if (hasPrefix(evalState->symbols[attr2], lastAttr)) {
if (std::string_view(evalState->symbols[attr2]).starts_with(lastAttr)) {
auto attrPath2 = (*attr)->getAttrPath(attr2);
/* Strip the attrpath prefix. */
attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size());
@ -367,12 +367,12 @@ void completeFlakeRef(ref<Store> store, std::string_view prefix)
for (auto & registry : fetchers::getRegistries(store)) {
for (auto & entry : registry->entries) {
auto from = entry.from.to_string();
if (!hasPrefix(prefix, "flake:") && hasPrefix(from, "flake:")) {
if (!prefix.starts_with("flake:") && from.starts_with("flake:")) {
std::string from2(from, 6);
if (hasPrefix(from2, prefix))
if (from2.starts_with(prefix))
completions->add(from2);
} else {
if (hasPrefix(from, prefix))
if (from.starts_with(prefix))
completions->add(from);
}
}

View file

@ -272,7 +272,7 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
auto dir = std::string(cur, 0, slash);
auto prefix2 = std::string(cur, slash + 1);
for (auto & entry : readDirectory(dir == "" ? "/" : dir)) {
if (entry.name[0] != '.' && hasPrefix(entry.name, prefix2))
if (entry.name[0] != '.' && entry.name.starts_with(prefix2))
completions.insert(prev + dir + "/" + entry.name);
}
} catch (Error &) {

View file

@ -29,7 +29,7 @@ static Strings parseNixPath(const std::string & s)
if (*p == ':') {
auto prefix = std::string(start2, s.end());
if (EvalSettings::isPseudoUrl(prefix) || hasPrefix(prefix, "flake:")) {
if (EvalSettings::isPseudoUrl(prefix) || prefix.starts_with("flake:")) {
++p;
while (p != s.end() && *p != ':') ++p;
}
@ -82,7 +82,7 @@ bool EvalSettings::isPseudoUrl(std::string_view s)
std::string EvalSettings::resolvePseudoUrl(std::string_view url)
{
if (hasPrefix(url, "channel:"))
if (url.starts_with("channel:"))
return "https://nixos.org/channels/" + std::string(url.substr(8)) + "/nixexprs.tar.xz";
else
return std::string(url);

View file

@ -484,7 +484,7 @@ SourcePath EvalState::checkSourcePath(const SourcePath & path_)
*/
Path abspath = canonPath(path_.path.abs());
if (hasPrefix(abspath, corepkgsPrefix)) return CanonPath(abspath);
if (abspath.starts_with(corepkgsPrefix)) return CanonPath(abspath);
for (auto & i : *allowedPaths) {
if (isDirOrInDir(abspath, i)) {
@ -527,18 +527,18 @@ void EvalState::checkURI(const std::string & uri)
if (uri == prefix ||
(uri.size() > prefix.size()
&& prefix.size() > 0
&& hasPrefix(uri, prefix)
&& uri.starts_with(prefix)
&& (prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/')))
return;
/* If the URI is a path, then check it against allowedPaths as
well. */
if (hasPrefix(uri, "/")) {
if (uri.starts_with("/")) {
checkSourcePath(CanonPath(uri));
return;
}
if (hasPrefix(uri, "file://")) {
if (uri.starts_with("file://")) {
checkSourcePath(CanonPath(std::string(uri, 7)));
return;
}
@ -642,7 +642,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
}
auto envName = symbols.create(primOp.name);
if (hasPrefix(primOp.name, "__"))
if (primOp.name.starts_with("__"))
primOp.name = primOp.name.substr(2);
Value * v = allocValue();
@ -719,7 +719,7 @@ void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env &
// for the top level, don't print the double underscore ones;
// they are in builtins.
for (auto & i : se.vars)
if (!hasPrefix(st[i.first], "__"))
if (!std::string_view(st[i.first]).starts_with("__"))
std::cout << st[i.first] << " ";
std::cout << ANSI_NORMAL;
std::cout << std::endl;
@ -2790,7 +2790,7 @@ SourcePath EvalState::findFile(const SearchPath & searchPath, const std::string_
if (pathExists(res)) return CanonPath(canonPath(res));
}
if (hasPrefix(path, "nix/"))
if (path.starts_with("nix/"))
return CanonPath(concatStrings(corepkgsPrefix, path.substr(4)));
error<ThrownError>(
@ -2823,7 +2823,7 @@ std::optional<std::string> EvalState::resolveSearchPathPath(const SearchPath::Pa
}
}
else if (hasPrefix(value, "flake:")) {
else if (value.starts_with("flake:")) {
experimentalFeatureSettings.require(Xp::Flakes);
auto flakeRef = parseFlakeRef(value.substr(6), {}, true, false);
debug("fetching flake search path element '%s''", value);

View file

@ -35,7 +35,7 @@ void ConfigFile::apply()
for (auto & [name, value] : settings) {
auto baseName = hasPrefix(name, "extra-") ? std::string(name, 6) : name;
auto baseName = name.starts_with("extra-") ? std::string(name, 6) : name;
// FIXME: Move into libutil/config.cc.
std::string valueS;

View file

@ -186,7 +186,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
}
} else {
if (!hasPrefix(path, "/"))
if (!path.starts_with("/"))
throw BadURL("flake reference '%s' is not an absolute path", url);
auto query = decodeQuery(match[2]);
path = canonPath(path + "/" + getOr(query, "dir", ""));

View file

@ -223,7 +223,7 @@ std::pair<StorePath, Input> fetchFromWorkdir(ref<Store> store, Input & input, co
Path actualPath(absPath(workdir));
PathFilter filter = [&](const Path & p) -> bool {
assert(hasPrefix(p, actualPath));
assert(p.starts_with(actualPath));
std::string file(p, actualPath.size() + 1);
auto st = lstat(p);
@ -231,7 +231,7 @@ std::pair<StorePath, Input> fetchFromWorkdir(ref<Store> store, Input & input, co
if (S_ISDIR(st.st_mode)) {
auto prefix = file + "/";
auto i = files.lower_bound(prefix);
return i != files.end() && hasPrefix(*i, prefix);
return i != files.end() && (*i).starts_with(prefix);
}
return files.count(file);
@ -267,7 +267,7 @@ struct GitInputScheme : InputScheme
url.scheme != "git+file") return {};
auto url2(url);
if (hasPrefix(url2.scheme, "git+")) url2.scheme = std::string(url2.scheme, 4);
if (url2.scheme.starts_with("git+")) url2.scheme = std::string(url2.scheme, 4);
url2.query.clear();
Attrs attrs;

View file

@ -181,7 +181,7 @@ struct MercurialInputScheme : InputScheme
Path actualPath(absPath(actualUrl));
PathFilter filter = [&](const Path & p) -> bool {
assert(hasPrefix(p, actualPath));
assert(p.starts_with(actualPath));
std::string file(p, actualPath.size() + 1);
auto st = lstat(p);
@ -189,7 +189,7 @@ struct MercurialInputScheme : InputScheme
if (S_ISDIR(st.st_mode)) {
auto prefix = file + "/";
auto i = files.lower_bound(prefix);
return i != files.end() && hasPrefix(*i, prefix);
return i != files.end() && (*i).starts_with(prefix);
}
return files.count(file);

View file

@ -157,7 +157,7 @@ static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
return std::make_shared<Registry>(Registry::Global); // empty registry
}
if (!hasPrefix(path, "/")) {
if (!path.starts_with("/")) {
auto storePath = downloadFile(store, path, "flake-registry.json", false).storePath;
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json");

View file

@ -188,10 +188,10 @@ struct CurlInputScheme : InputScheme
const bool hasTarballExtension(std::string_view path) const
{
return hasSuffix(path, ".zip") || hasSuffix(path, ".tar")
|| hasSuffix(path, ".tgz") || hasSuffix(path, ".tar.gz")
|| hasSuffix(path, ".tar.xz") || hasSuffix(path, ".tar.bz2")
|| hasSuffix(path, ".tar.zst");
return path.ends_with(".zip") || path.ends_with(".tar")
|| path.ends_with(".tgz") || path.ends_with(".tar.gz")
|| path.ends_with(".tar.xz") || path.ends_with(".tar.bz2")
|| path.ends_with(".tar.zst");
}
virtual bool isValidURL(const ParsedURL & url, bool requireTree) const = 0;

View file

@ -47,7 +47,7 @@ MixCommonArgs::MixCommonArgs(const std::string & programName)
std::map<std::string, Config::SettingInfo> settings;
globalConfig.getSettings(settings);
for (auto & s : settings)
if (hasPrefix(s.first, prefix))
if (s.first.starts_with(prefix))
completions->add(s.first, fmt("Set the `%s` setting.", s.first));
}
}

View file

@ -188,7 +188,7 @@ public:
if (type == actBuild) {
std::string name(storePathToName(getS(fields, 0)));
if (hasSuffix(name, ".drv"))
if (name.ends_with(".drv"))
name = name.substr(0, name.size() - 4);
i->s = fmt("building " ANSI_BOLD "%s" ANSI_NORMAL, name);
auto machineName = getS(fields, 1);
@ -207,7 +207,7 @@ public:
auto name = storePathToName(getS(fields, 0));
auto sub = getS(fields, 1);
i->s = fmt(
hasPrefix(sub, "local")
sub.starts_with("local")
? "copying " ANSI_BOLD "%s" ANSI_NORMAL " from %s"
: "fetching " ANSI_BOLD "%s" ANSI_NORMAL " from %s",
name, sub);
@ -215,7 +215,7 @@ public:
if (type == actPostBuildHook) {
auto name = storePathToName(getS(fields, 0));
if (hasSuffix(name, ".drv"))
if (name.ends_with(".drv"))
name = name.substr(0, name.size() - 4);
i->s = fmt("post-build " ANSI_BOLD "%s" ANSI_NORMAL, name);
i->name = DrvName(name).name;

View file

@ -596,7 +596,7 @@ void LocalDerivationGoal::startBuilder()
else
pathsInChroot[i.substr(0, p)] = {i.substr(p + 1), optional};
}
if (hasPrefix(worker.store.storeDir, tmpDirInSandbox))
if (worker.store.storeDir.starts_with(tmpDirInSandbox))
{
throw Error("`sandbox-build-dir` must not contain the storeDir");
}

View file

@ -53,13 +53,13 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
* Python package brings its own
* `$out/lib/pythonX.Y/site-packages/easy-install.pth'.)
*/
if (hasSuffix(srcFile, "/propagated-build-inputs") ||
hasSuffix(srcFile, "/nix-support") ||
hasSuffix(srcFile, "/perllocal.pod") ||
hasSuffix(srcFile, "/info/dir") ||
hasSuffix(srcFile, "/log") ||
hasSuffix(srcFile, "/manifest.nix") ||
hasSuffix(srcFile, "/manifest.json"))
if (srcFile.ends_with("/propagated-build-inputs") ||
srcFile.ends_with("/nix-support") ||
srcFile.ends_with("/perllocal.pod") ||
srcFile.ends_with("/info/dir") ||
srcFile.ends_with("/log") ||
srcFile.ends_with("/manifest.nix") ||
srcFile.ends_with("/manifest.json"))
continue;
else if (S_ISDIR(srcSt.st_mode)) {

View file

@ -41,7 +41,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
request.decompress = false;
auto decompressor = makeDecompressionSink(
unpack && hasSuffix(mainUrl, ".xz") ? "xz" : "none", sink);
unpack && mainUrl.ends_with(".xz") ? "xz" : "none", sink);
fileTransfer->download(std::move(request), *decompressor);
decompressor->finish();
});
@ -62,7 +62,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
if (getAttr("outputHashMode") == "flat")
for (auto hashedMirror : settings.hashedMirrors.get())
try {
if (!hasSuffix(hashedMirror, "/")) hashedMirror += '/';
if (!hashedMirror.ends_with("/")) hashedMirror += '/';
std::optional<HashType> ht = parseHashTypeOpt(getAttr("outputHashAlgo"));
Hash h = newHashAllowEmpty(getAttr("outputHash"), ht);
fetch(hashedMirror + printHashType(h.type) + "/" + h.to_string(Base16, false));

View file

@ -221,7 +221,7 @@ struct ClientSettings
for (auto & s : ss)
if (trusted.count(s))
subs.push_back(s);
else if (!hasSuffix(s, "/") && trusted.count(s + "/"))
else if (!s.ends_with("/") && trusted.count(s + "/"))
subs.push_back(s + "/");
else
warn("ignoring untrusted substituter '%s', you are not a trusted user.\n"

View file

@ -658,7 +658,7 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
// FIXME: remove
bool isDerivation(std::string_view fileName)
{
return hasSuffix(fileName, drvExtension);
return fileName.ends_with(drvExtension);
}
@ -927,7 +927,7 @@ std::string_view BasicDerivation::nameFromPath(const StorePath & drvPath)
{
auto nameWithSuffix = drvPath.name();
constexpr std::string_view extension = ".drv";
assert(hasSuffix(nameWithSuffix, extension));
assert(nameWithSuffix.ends_with(extension));
nameWithSuffix.remove_suffix(extension.size());
return nameWithSuffix;
}

View file

@ -670,8 +670,8 @@ struct curlFileTransfer : public FileTransfer
void enqueueItem(std::shared_ptr<TransferItem> item)
{
if (item->request.data
&& !hasPrefix(item->request.uri, "http://")
&& !hasPrefix(item->request.uri, "https://"))
&& !item->request.uri.starts_with("http://")
&& !item->request.uri.starts_with("https://"))
throw nix::Error("uploading to '%s' is not supported", item->request.uri);
{
@ -703,7 +703,7 @@ struct curlFileTransfer : public FileTransfer
Callback<FileTransferResult> callback) override
{
/* Ugly hack to support s3:// URIs. */
if (hasPrefix(request.uri, "s3://")) {
if (request.uri.starts_with("s3://")) {
// FIXME: do this on a worker thread
try {
#if ENABLE_S3

View file

@ -241,7 +241,7 @@ bool Settings::isWSL1()
uname(&utsbuf);
// WSL1 uses -Microsoft suffix
// WSL2 uses -microsoft-standard suffix
return hasSuffix(utsbuf.release, "-Microsoft");
return std::string_view(utsbuf.release).ends_with("-Microsoft");
}
Path Settings::getDefaultSSLCertFile()
@ -415,7 +415,7 @@ void initLibStore() {
sshd). This breaks build users because they don't have access
to the TMPDIR, in particular in nix-store --serve. */
#if __APPLE__
if (hasPrefix(getEnv("TMPDIR").value_or("/tmp"), "/var/folders/"))
if (getEnv("TMPDIR").value_or("/tmp").starts_with("/var/folders/"))
unsetenv("TMPDIR");
#endif

View file

@ -145,7 +145,7 @@ protected:
FileTransferRequest makeRequest(const std::string & path)
{
return FileTransferRequest(
hasPrefix(path, "https://") || hasPrefix(path, "http://") || hasPrefix(path, "file://")
path.starts_with("https://") || path.starts_with("http://") || path.starts_with("file://")
? path
: cacheUri + "/" + path);

View file

@ -85,7 +85,7 @@ protected:
for (auto & entry : readDirectory(binaryCacheDir)) {
if (entry.name.size() != 40 ||
!hasSuffix(entry.name, ".narinfo"))
!entry.name.ends_with(".narinfo"))
continue;
paths.insert(parseStorePath(
storeDir + "/" + entry.name.substr(0, entry.name.size() - 8)

View file

@ -24,10 +24,10 @@ Machine::Machine(decltype(storeUri) storeUri,
|| storeUri == "auto"
|| storeUri == "daemon"
|| storeUri == "local"
|| hasPrefix(storeUri, "auto?")
|| hasPrefix(storeUri, "daemon?")
|| hasPrefix(storeUri, "local?")
|| hasPrefix(storeUri, "?")
|| storeUri.starts_with("auto?")
|| storeUri.starts_with("daemon?")
|| storeUri.starts_with("local?")
|| storeUri.starts_with("?")
? storeUri
: "ssh://" + storeUri),
systemTypes(systemTypes),
@ -67,12 +67,12 @@ bool Machine::mandatoryMet(const std::set<std::string> & features) const
ref<Store> Machine::openStore() const
{
Store::Params storeParams;
if (hasPrefix(storeUri, "ssh://")) {
if (storeUri.starts_with("ssh://")) {
storeParams["max-connections"] = "1";
storeParams["log-fd"] = "4";
}
if (hasPrefix(storeUri, "ssh://") || hasPrefix(storeUri, "ssh-ng://")) {
if (storeUri.starts_with("ssh://") || storeUri.starts_with("ssh-ng://")) {
if (sshKey != "")
storeParams["ssh-key"] = sshKey;
if (sshPublicHostKey != "")

View file

@ -42,7 +42,7 @@ StorePath::StorePath(const Hash & hash, std::string_view _name)
bool StorePath::isDerivation() const
{
return hasSuffix(name(), drvExtension);
return name().ends_with(drvExtension);
}
StorePath StorePath::dummy("ffffffffffffffffffffffffffffffff-x");

View file

@ -213,7 +213,7 @@ struct S3BinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
support it.
> **Note**
>
>
> HTTPS should be used if the cache might contain sensitive
> information.
)"};
@ -224,7 +224,7 @@ struct S3BinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
Do not specify this setting if you're using Amazon S3.
> **Note**
>
>
> This endpoint must support HTTPS and will use path-based
> addressing instead of virtual host based addressing.
)"};
@ -448,11 +448,11 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
return std::make_shared<std::stringstream>(std::move(compressed));
};
if (narinfoCompression != "" && hasSuffix(path, ".narinfo"))
if (narinfoCompression != "" && path.ends_with(".narinfo"))
uploadFile(path, compress(narinfoCompression), mimeType, narinfoCompression);
else if (lsCompression != "" && hasSuffix(path, ".ls"))
else if (lsCompression != "" && path.ends_with(".ls"))
uploadFile(path, compress(lsCompression), mimeType, lsCompression);
else if (logCompression != "" && hasPrefix(path, "log/"))
else if (logCompression != "" && path.starts_with("log/"))
uploadFile(path, compress(logCompression), mimeType, logCompression);
else
uploadFile(path, istream, mimeType, "");
@ -499,7 +499,7 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
for (auto object : contents) {
auto & key = object.GetKey();
if (key.size() != 40 || !hasSuffix(key, ".narinfo")) continue;
if (key.size() != 40 || !key.ends_with(".narinfo")) continue;
paths.insert(parseStorePath(storeDir + "/" + key.substr(0, key.size() - 8) + "-" + MissingName));
}

View file

@ -12,7 +12,7 @@ SSHMaster::SSHMaster(const std::string & host, const std::string & keyFile, cons
, compress(compress)
, logFD(logFD)
{
if (host == "" || hasPrefix(host, "-"))
if (host == "" || host.starts_with("-"))
throw Error("invalid SSH host name '%s'", host);
auto state(state_.lock());

View file

@ -162,7 +162,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
if (auto prefix = needsCompletion(*pos)) {
for (auto & [name, flag] : longFlags) {
if (!hiddenCategories.count(flag->category)
&& hasPrefix(name, std::string(*prefix, 2)))
&& name.starts_with(std::string(*prefix, 2)))
{
if (auto & f = flag->experimentalFeature)
flagExperimentalFeatures.insert(*f);
@ -274,7 +274,7 @@ nlohmann::json Args::toJSON()
static void hashTypeCompleter(size_t index, std::string_view prefix)
{
for (auto & type : hashTypes)
if (hasPrefix(type, prefix))
if (type.starts_with(prefix))
completions->add(type);
}
@ -370,7 +370,7 @@ MultiCommand::MultiCommand(const Commands & commands_)
}},
.completer = {[&](size_t, std::string_view prefix) {
for (auto & [name, command] : commands)
if (hasPrefix(name, prefix))
if (name.starts_with(prefix))
completions->add(name);
}}
});

View file

@ -41,7 +41,7 @@ std::map<std::string, std::string> getCgroups(const Path & cgroupFile)
if (!std::regex_match(line, match, regex))
throw Error("invalid line '%s' in '%s'", line, cgroupFile);
std::string name = hasPrefix(std::string(match[2]), "name=") ? std::string(match[2], 5) : match[2];
std::string name = std::string(match[2]).starts_with("name=") ? std::string(match[2], 5) : match[2];
cgroups.insert_or_assign(name, match[3]);
}
@ -117,13 +117,13 @@ static CgroupStats destroyCgroup(const Path & cgroup, bool returnStats)
if (pathExists(cpustatPath)) {
for (auto & line : tokenizeString<std::vector<std::string>>(readFile(cpustatPath), "\n")) {
std::string_view userPrefix = "user_usec ";
if (hasPrefix(line, userPrefix)) {
if (line.starts_with(userPrefix)) {
auto n = string2Int<uint64_t>(line.substr(userPrefix.size()));
if (n) stats.cpuUser = std::chrono::microseconds(*n);
}
std::string_view systemPrefix = "system_usec ";
if (hasPrefix(line, systemPrefix)) {
if (line.starts_with(systemPrefix)) {
auto n = string2Int<uint64_t>(line.substr(systemPrefix.size()));
if (n) stats.cpuSystem = std::chrono::microseconds(*n);
}

View file

@ -18,7 +18,7 @@ bool Config::set(const std::string & name, const std::string & value)
bool append = false;
auto i = _settings.find(name);
if (i == _settings.end()) {
if (hasPrefix(name, "extra-")) {
if (name.starts_with("extra-")) {
i = _settings.find(std::string(name, 6));
if (i == _settings.end() || !i->second.setting->isAppendable())
return false;

View file

@ -266,7 +266,7 @@ static Logger::Fields getFields(nlohmann::json & json)
std::optional<nlohmann::json> parseJSONMessage(const std::string & msg)
{
if (!hasPrefix(msg, "@nix ")) return std::nullopt;
if (!msg.starts_with("@nix ")) return std::nullopt;
try {
return nlohmann::json::parse(std::string(msg, 5));
} catch (std::exception & e) {

View file

@ -83,7 +83,7 @@ SourcePath SourcePath::resolveSymlinks(SymlinkResolution mode) const
throw Error("infinite symlink recursion in path '%s'", path);
auto target = res.readLink();
res.path.pop();
if (hasPrefix(target, "/"))
if (target.starts_with("/"))
res.path = CanonPath::root;
todo.splice(todo.begin(), tokenizeString<std::list<std::string>>(target, "/"));
}

View file

@ -27,7 +27,7 @@ static inline std::optional<std::string_view> splitPrefixTo(std::string_view & s
}
static inline bool splitPrefix(std::string_view & string, std::string_view prefix) {
bool res = hasPrefix(string, prefix);
bool res = string.starts_with(prefix);
if (res)
string.remove_prefix(prefix.length());
return res;

View file

@ -1449,19 +1449,6 @@ bool statusOk(int status)
}
bool hasPrefix(std::string_view s, std::string_view prefix)
{
return s.compare(0, prefix.size(), prefix) == 0;
}
bool hasSuffix(std::string_view s, std::string_view suffix)
{
return s.size() >= suffix.size()
&& s.substr(s.size() - suffix.size()) == suffix;
}
std::string toLower(const std::string & s)
{
std::string r(s);

View file

@ -665,19 +665,6 @@ T readLittleEndian(unsigned char * p)
return x;
}
/**
* @return true iff `s` starts with `prefix`.
*/
bool hasPrefix(std::string_view s, std::string_view prefix);
/**
* @return true iff `s` ends in `suffix`.
*/
bool hasSuffix(std::string_view s, std::string_view suffix);
/**
* Convert a string to lower case.
*/

View file

@ -305,7 +305,7 @@ static void main_nix_build(int argc, char * * argv)
absolute = canonPath(absPath(i), true);
} catch (Error & e) {};
auto [path, outputNames] = parsePathWithOutputs(absolute);
if (evalStore->isStorePath(path) && hasSuffix(path, ".drv"))
if (evalStore->isStorePath(path) && path.ends_with(".drv"))
drvs.push_back(DrvInfo(*state, evalStore, absolute));
else
/* If we're in a #! script, interpret filenames

View file

@ -200,7 +200,7 @@ static int main_nix_channel(int argc, char ** argv)
} else if (*arg == "--rollback") {
cmd = cRollback;
} else {
if (hasPrefix(*arg, "-"))
if ((*arg).starts_with("-"))
throw UsageError("unsupported argument '%s'", *arg);
args.push_back(std::move(*arg));
}

View file

@ -125,13 +125,13 @@ static void getAllExprs(EvalState & state,
continue; // ignore dangling symlinks in ~/.nix-defexpr
}
if (isNixExpr(path2, st) && (st.type != InputAccessor::tRegular || hasSuffix(path2.baseName(), ".nix"))) {
if (isNixExpr(path2, st) && (st.type != InputAccessor::tRegular || path2.baseName().ends_with(".nix"))) {
/* Strip off the `.nix' filename suffix (if applicable),
otherwise the attribute cannot be selected with the
`-A' option. Useful if you want to stick a Nix
expression directly in ~/.nix-defexpr. */
std::string attrName = i;
if (hasSuffix(attrName, ".nix"))
if (attrName.ends_with(".nix"))
attrName = std::string(attrName, 0, attrName.size() - 4);
if (!seen.insert(attrName).second) {
std::string suggestionMessage = "";
@ -241,7 +241,7 @@ std::set<std::string> searchByPrefix(const DrvInfos & allElems, std::string_view
std::set<std::string> result;
for (const auto & drvInfo : allElems) {
const auto drvName = DrvName { drvInfo.queryName() };
if (hasPrefix(drvName.name, prefix)) {
if (drvName.name.starts_with(prefix)) {
result.emplace(drvName.name);
if (result.size() >= maxResults) {

View file

@ -448,7 +448,7 @@ struct Common : InstallableCommand, MixProfile
StorePath getShellOutPath(ref<Store> store, ref<Installable> installable)
{
auto path = installable->getStorePath();
if (path && hasSuffix(path->to_string(), "-env"))
if (path && path->to_string().ends_with("-env"))
return *path;
else {
auto drvs = Installable::toDerivations(store, {installable});

View file

@ -101,7 +101,7 @@ struct CmdDoctor : StoreCommand
try {
Path userEnv = canonPath(profileDir, true);
if (store->isStorePath(userEnv) && hasSuffix(userEnv, "user-environment")) {
if (store->isStorePath(userEnv) && userEnv.ends_with("user-environment")) {
while (profileDir.find("/profiles/") == std::string::npos && isLink(profileDir))
profileDir = absPath(readLink(profileDir), dirOf(profileDir));

View file

@ -334,7 +334,7 @@ struct CmdFlakeCheck : FlakeCommand
return
name == expected
|| name == "_"
|| (hasPrefix(name, "_") && name.substr(1) == expected);
|| (name.starts_with("_") && name.substr(1) == expected);
};
auto checkSystemName = [&](const std::string & system, const PosIdx pos) {

View file

@ -42,7 +42,7 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url)
throw Error("mirror URL '%s' did not expand to anything", url);
std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "while evaluating the first available mirror"));
return mirror + (hasSuffix(mirror, "/") ? "" : "/") + s.substr(p + 1);
return mirror + (mirror.ends_with("/") ? "" : "/") + s.substr(p + 1);
}
std::tuple<StorePath, Hash> prefetchFile(

View file

@ -115,7 +115,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
printInfo("found Nix in '%s'", where);
if (hasPrefix(where, "/run/current-system"))
if (where.starts_with("/run/current-system"))
throw Error("Nix on NixOS must be upgraded via 'nixos-rebuild'");
Path profileDir = dirOf(where);
@ -129,7 +129,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
Path userEnv = canonPath(profileDir, true);
if (baseNameOf(where) != "bin" ||
!hasSuffix(userEnv, "user-environment"))
!userEnv.ends_with("user-environment"))
throw Error("directory '%s' does not appear to be part of a Nix profile", where);
if (!store->isValidPath(store->parseStorePath(userEnv)))

View file

@ -105,7 +105,7 @@ bool isSymlink(const Path & path)
Path resolveSymlink(const Path & path)
{
auto target = readLink(path);
return hasPrefix(target, "/")
return target.starts_with("/")
? target
: concatStrings(dirOf(path), "/", target);
}
@ -125,7 +125,7 @@ std::set<std::string> resolveTree(const Path & path, PathSet & deps)
std::set<std::string> getPath(const Path & path)
{
if (hasPrefix(path, "/dev")) return {};
if (path.starts_with("/dev")) return {};
Path cacheFile = resolveCacheFile(path);
if (pathExists(cacheFile))

View file

@ -234,36 +234,6 @@ namespace nix {
ASSERT_EQ(concatStringsSep(",", strings), "this");
}
/* ----------------------------------------------------------------------------
* hasPrefix
* --------------------------------------------------------------------------*/
TEST(hasPrefix, emptyStringHasNoPrefix) {
ASSERT_FALSE(hasPrefix("", "foo"));
}
TEST(hasPrefix, emptyStringIsAlwaysPrefix) {
ASSERT_TRUE(hasPrefix("foo", ""));
ASSERT_TRUE(hasPrefix("jshjkfhsadf", ""));
}
TEST(hasPrefix, trivialCase) {
ASSERT_TRUE(hasPrefix("foobar", "foo"));
}
/* ----------------------------------------------------------------------------
* hasSuffix
* --------------------------------------------------------------------------*/
TEST(hasSuffix, emptyStringHasNoSuffix) {
ASSERT_FALSE(hasSuffix("", "foo"));
}
TEST(hasSuffix, trivialCase) {
ASSERT_TRUE(hasSuffix("foo", "foo"));
ASSERT_TRUE(hasSuffix("foobar", "bar"));
}
/* ----------------------------------------------------------------------------
* base64Encode
* --------------------------------------------------------------------------*/