2014-07-10 17:50:51 +03:00
# include "util.hh"
2023-10-25 07:43:36 +03:00
# include "fmt.hh"
2024-08-05 19:05:29 +03:00
# include "file-path.hh"
2024-09-30 12:49:53 +03:00
# include "signals.hh"
2014-07-10 17:50:51 +03:00
2021-09-08 13:20:08 +03:00
# include <array>
2017-01-17 19:21:02 +02:00
# include <cctype>
# include <iostream>
2021-08-28 23:26:53 +03:00
# include <regex>
2024-01-03 22:02:20 +02:00
# include <sodium.h>
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-30 07:12:34 +03:00
# include <boost/lexical_cast.hpp>
# include <stdint.h>
2023-02-10 15:38:14 +02:00
2024-03-01 23:07:01 +02:00
# ifdef NDEBUG
# error "Nix may not be built with assertions disabled (i.e. with -DNDEBUG)."
# endif
2023-10-25 07:43:36 +03:00
namespace nix {
2014-07-10 17:50:51 +03:00
2023-10-25 07:43:36 +03:00
void initLibUtil ( ) {
// Check that exception handling works. Exception handling has been observed
// not to work on darwin when the linker flags aren't quite right.
// In this case we don't want to expose the user to some unrelated uncaught
// exception, but rather tell them exactly that exception handling is
// broken.
// When exception handling fails, the message tends to be printed by the
// C++ runtime, followed by an abort.
// For example on macOS we might see an error such as
2023-12-02 00:03:28 +02:00
// libc++abi: terminating with uncaught exception of type nix::SystemError: error: C++ exception handling is broken. This would appear to be a problem with the way Nix was compiled and/or linked and/or loaded.
2023-10-25 07:43:36 +03:00
bool caught = false ;
try {
throwExceptionSelfCheck ( ) ;
} catch ( const nix : : Error & _e ) {
caught = true ;
}
// This is not actually the main point of this check, but let's make sure anyway:
assert ( caught ) ;
2024-01-03 22:02:20 +02:00
if ( sodium_init ( ) = = - 1 )
throw Error ( " could not initialise libsodium " ) ;
2014-07-10 17:50:51 +03:00
}
2023-10-25 07:43:36 +03:00
//////////////////////////////////////////////////////////////////////
2014-07-10 17:50:51 +03:00
2015-06-09 11:50:55 +03:00
std : : vector < char * > stringsToCharPtrs ( const Strings & ss )
2014-12-12 16:01:16 +02:00
{
2015-06-09 11:50:55 +03:00
std : : vector < char * > res ;
for ( auto & s : ss ) res . push_back ( ( char * ) s . c_str ( ) ) ;
2014-12-12 16:01:16 +02:00
res . push_back ( 0 ) ;
return res ;
}
2004-06-20 16:37:51 +03:00
2004-06-22 12:51:44 +03:00
//////////////////////////////////////////////////////////////////////
2022-02-25 17:00:00 +02:00
std : : string chomp ( std : : string_view s )
2012-08-01 18:19:24 +03:00
{
size_t i = s . find_last_not_of ( " \n \r \t " ) ;
2023-11-02 11:13:55 +02:00
return i = = s . npos ? " " : std : : string ( s , 0 , i + 1 ) ;
2012-08-01 18:19:24 +03:00
}
2022-02-25 17:00:00 +02:00
std : : string trim ( std : : string_view s , std : : string_view whitespace )
2015-04-09 12:42:04 +03:00
{
auto i = s . find_first_not_of ( whitespace ) ;
2022-03-03 12:11:16 +02:00
if ( i = = s . npos ) return " " ;
2015-04-09 12:42:04 +03:00
auto j = s . find_last_not_of ( whitespace ) ;
2022-03-03 12:11:16 +02:00
return std : : string ( s , i , j = = s . npos ? j : j - i + 1 ) ;
2015-04-09 12:42:04 +03:00
}
2022-02-25 17:00:00 +02:00
std : : string replaceStrings (
std : : string res ,
std : : string_view from ,
std : : string_view to )
2015-06-17 17:20:11 +03:00
{
2020-11-10 15:59:03 +02:00
if ( from . empty ( ) ) return res ;
2015-06-17 17:20:11 +03:00
size_t pos = 0 ;
2023-11-02 11:13:55 +02:00
while ( ( pos = res . find ( from , pos ) ) ! = res . npos ) {
2015-06-17 17:20:11 +03:00
res . replace ( pos , from . size ( ) , to ) ;
pos + = to . size ( ) ;
}
return res ;
}
2022-02-25 17:00:00 +02:00
std : : string rewriteStrings ( std : : string s , const StringMap & rewrites )
2018-03-30 01:56:13 +03:00
{
for ( auto & i : rewrites ) {
if ( i . first = = i . second ) continue ;
size_t j = 0 ;
2023-11-02 11:13:55 +02:00
while ( ( j = s . find ( i . first , j ) ) ! = s . npos )
2018-03-30 01:56:13 +03:00
s . replace ( j , i . first . size ( ) , i . second ) ;
}
return s ;
}
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-30 07:12:34 +03:00
template < class N >
std : : optional < N > string2Int ( const std : : string_view s )
{
if ( s . substr ( 0 , 1 ) = = " - " & & ! std : : numeric_limits < N > : : is_signed )
return std : : nullopt ;
try {
return boost : : lexical_cast < N > ( s . data ( ) , s . size ( ) ) ;
} catch ( const boost : : bad_lexical_cast & ) {
return std : : nullopt ;
}
}
// Explicitly instantiated in one place for faster compilation
template std : : optional < unsigned char > string2Int < unsigned char > ( const std : : string_view s ) ;
template std : : optional < unsigned short > string2Int < unsigned short > ( const std : : string_view s ) ;
template std : : optional < unsigned int > string2Int < unsigned int > ( const std : : string_view s ) ;
template std : : optional < unsigned long > string2Int < unsigned long > ( const std : : string_view s ) ;
template std : : optional < unsigned long long > string2Int < unsigned long long > ( const std : : string_view s ) ;
template std : : optional < signed char > string2Int < signed char > ( const std : : string_view s ) ;
template std : : optional < signed short > string2Int < signed short > ( const std : : string_view s ) ;
template std : : optional < signed int > string2Int < signed int > ( const std : : string_view s ) ;
template std : : optional < signed long > string2Int < signed long > ( const std : : string_view s ) ;
template std : : optional < signed long long > string2Int < signed long long > ( const std : : string_view s ) ;
template < class N >
std : : optional < N > string2Float ( const std : : string_view s )
{
try {
return boost : : lexical_cast < N > ( s . data ( ) , s . size ( ) ) ;
} catch ( const boost : : bad_lexical_cast & ) {
return std : : nullopt ;
}
}
template std : : optional < double > string2Float < double > ( const std : : string_view s ) ;
template std : : optional < float > string2Float < float > ( const std : : string_view s ) ;
2018-03-30 01:56:13 +03:00
2024-05-10 17:58:19 +03:00
std : : string renderSize ( uint64_t value , bool align )
2024-05-10 17:49:40 +03:00
{
static const std : : array < char , 9 > prefixes { {
' K ' , ' K ' , ' M ' , ' G ' , ' T ' , ' P ' , ' E ' , ' Z ' , ' Y '
} } ;
size_t power = 0 ;
double res = value ;
while ( res > 1024 & & power < prefixes . size ( ) ) {
+ + power ;
res / = 1024 ;
}
2024-05-10 17:58:19 +03:00
return fmt ( align ? " %6.1f %ciB " : " %.1f %ciB " , power = = 0 ? res / 1024 : res , prefixes . at ( power ) ) ;
2024-05-10 17:49:40 +03:00
}
2020-06-13 00:12:36 +03:00
bool hasPrefix ( std : : string_view s , std : : string_view prefix )
2016-04-29 22:04:40 +03:00
{
2017-05-01 18:28:19 +03:00
return s . compare ( 0 , prefix . size ( ) , prefix ) = = 0 ;
2016-04-29 22:04:40 +03:00
}
2019-12-05 20:11:09 +02:00
bool hasSuffix ( std : : string_view s , std : : string_view suffix )
2008-08-25 16:31:57 +03:00
{
2019-12-05 20:11:09 +02:00
return s . size ( ) > = suffix . size ( )
& & s . substr ( s . size ( ) - suffix . size ( ) ) = = suffix ;
2008-08-25 16:31:57 +03:00
}
2023-11-02 16:49:22 +02:00
std : : string toLower ( std : : string s )
2016-09-14 15:42:15 +03:00
{
2023-11-02 16:49:22 +02:00
for ( auto & c : s )
2016-09-14 15:42:15 +03:00
c = std : : tolower ( c ) ;
2023-11-02 16:49:22 +02:00
return s ;
2016-09-14 15:42:15 +03:00
}
2022-01-21 18:55:51 +02:00
std : : string shellEscape ( const std : : string_view s )
2017-10-25 14:01:50 +03:00
{
2022-01-21 18:55:51 +02:00
std : : string r ;
r . reserve ( s . size ( ) + 2 ) ;
2023-11-02 16:49:22 +02:00
r + = ' \' ' ;
2017-10-25 14:01:50 +03:00
for ( auto & i : s )
if ( i = = ' \' ' ) r + = " ' \\ '' " ; else r + = i ;
r + = ' \' ' ;
return r ;
}
2024-09-30 12:49:53 +03:00
void ignoreExceptionInDestructor ( Verbosity lvl )
2007-05-01 18:16:17 +03:00
{
2022-02-07 18:14:57 +02:00
/* Make sure no exceptions leave this function.
printError ( ) also throws when remote is closed . */
2007-05-01 18:16:17 +03:00
try {
2022-02-07 18:14:57 +02:00
try {
throw ;
} catch ( std : : exception & e ) {
2022-12-02 16:03:40 +02:00
printMsg ( lvl , " error (ignored): %1% " , e . what ( ) ) ;
2022-02-07 18:14:57 +02:00
}
} catch ( . . . ) { }
2007-05-01 18:16:17 +03:00
}
2024-09-30 12:49:53 +03:00
void ignoreExceptionExceptInterrupt ( Verbosity lvl )
{
try {
throw ;
} catch ( const Interrupted & e ) {
throw ;
} catch ( std : : exception & e ) {
printMsg ( lvl , " error (ignored): %1% " , e . what ( ) ) ;
}
}
2014-08-20 17:01:16 +03:00
2021-10-17 10:51:33 +03:00
constexpr char base64Chars [ ] = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ " ;
2015-02-09 16:09:39 +02:00
2022-02-25 17:00:00 +02:00
std : : string base64Encode ( std : : string_view s )
2015-02-09 16:09:39 +02:00
{
2022-02-25 17:00:00 +02:00
std : : string res ;
2022-04-05 22:16:11 +03:00
res . reserve ( ( s . size ( ) + 2 ) / 3 * 4 ) ;
2015-02-09 16:09:39 +02:00
int data = 0 , nbits = 0 ;
for ( char c : s ) {
data = data < < 8 | ( unsigned char ) c ;
nbits + = 8 ;
while ( nbits > = 6 ) {
nbits - = 6 ;
res . push_back ( base64Chars [ data > > nbits & 0x3f ] ) ;
}
}
if ( nbits ) res . push_back ( base64Chars [ data < < ( 6 - nbits ) & 0x3f ] ) ;
while ( res . size ( ) % 4 ) res . push_back ( ' = ' ) ;
return res ;
}
2022-02-25 17:00:00 +02:00
std : : string base64Decode ( std : : string_view s )
2015-02-09 16:09:39 +02:00
{
2021-10-17 10:51:33 +03:00
constexpr char npos = - 1 ;
2023-11-02 16:50:00 +02:00
constexpr std : : array < char , 256 > base64DecodeChars = [ & ] {
2021-10-17 10:51:33 +03:00
std : : array < char , 256 > result { } ;
for ( auto & c : result )
c = npos ;
2015-02-09 16:09:39 +02:00
for ( int i = 0 ; i < 64 ; i + + )
2021-10-17 10:51:33 +03:00
result [ base64Chars [ i ] ] = i ;
return result ;
} ( ) ;
2015-02-09 16:09:39 +02:00
2022-02-25 17:00:00 +02:00
std : : string res ;
2022-04-05 22:16:11 +03:00
// Some sequences are missing the padding consisting of up to two '='.
// vvv
res . reserve ( ( s . size ( ) + 2 ) / 4 * 3 ) ;
2015-02-09 16:09:39 +02:00
unsigned int d = 0 , bits = 0 ;
for ( char c : s ) {
if ( c = = ' = ' ) break ;
if ( c = = ' \n ' ) continue ;
2021-07-30 21:08:54 +03:00
char digit = base64DecodeChars [ ( unsigned char ) c ] ;
2024-09-20 17:41:45 +03:00
if ( digit = = npos )
2024-09-17 22:25:30 +03:00
throw FormatError ( " invalid character in Base64 string: '%c' " , c ) ;
2015-02-09 16:09:39 +02:00
bits + = 6 ;
d = d < < 6 | digit ;
if ( bits > = 8 ) {
res . push_back ( d > > ( bits - 8 ) & 0xff ) ;
bits - = 8 ;
}
}
return res ;
}
2020-08-20 13:21:46 +03:00
std : : string stripIndentation ( std : : string_view s )
{
size_t minIndent = 10000 ;
size_t curIndent = 0 ;
bool atStartOfLine = true ;
for ( auto & c : s ) {
if ( atStartOfLine & & c = = ' ' )
curIndent + + ;
else if ( c = = ' \n ' ) {
if ( atStartOfLine )
minIndent = std : : max ( minIndent , curIndent ) ;
curIndent = 0 ;
atStartOfLine = true ;
} else {
if ( atStartOfLine ) {
minIndent = std : : min ( minIndent , curIndent ) ;
atStartOfLine = false ;
}
}
}
std : : string res ;
size_t pos = 0 ;
while ( pos < s . size ( ) ) {
auto eol = s . find ( ' \n ' , pos ) ;
if ( eol = = s . npos ) eol = s . size ( ) ;
if ( eol - pos > minIndent )
res . append ( s . substr ( pos + minIndent , eol - pos - minIndent ) ) ;
res . push_back ( ' \n ' ) ;
pos = eol + 1 ;
}
return res ;
}
2022-12-07 13:58:58 +02:00
std : : pair < std : : string_view , std : : string_view > getLine ( std : : string_view s )
{
auto newline = s . find ( ' \n ' ) ;
if ( newline = = s . npos ) {
return { s , " " } ;
} else {
auto line = s . substr ( 0 , newline ) ;
if ( ! line . empty ( ) & & line [ line . size ( ) - 1 ] = = ' \r ' )
line = line . substr ( 0 , line . size ( ) - 1 ) ;
return { line , s . substr ( newline + 1 ) } ;
}
}
2022-02-25 17:00:00 +02:00
std : : string showBytes ( uint64_t bytes )
2020-10-06 11:40:49 +03:00
{
return fmt ( " %.2f MiB " , bytes / ( 1024.0 * 1024.0 ) ) ;
}
2006-09-05 00:06:23 +03:00
}