Skip to content

Commit 7c85ac2

Browse files
authored
Merge pull request #14444 from NixOS/less-c_str
Use less `c_str()` in the evaluator, and other cleanups
2 parents 0539b58 + bd42092 commit 7c85ac2

File tree

16 files changed

+64
-38
lines changed

16 files changed

+64
-38
lines changed

src/libexpr-c/nix_api_value.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ nix_get_string(nix_c_context * context, const nix_value * value, nix_get_string_
235235
try {
236236
auto & v = check_value_in(value);
237237
assert(v.type() == nix::nString);
238-
call_nix_get_string_callback(v.c_str(), callback, user_data);
238+
call_nix_get_string_callback(v.string_view(), callback, user_data);
239239
}
240240
NIXC_CATCH_ERRS
241241
}

src/libexpr-test-support/include/nix/expr/tests/libexpr.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ MATCHER_P(IsStringEq, s, fmt("The string is equal to \"%1%\"", s))
106106
if (arg.type() != nString) {
107107
return false;
108108
}
109-
return std::string_view(arg.c_str()) == s;
109+
return arg.string_view() == s;
110110
}
111111

112112
MATCHER_P(IsIntEq, v, fmt("The string is equal to \"%1%\"", v))

src/libexpr-tests/value/value.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "nix/expr/value.hh"
22

33
#include "nix/store/tests/libstore.hh"
4+
#include <gtest/gtest.h>
45

56
namespace nix {
67

@@ -22,4 +23,21 @@ TEST_F(ValueTest, vInt)
2223
ASSERT_EQ(true, vInt.isValid());
2324
}
2425

26+
TEST_F(ValueTest, staticString)
27+
{
28+
Value vStr1;
29+
Value vStr2;
30+
vStr1.mkStringNoCopy("foo");
31+
vStr2.mkStringNoCopy("foo");
32+
33+
auto sd1 = vStr1.string_view();
34+
auto sd2 = vStr2.string_view();
35+
36+
// The strings should be the same
37+
ASSERT_EQ(sd1, sd2);
38+
39+
// The strings should also be backed by the same (static) allocation
40+
ASSERT_EQ(sd1.data(), sd2.data());
41+
}
42+
2543
} // namespace nix

src/libexpr/eval-cache.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ Value & AttrCursor::forceValue()
406406

407407
if (root->db && (!cachedValue || std::get_if<placeholder_t>(&cachedValue->second))) {
408408
if (v.type() == nString)
409-
cachedValue = {root->db->setString(getKey(), v.c_str(), v.context()), string_t{v.c_str(), {}}};
409+
cachedValue = {root->db->setString(getKey(), v.string_view(), v.context()), string_t{v.string_view(), {}}};
410410
else if (v.type() == nPath) {
411411
auto path = v.path().path;
412412
cachedValue = {root->db->setString(getKey(), path.abs()), string_t{path.abs(), {}}};
@@ -541,7 +541,7 @@ std::string AttrCursor::getString()
541541
if (v.type() != nString && v.type() != nPath)
542542
root->state.error<TypeError>("'%s' is not a string but %s", getAttrPathStr(), showType(v)).debugThrow();
543543

544-
return v.type() == nString ? v.c_str() : v.path().to_string();
544+
return v.type() == nString ? std::string(v.string_view()) : v.path().to_string();
545545
}
546546

547547
string_t AttrCursor::getStringWithContext()
@@ -580,7 +580,7 @@ string_t AttrCursor::getStringWithContext()
580580
if (v.type() == nString) {
581581
NixStringContext context;
582582
copyContext(v, context);
583-
return {v.c_str(), std::move(context)};
583+
return {std::string{v.string_view()}, std::move(context)};
584584
} else if (v.type() == nPath)
585585
return {v.path().to_string(), {}};
586586
else

src/libexpr/eval.cc

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2366,12 +2366,15 @@ BackedStringView EvalState::coerceToString(
23662366
}
23672367

23682368
if (v.type() == nPath) {
2369-
return !canonicalizePath && !copyToStore
2370-
? // FIXME: hack to preserve path literals that end in a
2371-
// slash, as in /foo/${x}.
2372-
v.pathStr()
2373-
: copyToStore ? store->printStorePath(copyPathToStore(context, v.path()))
2374-
: std::string(v.path().path.abs());
2369+
if (!canonicalizePath && !copyToStore) {
2370+
// FIXME: hack to preserve path literals that end in a
2371+
// slash, as in /foo/${x}.
2372+
return v.pathStrView();
2373+
} else if (copyToStore) {
2374+
return store->printStorePath(copyPathToStore(context, v.path()));
2375+
} else {
2376+
return std::string{v.path().path.abs()};
2377+
}
23752378
}
23762379

23772380
if (v.type() == nAttrs) {
@@ -2624,7 +2627,7 @@ void EvalState::assertEqValues(Value & v1, Value & v2, const PosIdx pos, std::st
26242627
return;
26252628

26262629
case nString:
2627-
if (strcmp(v1.c_str(), v2.c_str()) != 0) {
2630+
if (v1.string_view() != v2.string_view()) {
26282631
error<AssertionError>(
26292632
"string '%s' is not equal to string '%s'",
26302633
ValuePrinter(*this, v1, errorPrintOptions),
@@ -2641,7 +2644,7 @@ void EvalState::assertEqValues(Value & v1, Value & v2, const PosIdx pos, std::st
26412644
ValuePrinter(*this, v2, errorPrintOptions))
26422645
.debugThrow();
26432646
}
2644-
if (strcmp(v1.pathStr(), v2.pathStr()) != 0) {
2647+
if (v1.pathStrView() != v2.pathStrView()) {
26452648
error<AssertionError>(
26462649
"path '%s' is not equal to path '%s'",
26472650
ValuePrinter(*this, v1, errorPrintOptions),
@@ -2807,12 +2810,12 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
28072810
return v1.boolean() == v2.boolean();
28082811

28092812
case nString:
2810-
return strcmp(v1.c_str(), v2.c_str()) == 0;
2813+
return v1.string_view() == v2.string_view();
28112814

28122815
case nPath:
28132816
return
28142817
// FIXME: compare accessors by their fingerprint.
2815-
v1.pathAccessor() == v2.pathAccessor() && strcmp(v1.pathStr(), v2.pathStr()) == 0;
2818+
v1.pathAccessor() == v2.pathAccessor() && v1.pathStrView() == v2.pathStrView();
28162819

28172820
case nNull:
28182821
return true;

src/libexpr/get-drvs.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
168168
for (auto elem : outTI->listView()) {
169169
if (elem->type() != nString)
170170
throw errMsg;
171-
auto out = outputs.find(elem->c_str());
171+
auto out = outputs.find(elem->string_view());
172172
if (out == outputs.end())
173173
throw errMsg;
174174
result.insert(*out);
@@ -245,7 +245,7 @@ std::string PackageInfo::queryMetaString(const std::string & name)
245245
Value * v = queryMeta(name);
246246
if (!v || v->type() != nString)
247247
return "";
248-
return v->c_str();
248+
return std::string{v->string_view()};
249249
}
250250

251251
NixInt PackageInfo::queryMetaInt(const std::string & name, NixInt def)
@@ -258,7 +258,7 @@ NixInt PackageInfo::queryMetaInt(const std::string & name, NixInt def)
258258
if (v->type() == nString) {
259259
/* Backwards compatibility with before we had support for
260260
integer meta fields. */
261-
if (auto n = string2Int<NixInt::Inner>(v->c_str()))
261+
if (auto n = string2Int<NixInt::Inner>(v->string_view()))
262262
return NixInt{*n};
263263
}
264264
return def;
@@ -274,7 +274,7 @@ NixFloat PackageInfo::queryMetaFloat(const std::string & name, NixFloat def)
274274
if (v->type() == nString) {
275275
/* Backwards compatibility with before we had support for
276276
float meta fields. */
277-
if (auto n = string2Float<NixFloat>(v->c_str()))
277+
if (auto n = string2Float<NixFloat>(v->string_view()))
278278
return *n;
279279
}
280280
return def;

src/libexpr/include/nix/expr/get-drvs.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace nix {
1515
struct PackageInfo
1616
{
1717
public:
18-
typedef std::map<std::string, std::optional<StorePath>> Outputs;
18+
typedef std::map<std::string, std::optional<StorePath>, std::less<>> Outputs;
1919

2020
private:
2121
EvalState * state;

src/libexpr/include/nix/expr/value.hh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ public:
11091109

11101110
std::string_view string_view() const noexcept
11111111
{
1112-
return std::string_view(getStorage<StringWithContext>().c_str);
1112+
return std::string_view{getStorage<StringWithContext>().c_str};
11131113
}
11141114

11151115
const char * c_str() const noexcept
@@ -1177,6 +1177,11 @@ public:
11771177
return getStorage<Path>().path;
11781178
}
11791179

1180+
std::string_view pathStrView() const noexcept
1181+
{
1182+
return std::string_view{getStorage<Path>().path};
1183+
}
1184+
11801185
SourceAccessor * pathAccessor() const noexcept
11811186
{
11821187
return getStorage<Path>().accessor;

src/libexpr/nixexpr.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ void ExprString::show(const SymbolTable & symbols, std::ostream & str) const
4545

4646
void ExprPath::show(const SymbolTable & symbols, std::ostream & str) const
4747
{
48-
str << v.pathStr();
48+
str << v.pathStrView();
4949
}
5050

5151
void ExprVar::show(const SymbolTable & symbols, std::ostream & str) const

src/libexpr/primops.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -691,12 +691,12 @@ struct CompareValues
691691
case nFloat:
692692
return v1->fpoint() < v2->fpoint();
693693
case nString:
694-
return strcmp(v1->c_str(), v2->c_str()) < 0;
694+
return v1->string_view() < v2->string_view();
695695
case nPath:
696696
// Note: we don't take the accessor into account
697697
// since it's not obvious how to compare them in a
698698
// reproducible way.
699-
return strcmp(v1->pathStr(), v2->pathStr()) < 0;
699+
return v1->pathStrView() < v2->pathStrView();
700700
case nList:
701701
// Lexicographic comparison
702702
for (size_t i = 0;; i++) {
@@ -2930,7 +2930,7 @@ static void prim_attrNames(EvalState & state, const PosIdx pos, Value ** args, V
29302930
for (const auto & [n, i] : enumerate(*args[0]->attrs()))
29312931
list[n] = Value::toPtr(state.symbols[i.name]);
29322932

2933-
std::sort(list.begin(), list.end(), [](Value * v1, Value * v2) { return strcmp(v1->c_str(), v2->c_str()) < 0; });
2933+
std::sort(list.begin(), list.end(), [](Value * v1, Value * v2) { return v1->string_view() < v2->string_view(); });
29342934

29352935
v.mkList(list);
29362936
}

0 commit comments

Comments
 (0)