1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-08 11:36:03 +01:00

Merge pull request #14444 from NixOS/less-c_str

Use less `c_str()` in the evaluator, and other cleanups
This commit is contained in:
John Ericson 2025-11-03 17:56:22 +00:00 committed by GitHub
commit 7c85ac23e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 64 additions and 38 deletions

View file

@ -235,7 +235,7 @@ nix_get_string(nix_c_context * context, const nix_value * value, nix_get_string_
try {
auto & v = check_value_in(value);
assert(v.type() == nix::nString);
call_nix_get_string_callback(v.c_str(), callback, user_data);
call_nix_get_string_callback(v.string_view(), callback, user_data);
}
NIXC_CATCH_ERRS
}

View file

@ -106,7 +106,7 @@ MATCHER_P(IsStringEq, s, fmt("The string is equal to \"%1%\"", s))
if (arg.type() != nString) {
return false;
}
return std::string_view(arg.c_str()) == s;
return arg.string_view() == s;
}
MATCHER_P(IsIntEq, v, fmt("The string is equal to \"%1%\"", v))

View file

@ -1,6 +1,7 @@
#include "nix/expr/value.hh"
#include "nix/store/tests/libstore.hh"
#include <gtest/gtest.h>
namespace nix {
@ -22,4 +23,21 @@ TEST_F(ValueTest, vInt)
ASSERT_EQ(true, vInt.isValid());
}
TEST_F(ValueTest, staticString)
{
Value vStr1;
Value vStr2;
vStr1.mkStringNoCopy("foo");
vStr2.mkStringNoCopy("foo");
auto sd1 = vStr1.string_view();
auto sd2 = vStr2.string_view();
// The strings should be the same
ASSERT_EQ(sd1, sd2);
// The strings should also be backed by the same (static) allocation
ASSERT_EQ(sd1.data(), sd2.data());
}
} // namespace nix

View file

@ -406,7 +406,7 @@ Value & AttrCursor::forceValue()
if (root->db && (!cachedValue || std::get_if<placeholder_t>(&cachedValue->second))) {
if (v.type() == nString)
cachedValue = {root->db->setString(getKey(), v.c_str(), v.context()), string_t{v.c_str(), {}}};
cachedValue = {root->db->setString(getKey(), v.string_view(), v.context()), string_t{v.string_view(), {}}};
else if (v.type() == nPath) {
auto path = v.path().path;
cachedValue = {root->db->setString(getKey(), path.abs()), string_t{path.abs(), {}}};
@ -541,7 +541,7 @@ std::string AttrCursor::getString()
if (v.type() != nString && v.type() != nPath)
root->state.error<TypeError>("'%s' is not a string but %s", getAttrPathStr(), showType(v)).debugThrow();
return v.type() == nString ? v.c_str() : v.path().to_string();
return v.type() == nString ? std::string(v.string_view()) : v.path().to_string();
}
string_t AttrCursor::getStringWithContext()
@ -580,7 +580,7 @@ string_t AttrCursor::getStringWithContext()
if (v.type() == nString) {
NixStringContext context;
copyContext(v, context);
return {v.c_str(), std::move(context)};
return {std::string{v.string_view()}, std::move(context)};
} else if (v.type() == nPath)
return {v.path().to_string(), {}};
else

View file

@ -2366,12 +2366,15 @@ BackedStringView EvalState::coerceToString(
}
if (v.type() == nPath) {
return !canonicalizePath && !copyToStore
? // FIXME: hack to preserve path literals that end in a
// slash, as in /foo/${x}.
v.pathStr()
: copyToStore ? store->printStorePath(copyPathToStore(context, v.path()))
: std::string(v.path().path.abs());
if (!canonicalizePath && !copyToStore) {
// FIXME: hack to preserve path literals that end in a
// slash, as in /foo/${x}.
return v.pathStrView();
} else if (copyToStore) {
return store->printStorePath(copyPathToStore(context, v.path()));
} else {
return std::string{v.path().path.abs()};
}
}
if (v.type() == nAttrs) {
@ -2624,7 +2627,7 @@ void EvalState::assertEqValues(Value & v1, Value & v2, const PosIdx pos, std::st
return;
case nString:
if (strcmp(v1.c_str(), v2.c_str()) != 0) {
if (v1.string_view() != v2.string_view()) {
error<AssertionError>(
"string '%s' is not equal to string '%s'",
ValuePrinter(*this, v1, errorPrintOptions),
@ -2641,7 +2644,7 @@ void EvalState::assertEqValues(Value & v1, Value & v2, const PosIdx pos, std::st
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
if (strcmp(v1.pathStr(), v2.pathStr()) != 0) {
if (v1.pathStrView() != v2.pathStrView()) {
error<AssertionError>(
"path '%s' is not equal to path '%s'",
ValuePrinter(*this, v1, errorPrintOptions),
@ -2807,12 +2810,12 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
return v1.boolean() == v2.boolean();
case nString:
return strcmp(v1.c_str(), v2.c_str()) == 0;
return v1.string_view() == v2.string_view();
case nPath:
return
// FIXME: compare accessors by their fingerprint.
v1.pathAccessor() == v2.pathAccessor() && strcmp(v1.pathStr(), v2.pathStr()) == 0;
v1.pathAccessor() == v2.pathAccessor() && v1.pathStrView() == v2.pathStrView();
case nNull:
return true;

View file

@ -168,7 +168,7 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
for (auto elem : outTI->listView()) {
if (elem->type() != nString)
throw errMsg;
auto out = outputs.find(elem->c_str());
auto out = outputs.find(elem->string_view());
if (out == outputs.end())
throw errMsg;
result.insert(*out);
@ -245,7 +245,7 @@ std::string PackageInfo::queryMetaString(const std::string & name)
Value * v = queryMeta(name);
if (!v || v->type() != nString)
return "";
return v->c_str();
return std::string{v->string_view()};
}
NixInt PackageInfo::queryMetaInt(const std::string & name, NixInt def)
@ -258,7 +258,7 @@ NixInt PackageInfo::queryMetaInt(const std::string & name, NixInt def)
if (v->type() == nString) {
/* Backwards compatibility with before we had support for
integer meta fields. */
if (auto n = string2Int<NixInt::Inner>(v->c_str()))
if (auto n = string2Int<NixInt::Inner>(v->string_view()))
return NixInt{*n};
}
return def;
@ -274,7 +274,7 @@ NixFloat PackageInfo::queryMetaFloat(const std::string & name, NixFloat def)
if (v->type() == nString) {
/* Backwards compatibility with before we had support for
float meta fields. */
if (auto n = string2Float<NixFloat>(v->c_str()))
if (auto n = string2Float<NixFloat>(v->string_view()))
return *n;
}
return def;

View file

@ -15,7 +15,7 @@ namespace nix {
struct PackageInfo
{
public:
typedef std::map<std::string, std::optional<StorePath>> Outputs;
typedef std::map<std::string, std::optional<StorePath>, std::less<>> Outputs;
private:
EvalState * state;

View file

@ -1109,7 +1109,7 @@ public:
std::string_view string_view() const noexcept
{
return std::string_view(getStorage<StringWithContext>().c_str);
return std::string_view{getStorage<StringWithContext>().c_str};
}
const char * c_str() const noexcept
@ -1177,6 +1177,11 @@ public:
return getStorage<Path>().path;
}
std::string_view pathStrView() const noexcept
{
return std::string_view{getStorage<Path>().path};
}
SourceAccessor * pathAccessor() const noexcept
{
return getStorage<Path>().accessor;

View file

@ -45,7 +45,7 @@ void ExprString::show(const SymbolTable & symbols, std::ostream & str) const
void ExprPath::show(const SymbolTable & symbols, std::ostream & str) const
{
str << v.pathStr();
str << v.pathStrView();
}
void ExprVar::show(const SymbolTable & symbols, std::ostream & str) const

View file

@ -691,12 +691,12 @@ struct CompareValues
case nFloat:
return v1->fpoint() < v2->fpoint();
case nString:
return strcmp(v1->c_str(), v2->c_str()) < 0;
return v1->string_view() < v2->string_view();
case nPath:
// Note: we don't take the accessor into account
// since it's not obvious how to compare them in a
// reproducible way.
return strcmp(v1->pathStr(), v2->pathStr()) < 0;
return v1->pathStrView() < v2->pathStrView();
case nList:
// Lexicographic comparison
for (size_t i = 0;; i++) {
@ -2930,7 +2930,7 @@ static void prim_attrNames(EvalState & state, const PosIdx pos, Value ** args, V
for (const auto & [n, i] : enumerate(*args[0]->attrs()))
list[n] = Value::toPtr(state.symbols[i.name]);
std::sort(list.begin(), list.end(), [](Value * v1, Value * v2) { return strcmp(v1->c_str(), v2->c_str()) < 0; });
std::sort(list.begin(), list.end(), [](Value * v1, Value * v2) { return v1->string_view() < v2->string_view(); });
v.mkList(list);
}

View file

@ -33,7 +33,7 @@ json printValueAsJSON(
case nString:
copyContext(v, context);
out = v.c_str();
out = v.string_view();
break;
case nPath:

View file

@ -82,7 +82,7 @@ static void printValueAsXML(
case nString:
/* !!! show the context? */
copyContext(v, context);
doc.writeEmptyElement("string", singletonAttrs("value", v.c_str()));
doc.writeEmptyElement("string", singletonAttrs("value", v.string_view()));
break;
case nPath:
@ -102,14 +102,14 @@ static void printValueAsXML(
if (strict)
state.forceValue(*a->value, a->pos);
if (a->value->type() == nString)
xmlAttrs["drvPath"] = drvPath = a->value->c_str();
xmlAttrs["drvPath"] = drvPath = a->value->string_view();
}
if (auto a = v.attrs()->get(state.s.outPath)) {
if (strict)
state.forceValue(*a->value, a->pos);
if (a->value->type() == nString)
xmlAttrs["outPath"] = a->value->c_str();
xmlAttrs["outPath"] = a->value->string_view();
}
XMLOpenElement _(doc, "derivation", xmlAttrs);

View file

@ -97,7 +97,7 @@ static void parseFlakeInputAttr(EvalState & state, const Attr & attr, fetchers::
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch (attr.value->type()) {
case nString:
attrs.emplace(state.symbols[attr.name], attr.value->c_str());
attrs.emplace(state.symbols[attr.name], std::string(attr.value->string_view()));
break;
case nBool:
attrs.emplace(state.symbols[attr.name], Explicit<bool>{attr.value->boolean()});
@ -177,7 +177,7 @@ static FlakeInput parseFlakeInput(
parseFlakeInputs(state, attr.value, attr.pos, lockRootAttrPath, flakeDir, false).first;
} else if (attr.name == sFollows) {
expectType(state, nString, *attr.value, attr.pos);
auto follows(parseInputAttrPath(attr.value->c_str()));
auto follows(parseInputAttrPath(attr.value->string_view()));
follows.insert(follows.begin(), lockRootAttrPath.begin(), lockRootAttrPath.end());
input.follows = follows;
} else
@ -264,7 +264,7 @@ static Flake readFlake(
if (auto description = vInfo.attrs()->get(state.s.description)) {
expectType(state, nString, *description->value, description->pos);
flake.description = description->value->c_str();
flake.description = description->value->string_view();
}
auto sInputs = state.symbols.create("inputs");

View file

@ -153,9 +153,9 @@ nix_err nix_err_code(const nix_c_context * read_context)
}
// internal
nix_err call_nix_get_string_callback(const std::string str, nix_get_string_callback callback, void * user_data)
nix_err call_nix_get_string_callback(const std::string_view str, nix_get_string_callback callback, void * user_data)
{
callback(str.c_str(), str.size(), user_data);
callback(str.data(), str.size(), user_data);
return NIX_OK;
}

View file

@ -32,7 +32,7 @@ nix_err nix_context_error(nix_c_context * context);
* @return NIX_OK if there were no errors.
* @see nix_get_string_callback
*/
nix_err call_nix_get_string_callback(const std::string str, nix_get_string_callback callback, void * user_data);
nix_err call_nix_get_string_callback(const std::string_view str, nix_get_string_callback callback, void * user_data);
#define NIXC_CATCH_ERRS \
catch (...) \

View file

@ -1228,7 +1228,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
else {
if (v->type() == nString) {
attrs2["type"] = "string";
attrs2["value"] = v->c_str();
attrs2["value"] = v->string_view();
xml.writeEmptyElement("meta", attrs2);
} else if (v->type() == nInt) {
attrs2["type"] = "int";
@ -1249,7 +1249,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
if (elem->type() != nString)
continue;
XMLAttrs attrs3;
attrs3["value"] = elem->c_str();
attrs3["value"] = elem->string_view();
xml.writeEmptyElement("string", attrs3);
}
} else if (v->type() == nAttrs) {
@ -1260,7 +1260,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
continue;
XMLAttrs attrs3;
attrs3["type"] = globals.state->symbols[i.name];
attrs3["value"] = i.value->c_str();
attrs3["value"] = i.value->string_view();
xml.writeEmptyElement("string", attrs3);
}
}