2012-07-18 14:59:03 -04:00
|
|
|
#pragma once
|
2023-03-31 23:18:41 -04:00
|
|
|
///@file
|
2003-04-04 16:14:56 +00:00
|
|
|
|
2006-09-04 21:06:23 +00:00
|
|
|
#include "types.hh"
|
2020-04-24 14:57:51 -06:00
|
|
|
#include "error.hh"
|
2016-04-25 15:26:07 +02:00
|
|
|
#include "logging.hh"
|
2016-09-20 15:39:08 +02:00
|
|
|
|
2021-12-31 03:16:59 +01:00
|
|
|
|
2014-07-10 16:50:51 +02:00
|
|
|
#include <functional>
|
2016-09-20 15:39:08 +02:00
|
|
|
#include <map>
|
2017-03-08 22:24:10 +01:00
|
|
|
#include <sstream>
|
2019-02-12 13:43:32 +01:00
|
|
|
#include <optional>
|
2009-11-24 12:56:26 +00:00
|
|
|
|
2006-09-04 21:06:23 +00:00
|
|
|
namespace nix {
|
2003-10-07 14:37:41 +00:00
|
|
|
|
2023-02-01 13:34:32 +01:00
|
|
|
void initLibUtil();
|
2003-10-07 14:37:41 +00:00
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Convert a list of strings to a null-terminated vector of `char
|
|
|
|
* *`s. The result must not be accessed beyond the lifetime of the
|
|
|
|
* list of strings.
|
|
|
|
*/
|
2015-06-09 10:50:55 +02:00
|
|
|
std::vector<char *> stringsToCharPtrs(const Strings & ss);
|
2014-12-12 15:01:16 +01:00
|
|
|
|
2004-01-15 20:23:55 +00:00
|
|
|
|
2019-11-10 11:14:26 -05:00
|
|
|
MakeError(FormatError, Error);
|
2016-07-18 18:50:27 -04:00
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* String tokenizer.
|
|
|
|
*/
|
2022-01-12 16:02:29 +01:00
|
|
|
template<class C> C tokenizeString(std::string_view s, std::string_view separators = " \t\n\r");
|
2005-09-22 15:43:22 +00:00
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Concatenate the given strings with a separator between the
|
|
|
|
* elements.
|
|
|
|
*/
|
2019-05-02 21:09:52 +02:00
|
|
|
template<class C>
|
2024-07-12 22:09:27 +02:00
|
|
|
std::string dropEmptyInitThenConcatStringsSep(const std::string_view sep, const C & ss)
|
2019-05-02 21:09:52 +02:00
|
|
|
{
|
2022-01-12 16:02:29 +01:00
|
|
|
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();
|
2022-02-25 16:00:00 +01:00
|
|
|
std::string s;
|
2022-01-12 16:02:29 +01:00
|
|
|
s.reserve(size);
|
2019-05-02 21:09:52 +02:00
|
|
|
for (auto & i : ss) {
|
|
|
|
if (s.size() != 0) s += sep;
|
|
|
|
s += i;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2022-01-12 16:02:29 +01:00
|
|
|
template<class ... Parts>
|
|
|
|
auto concatStrings(Parts && ... parts)
|
2022-02-25 16:00:00 +01:00
|
|
|
-> std::enable_if_t<(... && std::is_convertible_v<Parts, std::string_view>), std::string>
|
2022-01-12 16:02:29 +01:00
|
|
|
{
|
|
|
|
std::string_view views[sizeof...(parts)] = { parts... };
|
2024-07-12 22:09:27 +02:00
|
|
|
return dropEmptyInitThenConcatStringsSep({}, views);
|
2022-01-12 16:02:29 +01:00
|
|
|
}
|
|
|
|
|
2019-05-02 21:09:52 +02:00
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Add quotes around a collection of strings.
|
|
|
|
*/
|
2019-05-02 21:09:52 +02:00
|
|
|
template<class C> Strings quoteStrings(const C & c)
|
|
|
|
{
|
|
|
|
Strings res;
|
|
|
|
for (auto & s : c)
|
|
|
|
res.push_back("'" + s + "'");
|
|
|
|
return res;
|
|
|
|
}
|
2010-08-27 13:18:13 +00:00
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Remove trailing whitespace from a string.
|
|
|
|
*
|
|
|
|
* \todo return std::string_view.
|
|
|
|
*/
|
2022-02-25 16:00:00 +01:00
|
|
|
std::string chomp(std::string_view s);
|
2012-08-01 11:19:24 -04:00
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Remove whitespace from the start and end of a string.
|
|
|
|
*/
|
2022-02-25 16:00:00 +01:00
|
|
|
std::string trim(std::string_view s, std::string_view whitespace = " \n\r\t");
|
2015-04-09 11:42:04 +02:00
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Replace all occurrences of a string inside another string.
|
|
|
|
*/
|
2022-02-25 16:00:00 +01:00
|
|
|
std::string replaceStrings(
|
|
|
|
std::string s,
|
|
|
|
std::string_view from,
|
|
|
|
std::string_view to);
|
2015-06-17 16:20:11 +02:00
|
|
|
|
|
|
|
|
2022-02-25 16:00:00 +01:00
|
|
|
std::string rewriteStrings(std::string s, const StringMap & rewrites);
|
2018-03-30 00:56:13 +02:00
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Parse a string into an integer.
|
|
|
|
*/
|
2021-01-08 12:22:21 +01:00
|
|
|
template<class N>
|
Remove 100s of CPU time (10%) from build times (1465s -> 1302s)
Result's from Mic92's framework 13th Gen Intel Core i7-1360P:
Before: 3595.92s user 183.01s system 1360% cpu 4:37.74 total
After: 3486.07s user 168.93s system 1354% cpu 4:29.79 total
I saw that boost/lexical_cast was costing about 100s in CPU time on our
compiles. We can fix this trivially by doing explicit template
instantiation in exactly one place and eliminating all other includes of
it, which is a code improvement anyway by hiding the boost.
Before:
```
lix/lix2 » ClangBuildAnalyzer --analyze buildtimeold.bin
Analyzing build trace from 'buildtimeold.bin'...
**** Time summary:
Compilation (551 times):
Parsing (frontend): 1465.3 s
Codegen & opts (backend): 1110.9 s
<snip>
**** Expensive headers:
178153 ms: ../src/libcmd/installable-value.hh (included 52 times, avg 3426 ms), included via:
40x: command.hh
5x: command-installable-value.hh
3x: installable-flake.hh
2x: <direct include>
2x: installable-attr-path.hh
176217 ms: ../src/libutil/error.hh (included 246 times, avg 716 ms), included via:
36x: command.hh installable-value.hh installables.hh derived-path.hh config.hh experimental-features.hh
12x: globals.hh config.hh experimental-features.hh
11x: file-system.hh file-descriptor.hh
6x: serialise.hh strings.hh
6x: <direct include>
6x: archive.hh serialise.hh strings.hh
...
173243 ms: ../src/libstore/store-api.hh (included 152 times, avg 1139 ms), included via:
55x: <direct include>
39x: command.hh installable-value.hh installables.hh
7x: libexpr.hh
4x: local-store.hh
4x: command-installable-value.hh installable-value.hh installables.hh
3x: binary-cache-store.hh
...
170482 ms: ../src/libutil/serialise.hh (included 201 times, avg 848 ms), included via:
37x: command.hh installable-value.hh installables.hh built-path.hh realisation.hh hash.hh
14x: store-api.hh nar-info.hh hash.hh
11x: <direct include>
7x: primops.hh eval.hh attr-set.hh nixexpr.hh value.hh source-path.hh archive.hh
7x: libexpr.hh value.hh source-path.hh archive.hh
6x: fetchers.hh hash.hh
...
169397 ms: ../src/libcmd/installables.hh (included 53 times, avg 3196 ms), included via:
40x: command.hh installable-value.hh
5x: command-installable-value.hh installable-value.hh
3x: installable-flake.hh installable-value.hh
2x: <direct include>
1x: installable-derived-path.hh
1x: installable-value.hh
...
159740 ms: ../src/libutil/strings.hh (included 221 times, avg 722 ms), included via:
37x: command.hh installable-value.hh installables.hh built-path.hh realisation.hh hash.hh serialise.hh
19x: <direct include>
14x: store-api.hh nar-info.hh hash.hh serialise.hh
11x: serialise.hh
7x: primops.hh eval.hh attr-set.hh nixexpr.hh value.hh source-path.hh archive.hh serialise.hh
7x: libexpr.hh value.hh source-path.hh archive.hh serialise.hh
...
156796 ms: ../src/libcmd/command.hh (included 51 times, avg 3074 ms), included via:
42x: <direct include>
7x: command-installable-value.hh
2x: installable-attr-path.hh
150392 ms: ../src/libutil/types.hh (included 251 times, avg 599 ms), included via:
36x: command.hh installable-value.hh installables.hh path.hh
11x: file-system.hh
10x: globals.hh
6x: fetchers.hh
6x: serialise.hh strings.hh error.hh
5x: archive.hh
...
133101 ms: /nix/store/644b90j1vms44nr18yw3520pzkrg4dd1-boost-1.81.0-dev/include/boost/lexical_cast.hpp (included 226 times, avg 588 ms), included via
:
37x: command.hh installable-value.hh installables.hh built-path.hh realisation.hh hash.hh serialise.hh strings.hh
19x: file-system.hh
11x: store-api.hh nar-info.hh hash.hh serialise.hh strings.hh
7x: primops.hh eval.hh attr-set.hh nixexpr.hh value.hh source-path.hh archive.hh serialise.hh strings.hh
7x: libexpr.hh value.hh source-path.hh archive.hh serialise.hh strings.hh
6x: eval.hh attr-set.hh nixexpr.hh value.hh source-path.hh archive.hh serialise.hh strings.hh
...
132887 ms: /nix/store/h2abv2l8irqj942i5rq9wbrj42kbsh5y-gcc-12.3.0/include/c++/12.3.0/memory (included 262 times, avg 507 ms), included via:
36x: command.hh installable-value.hh installables.hh path.hh types.hh ref.hh
16x: gtest.h
11x: file-system.hh types.hh ref.hh
10x: globals.hh types.hh ref.hh
10x: json.hpp
6x: serialise.hh
...
done in 0.6s.
```
After:
```
lix/lix2 » maintainers/buildtime_report.sh build
Processing all files and saving to '/home/jade/lix/lix2/maintainers/../buildtime.bin'...
done in 0.6s. Run 'ClangBuildAnalyzer --analyze /home/jade/lix/lix2/maintainers/../buildtime.bin' to analyze it.
Analyzing build trace from '/home/jade/lix/lix2/maintainers/../buildtime.bin'...
**** Time summary:
Compilation (551 times):
Parsing (frontend): 1302.1 s
Codegen & opts (backend): 956.3 s
<snip>
**** Expensive headers:
178145 ms: ../src/libutil/error.hh (included 246 times, avg 724 ms), included via:
36x: command.hh installable-value.hh installables.hh derived-path.hh config.hh experimental-features.hh
12x: globals.hh config.hh experimental-features.hh
11x: file-system.hh file-descriptor.hh
6x: <direct include>
6x: serialise.hh strings.hh
6x: fetchers.hh hash.hh serialise.hh strings.hh
...
154043 ms: ../src/libcmd/installable-value.hh (included 52 times, avg 2962 ms), included via:
40x: command.hh
5x: command-installable-value.hh
3x: installable-flake.hh
2x: <direct include>
2x: installable-attr-path.hh
153593 ms: ../src/libstore/store-api.hh (included 152 times, avg 1010 ms), included via:
55x: <direct include>
39x: command.hh installable-value.hh installables.hh
7x: libexpr.hh
4x: local-store.hh
4x: command-installable-value.hh installable-value.hh installables.hh
3x: binary-cache-store.hh
...
149948 ms: ../src/libutil/types.hh (included 251 times, avg 597 ms), included via:
36x: command.hh installable-value.hh installables.hh path.hh
11x: file-system.hh
10x: globals.hh
6x: fetchers.hh
6x: serialise.hh strings.hh error.hh
5x: archive.hh
...
144560 ms: ../src/libcmd/installables.hh (included 53 times, avg 2727 ms), included via:
40x: command.hh installable-value.hh
5x: command-installable-value.hh installable-value.hh
3x: installable-flake.hh installable-value.hh
2x: <direct include>
1x: installable-value.hh
1x: installable-derived-path.hh
...
136585 ms: ../src/libcmd/command.hh (included 51 times, avg 2678 ms), included via:
42x: <direct include>
7x: command-installable-value.hh
2x: installable-attr-path.hh
133394 ms: /nix/store/h2abv2l8irqj942i5rq9wbrj42kbsh5y-gcc-12.3.0/include/c++/12.3.0/memory (included 262 times, avg 509 ms), included via:
36x: command.hh installable-value.hh installables.hh path.hh types.hh ref.hh
16x: gtest.h
11x: file-system.hh types.hh ref.hh
10x: globals.hh types.hh ref.hh
10x: json.hpp
6x: serialise.hh
...
89315 ms: ../src/libstore/derived-path.hh (included 178 times, avg 501 ms), included via:
37x: command.hh installable-value.hh installables.hh
25x: store-api.hh realisation.hh
7x: primops.hh eval.hh attr-set.hh nixexpr.hh value.hh context.hh
6x: eval.hh attr-set.hh nixexpr.hh value.hh context.hh
6x: libexpr.hh value.hh context.hh
6x: shared.hh
...
87347 ms: /nix/store/h2abv2l8irqj942i5rq9wbrj42kbsh5y-gcc-12.3.0/include/c++/12.3.0/ostream (included 273 times, avg 319 ms), included via:
35x: command.hh installable-value.hh installables.hh path.hh types.hh ref.hh memory unique_ptr.h
12x: regex sstream istream
10x: file-system.hh types.hh ref.hh memory unique_ptr.h
10x: gtest.h memory unique_ptr.h
10x: globals.hh types.hh ref.hh memory unique_ptr.h
6x: fetchers.hh types.hh ref.hh memory unique_ptr.h
...
85249 ms: ../src/libutil/config.hh (included 213 times, avg 400 ms), included via:
37x: command.hh installable-value.hh installables.hh derived-path.hh
20x: globals.hh
20x: logging.hh
16x: store-api.hh logging.hh
6x: <direct include>
6x: eval.hh attr-set.hh nixexpr.hh value.hh context.hh derived-path.hh
...
done in 0.5s.
```
Adapated from https://git.lix.systems/lix-project/lix/commit/18aa3e1d570b4ecbb9962376e5fba5757dad8da9
2024-05-29 21:12:34 -07:00
|
|
|
std::optional<N> string2Int(const std::string_view s);
|
2021-01-08 12:51:19 +01:00
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Like string2Int(), but support an optional suffix 'K', 'M', 'G' or
|
|
|
|
* 'T' denoting a binary unit prefix.
|
|
|
|
*/
|
2021-01-08 12:51:19 +01:00
|
|
|
template<class N>
|
2021-12-31 03:16:59 +01:00
|
|
|
N string2IntWithUnitPrefix(std::string_view s)
|
2021-01-08 12:51:19 +01:00
|
|
|
{
|
2023-02-16 17:31:20 +01:00
|
|
|
uint64_t multiplier = 1;
|
2021-01-08 12:51:19 +01:00
|
|
|
if (!s.empty()) {
|
|
|
|
char u = std::toupper(*s.rbegin());
|
|
|
|
if (std::isalpha(u)) {
|
|
|
|
if (u == 'K') multiplier = 1ULL << 10;
|
|
|
|
else if (u == 'M') multiplier = 1ULL << 20;
|
|
|
|
else if (u == 'G') multiplier = 1ULL << 30;
|
|
|
|
else if (u == 'T') multiplier = 1ULL << 40;
|
|
|
|
else throw UsageError("invalid unit specifier '%1%'", u);
|
2021-12-31 03:16:59 +01:00
|
|
|
s.remove_suffix(1);
|
2021-01-08 12:51:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (auto n = string2Int<N>(s))
|
|
|
|
return *n * multiplier;
|
|
|
|
throw UsageError("'%s' is not an integer", s);
|
2009-11-24 12:26:25 +00:00
|
|
|
}
|
|
|
|
|
2024-05-10 16:49:40 +02:00
|
|
|
/**
|
|
|
|
* Pretty-print a byte value, e.g. 12433615056 is rendered as `11.6
|
2024-05-13 10:29:35 +02:00
|
|
|
* GiB`. If `align` is set, the number will be right-justified by
|
|
|
|
* padding with spaces on the left.
|
2024-05-10 16:49:40 +02:00
|
|
|
*/
|
2024-05-10 16:58:19 +02:00
|
|
|
std::string renderSize(uint64_t value, bool align = false);
|
2024-05-10 16:49:40 +02:00
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Parse a string into a float.
|
|
|
|
*/
|
2021-01-08 12:22:21 +01:00
|
|
|
template<class N>
|
Remove 100s of CPU time (10%) from build times (1465s -> 1302s)
Result's from Mic92's framework 13th Gen Intel Core i7-1360P:
Before: 3595.92s user 183.01s system 1360% cpu 4:37.74 total
After: 3486.07s user 168.93s system 1354% cpu 4:29.79 total
I saw that boost/lexical_cast was costing about 100s in CPU time on our
compiles. We can fix this trivially by doing explicit template
instantiation in exactly one place and eliminating all other includes of
it, which is a code improvement anyway by hiding the boost.
Before:
```
lix/lix2 » ClangBuildAnalyzer --analyze buildtimeold.bin
Analyzing build trace from 'buildtimeold.bin'...
**** Time summary:
Compilation (551 times):
Parsing (frontend): 1465.3 s
Codegen & opts (backend): 1110.9 s
<snip>
**** Expensive headers:
178153 ms: ../src/libcmd/installable-value.hh (included 52 times, avg 3426 ms), included via:
40x: command.hh
5x: command-installable-value.hh
3x: installable-flake.hh
2x: <direct include>
2x: installable-attr-path.hh
176217 ms: ../src/libutil/error.hh (included 246 times, avg 716 ms), included via:
36x: command.hh installable-value.hh installables.hh derived-path.hh config.hh experimental-features.hh
12x: globals.hh config.hh experimental-features.hh
11x: file-system.hh file-descriptor.hh
6x: serialise.hh strings.hh
6x: <direct include>
6x: archive.hh serialise.hh strings.hh
...
173243 ms: ../src/libstore/store-api.hh (included 152 times, avg 1139 ms), included via:
55x: <direct include>
39x: command.hh installable-value.hh installables.hh
7x: libexpr.hh
4x: local-store.hh
4x: command-installable-value.hh installable-value.hh installables.hh
3x: binary-cache-store.hh
...
170482 ms: ../src/libutil/serialise.hh (included 201 times, avg 848 ms), included via:
37x: command.hh installable-value.hh installables.hh built-path.hh realisation.hh hash.hh
14x: store-api.hh nar-info.hh hash.hh
11x: <direct include>
7x: primops.hh eval.hh attr-set.hh nixexpr.hh value.hh source-path.hh archive.hh
7x: libexpr.hh value.hh source-path.hh archive.hh
6x: fetchers.hh hash.hh
...
169397 ms: ../src/libcmd/installables.hh (included 53 times, avg 3196 ms), included via:
40x: command.hh installable-value.hh
5x: command-installable-value.hh installable-value.hh
3x: installable-flake.hh installable-value.hh
2x: <direct include>
1x: installable-derived-path.hh
1x: installable-value.hh
...
159740 ms: ../src/libutil/strings.hh (included 221 times, avg 722 ms), included via:
37x: command.hh installable-value.hh installables.hh built-path.hh realisation.hh hash.hh serialise.hh
19x: <direct include>
14x: store-api.hh nar-info.hh hash.hh serialise.hh
11x: serialise.hh
7x: primops.hh eval.hh attr-set.hh nixexpr.hh value.hh source-path.hh archive.hh serialise.hh
7x: libexpr.hh value.hh source-path.hh archive.hh serialise.hh
...
156796 ms: ../src/libcmd/command.hh (included 51 times, avg 3074 ms), included via:
42x: <direct include>
7x: command-installable-value.hh
2x: installable-attr-path.hh
150392 ms: ../src/libutil/types.hh (included 251 times, avg 599 ms), included via:
36x: command.hh installable-value.hh installables.hh path.hh
11x: file-system.hh
10x: globals.hh
6x: fetchers.hh
6x: serialise.hh strings.hh error.hh
5x: archive.hh
...
133101 ms: /nix/store/644b90j1vms44nr18yw3520pzkrg4dd1-boost-1.81.0-dev/include/boost/lexical_cast.hpp (included 226 times, avg 588 ms), included via
:
37x: command.hh installable-value.hh installables.hh built-path.hh realisation.hh hash.hh serialise.hh strings.hh
19x: file-system.hh
11x: store-api.hh nar-info.hh hash.hh serialise.hh strings.hh
7x: primops.hh eval.hh attr-set.hh nixexpr.hh value.hh source-path.hh archive.hh serialise.hh strings.hh
7x: libexpr.hh value.hh source-path.hh archive.hh serialise.hh strings.hh
6x: eval.hh attr-set.hh nixexpr.hh value.hh source-path.hh archive.hh serialise.hh strings.hh
...
132887 ms: /nix/store/h2abv2l8irqj942i5rq9wbrj42kbsh5y-gcc-12.3.0/include/c++/12.3.0/memory (included 262 times, avg 507 ms), included via:
36x: command.hh installable-value.hh installables.hh path.hh types.hh ref.hh
16x: gtest.h
11x: file-system.hh types.hh ref.hh
10x: globals.hh types.hh ref.hh
10x: json.hpp
6x: serialise.hh
...
done in 0.6s.
```
After:
```
lix/lix2 » maintainers/buildtime_report.sh build
Processing all files and saving to '/home/jade/lix/lix2/maintainers/../buildtime.bin'...
done in 0.6s. Run 'ClangBuildAnalyzer --analyze /home/jade/lix/lix2/maintainers/../buildtime.bin' to analyze it.
Analyzing build trace from '/home/jade/lix/lix2/maintainers/../buildtime.bin'...
**** Time summary:
Compilation (551 times):
Parsing (frontend): 1302.1 s
Codegen & opts (backend): 956.3 s
<snip>
**** Expensive headers:
178145 ms: ../src/libutil/error.hh (included 246 times, avg 724 ms), included via:
36x: command.hh installable-value.hh installables.hh derived-path.hh config.hh experimental-features.hh
12x: globals.hh config.hh experimental-features.hh
11x: file-system.hh file-descriptor.hh
6x: <direct include>
6x: serialise.hh strings.hh
6x: fetchers.hh hash.hh serialise.hh strings.hh
...
154043 ms: ../src/libcmd/installable-value.hh (included 52 times, avg 2962 ms), included via:
40x: command.hh
5x: command-installable-value.hh
3x: installable-flake.hh
2x: <direct include>
2x: installable-attr-path.hh
153593 ms: ../src/libstore/store-api.hh (included 152 times, avg 1010 ms), included via:
55x: <direct include>
39x: command.hh installable-value.hh installables.hh
7x: libexpr.hh
4x: local-store.hh
4x: command-installable-value.hh installable-value.hh installables.hh
3x: binary-cache-store.hh
...
149948 ms: ../src/libutil/types.hh (included 251 times, avg 597 ms), included via:
36x: command.hh installable-value.hh installables.hh path.hh
11x: file-system.hh
10x: globals.hh
6x: fetchers.hh
6x: serialise.hh strings.hh error.hh
5x: archive.hh
...
144560 ms: ../src/libcmd/installables.hh (included 53 times, avg 2727 ms), included via:
40x: command.hh installable-value.hh
5x: command-installable-value.hh installable-value.hh
3x: installable-flake.hh installable-value.hh
2x: <direct include>
1x: installable-value.hh
1x: installable-derived-path.hh
...
136585 ms: ../src/libcmd/command.hh (included 51 times, avg 2678 ms), included via:
42x: <direct include>
7x: command-installable-value.hh
2x: installable-attr-path.hh
133394 ms: /nix/store/h2abv2l8irqj942i5rq9wbrj42kbsh5y-gcc-12.3.0/include/c++/12.3.0/memory (included 262 times, avg 509 ms), included via:
36x: command.hh installable-value.hh installables.hh path.hh types.hh ref.hh
16x: gtest.h
11x: file-system.hh types.hh ref.hh
10x: globals.hh types.hh ref.hh
10x: json.hpp
6x: serialise.hh
...
89315 ms: ../src/libstore/derived-path.hh (included 178 times, avg 501 ms), included via:
37x: command.hh installable-value.hh installables.hh
25x: store-api.hh realisation.hh
7x: primops.hh eval.hh attr-set.hh nixexpr.hh value.hh context.hh
6x: eval.hh attr-set.hh nixexpr.hh value.hh context.hh
6x: libexpr.hh value.hh context.hh
6x: shared.hh
...
87347 ms: /nix/store/h2abv2l8irqj942i5rq9wbrj42kbsh5y-gcc-12.3.0/include/c++/12.3.0/ostream (included 273 times, avg 319 ms), included via:
35x: command.hh installable-value.hh installables.hh path.hh types.hh ref.hh memory unique_ptr.h
12x: regex sstream istream
10x: file-system.hh types.hh ref.hh memory unique_ptr.h
10x: gtest.h memory unique_ptr.h
10x: globals.hh types.hh ref.hh memory unique_ptr.h
6x: fetchers.hh types.hh ref.hh memory unique_ptr.h
...
85249 ms: ../src/libutil/config.hh (included 213 times, avg 400 ms), included via:
37x: command.hh installable-value.hh installables.hh derived-path.hh
20x: globals.hh
20x: logging.hh
16x: store-api.hh logging.hh
6x: <direct include>
6x: eval.hh attr-set.hh nixexpr.hh value.hh context.hh derived-path.hh
...
done in 0.5s.
```
Adapated from https://git.lix.systems/lix-project/lix/commit/18aa3e1d570b4ecbb9962376e5fba5757dad8da9
2024-05-29 21:12:34 -07:00
|
|
|
std::optional<N> string2Float(const std::string_view s);
|
2016-01-05 00:40:40 +01:00
|
|
|
|
2004-09-10 13:32:08 +00:00
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Convert a little-endian integer to host order.
|
|
|
|
*/
|
2022-12-07 12:58:58 +01:00
|
|
|
template<typename T>
|
|
|
|
T readLittleEndian(unsigned char * p)
|
|
|
|
{
|
|
|
|
T x = 0;
|
2022-12-12 12:40:51 +01:00
|
|
|
for (size_t i = 0; i < sizeof(x); ++i, ++p) {
|
|
|
|
x |= ((T) *p) << (i * 8);
|
|
|
|
}
|
2022-12-07 12:58:58 +01:00
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* @return true iff `s` starts with `prefix`.
|
|
|
|
*/
|
2020-06-12 21:12:36 +00:00
|
|
|
bool hasPrefix(std::string_view s, std::string_view prefix);
|
2016-04-29 21:04:40 +02:00
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* @return true iff `s` ends in `suffix`.
|
|
|
|
*/
|
2019-12-05 19:11:09 +01:00
|
|
|
bool hasSuffix(std::string_view s, std::string_view suffix);
|
2008-08-25 13:31:57 +00:00
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Convert a string to lower case.
|
|
|
|
*/
|
2023-11-02 15:49:22 +01:00
|
|
|
std::string toLower(std::string s);
|
2016-09-14 14:42:15 +02:00
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Escape a string as a shell word.
|
|
|
|
*/
|
2022-01-21 17:55:51 +01:00
|
|
|
std::string shellEscape(const std::string_view s);
|
2017-08-25 15:57:49 +02:00
|
|
|
|
|
|
|
|
2021-08-28 16:26:53 -04:00
|
|
|
/* Exception handling in destructors: print an error message, then
|
|
|
|
ignore the exception. */
|
2022-12-02 15:03:40 +01:00
|
|
|
void ignoreException(Verbosity lvl = lvlError);
|
2008-09-17 10:02:55 +00:00
|
|
|
|
|
|
|
|
2014-08-20 16:01:16 +02:00
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Tree formatting.
|
|
|
|
*/
|
2020-03-24 14:17:10 +01:00
|
|
|
constexpr char treeConn[] = "├───";
|
|
|
|
constexpr char treeLast[] = "└───";
|
|
|
|
constexpr char treeLine[] = "│ ";
|
|
|
|
constexpr char treeNull[] = " ";
|
|
|
|
|
2014-08-20 16:01:16 +02:00
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Base64 encoding/decoding.
|
|
|
|
*/
|
2022-02-25 16:00:00 +01:00
|
|
|
std::string base64Encode(std::string_view s);
|
|
|
|
std::string base64Decode(std::string_view s);
|
2015-02-09 15:09:39 +01:00
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Remove common leading whitespace from the lines in the string
|
|
|
|
* 's'. For example, if every line is indented by at least 3 spaces,
|
|
|
|
* then we remove 3 spaces from the start of every line.
|
|
|
|
*/
|
2020-08-20 12:21:46 +02:00
|
|
|
std::string stripIndentation(std::string_view s);
|
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Get the prefix of 's' up to and excluding the next line break (LF
|
|
|
|
* optionally preceded by CR), and the remainder following the line
|
|
|
|
* break.
|
|
|
|
*/
|
2022-12-07 12:58:58 +01:00
|
|
|
std::pair<std::string_view, std::string_view> getLine(std::string_view s);
|
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Get a value for the specified key from an associate container.
|
|
|
|
*/
|
Eliminate the "store" global variable
Also, move a few free-standing functions into StoreAPI and Derivation.
Also, introduce a non-nullable smart pointer, ref<T>, which is just a
wrapper around std::shared_ptr ensuring that the pointer is never
null. (For reference-counted values, this is better than passing a
"T&", because the latter doesn't maintain the refcount. Usually, the
caller will have a shared_ptr keeping the value alive, but that's not
always the case, e.g., when passing a reference to a std::thread via
std::bind.)
2016-02-04 14:28:26 +01:00
|
|
|
template <class T>
|
2022-05-04 07:44:32 +02:00
|
|
|
const typename T::mapped_type * get(const T & map, const typename T::key_type & key)
|
Eliminate the "store" global variable
Also, move a few free-standing functions into StoreAPI and Derivation.
Also, introduce a non-nullable smart pointer, ref<T>, which is just a
wrapper around std::shared_ptr ensuring that the pointer is never
null. (For reference-counted values, this is better than passing a
"T&", because the latter doesn't maintain the refcount. Usually, the
caller will have a shared_ptr keeping the value alive, but that's not
always the case, e.g., when passing a reference to a std::thread via
std::bind.)
2016-02-04 14:28:26 +01:00
|
|
|
{
|
|
|
|
auto i = map.find(key);
|
2022-05-04 07:44:32 +02:00
|
|
|
if (i == map.end()) return nullptr;
|
|
|
|
return &i->second;
|
Eliminate the "store" global variable
Also, move a few free-standing functions into StoreAPI and Derivation.
Also, introduce a non-nullable smart pointer, ref<T>, which is just a
wrapper around std::shared_ptr ensuring that the pointer is never
null. (For reference-counted values, this is better than passing a
"T&", because the latter doesn't maintain the refcount. Usually, the
caller will have a shared_ptr keeping the value alive, but that's not
always the case, e.g., when passing a reference to a std::thread via
std::bind.)
2016-02-04 14:28:26 +01:00
|
|
|
}
|
|
|
|
|
2022-05-04 07:44:32 +02:00
|
|
|
template <class T>
|
|
|
|
typename T::mapped_type * get(T & map, const typename T::key_type & key)
|
|
|
|
{
|
|
|
|
auto i = map.find(key);
|
|
|
|
if (i == map.end()) return nullptr;
|
|
|
|
return &i->second;
|
|
|
|
}
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Get a value for the specified key from an associate container, or a default value if the key isn't present.
|
|
|
|
*/
|
2022-05-04 07:44:32 +02:00
|
|
|
template <class T>
|
|
|
|
const typename T::mapped_type & getOr(T & map,
|
|
|
|
const typename T::key_type & key,
|
|
|
|
const typename T::mapped_type & defaultValue)
|
|
|
|
{
|
|
|
|
auto i = map.find(key);
|
|
|
|
if (i == map.end()) return defaultValue;
|
|
|
|
return i->second;
|
|
|
|
}
|
Eliminate the "store" global variable
Also, move a few free-standing functions into StoreAPI and Derivation.
Also, introduce a non-nullable smart pointer, ref<T>, which is just a
wrapper around std::shared_ptr ensuring that the pointer is never
null. (For reference-counted values, this is better than passing a
"T&", because the latter doesn't maintain the refcount. Usually, the
caller will have a shared_ptr keeping the value alive, but that's not
always the case, e.g., when passing a reference to a std::thread via
std::bind.)
2016-02-04 14:28:26 +01:00
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Remove and return the first item from a container.
|
|
|
|
*/
|
2021-08-20 11:18:35 +02:00
|
|
|
template <class T>
|
|
|
|
std::optional<typename T::value_type> remove_begin(T & c)
|
|
|
|
{
|
|
|
|
auto i = c.begin();
|
|
|
|
if (i == c.end()) return {};
|
|
|
|
auto v = std::move(*i);
|
|
|
|
c.erase(i);
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Remove and return the first item from a container.
|
|
|
|
*/
|
2021-10-14 12:31:21 +02:00
|
|
|
template <class T>
|
|
|
|
std::optional<typename T::value_type> pop(T & c)
|
|
|
|
{
|
|
|
|
if (c.empty()) return {};
|
|
|
|
auto v = std::move(c.front());
|
|
|
|
c.pop();
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-27 22:16:01 +02:00
|
|
|
template<typename T>
|
2020-09-21 18:40:11 +02:00
|
|
|
class Callback;
|
2016-09-16 18:54:14 +02:00
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* A RAII helper that increments a counter on construction and
|
|
|
|
* decrements it on destruction.
|
|
|
|
*/
|
2017-08-14 22:42:17 +02:00
|
|
|
template<typename T>
|
|
|
|
struct MaintainCount
|
|
|
|
{
|
|
|
|
T & counter;
|
|
|
|
long delta;
|
|
|
|
MaintainCount(T & counter, long delta = 1) : counter(counter), delta(delta) { counter += delta; }
|
|
|
|
~MaintainCount() { counter -= delta; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* A Rust/Python-like enumerate() iterator adapter.
|
|
|
|
*
|
|
|
|
* Borrowed from http://reedbeta.com/blog/python-like-enumerate-in-cpp17.
|
|
|
|
*/
|
2020-03-24 14:17:10 +01:00
|
|
|
template <typename T,
|
|
|
|
typename TIter = decltype(std::begin(std::declval<T>())),
|
|
|
|
typename = decltype(std::end(std::declval<T>()))>
|
|
|
|
constexpr auto enumerate(T && iterable)
|
|
|
|
{
|
|
|
|
struct iterator
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
TIter iter;
|
2023-04-02 18:11:16 -04:00
|
|
|
constexpr bool operator != (const iterator & other) const { return iter != other.iter; }
|
|
|
|
constexpr void operator ++ () { ++i; ++iter; }
|
|
|
|
constexpr auto operator * () const { return std::tie(i, *iter); }
|
2020-03-24 14:17:10 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct iterable_wrapper
|
|
|
|
{
|
|
|
|
T iterable;
|
2023-04-02 18:11:16 -04:00
|
|
|
constexpr auto begin() { return iterator{ 0, std::begin(iterable) }; }
|
|
|
|
constexpr auto end() { return iterator{ 0, std::end(iterable) }; }
|
2020-03-24 14:17:10 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
return iterable_wrapper{ std::forward<T>(iterable) };
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* C++17 std::visit boilerplate
|
|
|
|
*/
|
2020-07-12 22:15:14 +00:00
|
|
|
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
|
|
|
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
|
|
|
|
|
|
|
|
|
2020-10-06 10:40:49 +02:00
|
|
|
std::string showBytes(uint64_t bytes);
|
|
|
|
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Provide an addition operator between strings and string_views
|
|
|
|
* inexplicably omitted from the standard library.
|
|
|
|
*/
|
2022-05-09 14:28:27 +02:00
|
|
|
inline std::string operator + (const std::string & s1, std::string_view s2)
|
|
|
|
{
|
|
|
|
auto s = s1;
|
|
|
|
s.append(s2);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline std::string operator + (std::string && s, std::string_view s2)
|
|
|
|
{
|
|
|
|
s.append(s2);
|
2022-06-02 16:48:53 +02:00
|
|
|
return std::move(s);
|
2022-05-09 14:28:27 +02:00
|
|
|
}
|
|
|
|
|
2022-12-07 12:58:58 +01:00
|
|
|
inline std::string operator + (std::string_view s1, const char * s2)
|
|
|
|
{
|
2022-12-12 12:36:19 +01:00
|
|
|
std::string s;
|
|
|
|
s.reserve(s1.size() + strlen(s2));
|
|
|
|
s.append(s1);
|
2022-12-07 12:58:58 +01:00
|
|
|
s.append(s2);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2006-09-04 21:06:23 +00:00
|
|
|
}
|