/src/solidity/libsolutil/StringUtils.h
Line | Count | Source |
1 | | /* |
2 | | This file is part of solidity. |
3 | | |
4 | | solidity is free software: you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation, either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | solidity is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with solidity. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | // SPDX-License-Identifier: GPL-3.0 |
18 | | /** @file StringUtils.h |
19 | | * @author Balajiganapathi S <balajiganapathi.s@gmail.com> |
20 | | * @date 2017 |
21 | | * |
22 | | * String routines |
23 | | */ |
24 | | |
25 | | #pragma once |
26 | | |
27 | | #include <libsolutil/CommonData.h> |
28 | | #include <libsolutil/Numeric.h> |
29 | | |
30 | | #include <algorithm> |
31 | | #include <charconv> |
32 | | #include <limits> |
33 | | #include <locale> |
34 | | #include <optional> |
35 | | #include <string> |
36 | | #include <vector> |
37 | | |
38 | | namespace solidity::util |
39 | | { |
40 | | |
41 | | // Calculates the Damerau–Levenshtein distance between _str1 and _str2 and returns true if that distance is not greater than _maxDistance |
42 | | // if _lenThreshold > 0 and the product of the strings length is greater than _lenThreshold, the function will return false |
43 | | bool stringWithinDistance(std::string const& _str1, std::string const& _str2, size_t _maxDistance, size_t _lenThreshold = 0); |
44 | | // Calculates the Damerau–Levenshtein distance between _str1 and _str2 |
45 | | size_t stringDistance(std::string const& _str1, std::string const& _str2); |
46 | | // Return a string having elements of suggestions as quoted, alternative suggestions. e.g. "a", "b" or "c" |
47 | | std::string quotedAlternativesList(std::vector<std::string> const& suggestions); |
48 | | |
49 | | /// @returns a string containing a comma-separated list of variable names consisting of @a _baseName suffixed |
50 | | /// with increasing integers in the range [@a _startSuffix, @a _endSuffix), if @a _startSuffix < @a _endSuffix, |
51 | | /// and with decreasing integers in the range [@a _endSuffix, @a _startSuffix), if @a _endSuffix < @a _startSuffix. |
52 | | /// If @a _startSuffix == @a _endSuffix, the empty string is returned. |
53 | | std::string suffixedVariableNameList(std::string const& _baseName, size_t _startSuffix, size_t _endSuffix); |
54 | | |
55 | | /// Joins collection of strings into one string with separators between, last separator can be different. |
56 | | /// @param _list collection of strings to join |
57 | | /// @param _separator defaults to ", " |
58 | | /// @param _lastSeparator (optional) will be used to separate last two strings instead of _separator |
59 | | /// @example join(vector<string>{"a", "b", "c"}, "; ", " or ") == "a; b or c" |
60 | | template<class T> |
61 | | std::string joinHumanReadable |
62 | | ( |
63 | | T const& _list, |
64 | | std::string const& _separator = ", ", |
65 | | std::string const& _lastSeparator = "" |
66 | | ) |
67 | 22.2M | { |
68 | 22.2M | auto const itEnd = end(_list); |
69 | | |
70 | 22.2M | std::stringstream result; |
71 | | |
72 | 22.6M | for (auto it = begin(_list); it != itEnd; ) |
73 | 493k | { |
74 | 493k | auto const& element = *it; |
75 | 493k | bool first = (it == begin(_list)); |
76 | 493k | ++it; |
77 | 493k | if (!first) |
78 | 64.6k | { |
79 | 64.6k | if (it == itEnd && !_lastSeparator.empty()) |
80 | 980 | result << _lastSeparator; // last iteration |
81 | 63.6k | else |
82 | 63.6k | result << _separator; |
83 | 64.6k | } |
84 | 493k | result << element; |
85 | 493k | } |
86 | | |
87 | 22.2M | return result.str(); |
88 | 22.2M | } Parser.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadable<ranges::transform_view<ranges::ref_view<std::__1::vector<solidity::langutil::Token, std::__1::allocator<solidity::langutil::Token> > const>, solidity::frontend::Parser::parseUsingDirective()::$_0> >(ranges::transform_view<ranges::ref_view<std::__1::vector<solidity::langutil::Token, std::__1::allocator<solidity::langutil::Token> > const>, solidity::frontend::Parser::parseUsingDirective()::$_0> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 67 | 114 | { | 68 | 114 | auto const itEnd = end(_list); | 69 | | | 70 | 114 | std::stringstream result; | 71 | | | 72 | 1.82k | for (auto it = begin(_list); it != itEnd; ) | 73 | 1.71k | { | 74 | 1.71k | auto const& element = *it; | 75 | 1.71k | bool first = (it == begin(_list)); | 76 | 1.71k | ++it; | 77 | 1.71k | if (!first) | 78 | 1.59k | { | 79 | 1.59k | if (it == itEnd && !_lastSeparator.empty()) | 80 | 0 | result << _lastSeparator; // last iteration | 81 | 1.59k | else | 82 | 1.59k | result << _separator; | 83 | 1.59k | } | 84 | 1.71k | result << element; | 85 | 1.71k | } | 86 | | | 87 | 114 | return result.str(); | 88 | 114 | } |
DeclarationTypeChecker.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadable<ranges::transform_view<ranges::ref_view<std::__1::set<solidity::frontend::VariableDeclaration::Location, std::__1::less<solidity::frontend::VariableDeclaration::Location>, std::__1::allocator<solidity::frontend::VariableDeclaration::Location> > >, solidity::frontend::DeclarationTypeChecker::endVisit(solidity::frontend::VariableDeclaration const&)::$_0> >(ranges::transform_view<ranges::ref_view<std::__1::set<solidity::frontend::VariableDeclaration::Location, std::__1::less<solidity::frontend::VariableDeclaration::Location>, std::__1::allocator<solidity::frontend::VariableDeclaration::Location> > >, solidity::frontend::DeclarationTypeChecker::endVisit(solidity::frontend::VariableDeclaration const&)::$_0> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 67 | 82 | { | 68 | 82 | auto const itEnd = end(_list); | 69 | | | 70 | 82 | std::stringstream result; | 71 | | | 72 | 273 | for (auto it = begin(_list); it != itEnd; ) | 73 | 191 | { | 74 | 191 | auto const& element = *it; | 75 | 191 | bool first = (it == begin(_list)); | 76 | 191 | ++it; | 77 | 191 | if (!first) | 78 | 109 | { | 79 | 109 | if (it == itEnd && !_lastSeparator.empty()) | 80 | 80 | result << _lastSeparator; // last iteration | 81 | 29 | else | 82 | 29 | result << _separator; | 83 | 109 | } | 84 | 191 | result << element; | 85 | 191 | } | 86 | | | 87 | 82 | return result.str(); | 88 | 82 | } |
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadable<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 67 | 22.1M | { | 68 | 22.1M | auto const itEnd = end(_list); | 69 | | | 70 | 22.1M | std::stringstream result; | 71 | | | 72 | 22.6M | for (auto it = begin(_list); it != itEnd; ) | 73 | 452k | { | 74 | 452k | auto const& element = *it; | 75 | 452k | bool first = (it == begin(_list)); | 76 | 452k | ++it; | 77 | 452k | if (!first) | 78 | 60.8k | { | 79 | 60.8k | if (it == itEnd && !_lastSeparator.empty()) | 80 | 699 | result << _lastSeparator; // last iteration | 81 | 60.1k | else | 82 | 60.1k | result << _separator; | 83 | 60.8k | } | 84 | 452k | result << element; | 85 | 452k | } | 86 | | | 87 | 22.1M | return result.str(); | 88 | 22.1M | } |
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadable<std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 67 | 299 | { | 68 | 299 | auto const itEnd = end(_list); | 69 | | | 70 | 299 | std::stringstream result; | 71 | | | 72 | 893 | for (auto it = begin(_list); it != itEnd; ) | 73 | 594 | { | 74 | 594 | auto const& element = *it; | 75 | 594 | bool first = (it == begin(_list)); | 76 | 594 | ++it; | 77 | 594 | if (!first) | 78 | 295 | { | 79 | 295 | if (it == itEnd && !_lastSeparator.empty()) | 80 | 201 | result << _lastSeparator; // last iteration | 81 | 94 | else | 82 | 94 | result << _separator; | 83 | 295 | } | 84 | 594 | result << element; | 85 | 594 | } | 86 | | | 87 | 299 | return result.str(); | 88 | 299 | } |
Types.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadable<ranges::transform_view<ranges::ref_view<std::__1::vector<solidity::frontend::Type const*, std::__1::allocator<solidity::frontend::Type const*> > const>, (anonymous namespace)::toStringInParentheses(std::__1::vector<solidity::frontend::Type const*, std::__1::allocator<solidity::frontend::Type const*> > const&, bool)::$_0> >(ranges::transform_view<ranges::ref_view<std::__1::vector<solidity::frontend::Type const*, std::__1::allocator<solidity::frontend::Type const*> > const>, (anonymous namespace)::toStringInParentheses(std::__1::vector<solidity::frontend::Type const*, std::__1::allocator<solidity::frontend::Type const*> > const&, bool)::$_0> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 67 | 3.97k | { | 68 | 3.97k | auto const itEnd = end(_list); | 69 | | | 70 | 3.97k | std::stringstream result; | 71 | | | 72 | 6.72k | for (auto it = begin(_list); it != itEnd; ) | 73 | 2.75k | { | 74 | 2.75k | auto const& element = *it; | 75 | 2.75k | bool first = (it == begin(_list)); | 76 | 2.75k | ++it; | 77 | 2.75k | if (!first) | 78 | 115 | { | 79 | 115 | if (it == itEnd && !_lastSeparator.empty()) | 80 | 0 | result << _lastSeparator; // last iteration | 81 | 115 | else | 82 | 115 | result << _separator; | 83 | 115 | } | 84 | 2.75k | result << element; | 85 | 2.75k | } | 86 | | | 87 | 3.97k | return result.str(); | 88 | 3.97k | } |
IRGenerator.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadable<ranges::transform_view<ranges::ref_view<std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const>, solidity::frontend::IRGenerator::generate(solidity::frontend::ContractDefinition const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&, std::__1::map<solidity::frontend::ContractDefinition const*, std::__1::basic_string_view<char, std::__1::char_traits<char> > const, std::__1::less<solidity::frontend::ContractDefinition const*>, std::__1::allocator<std::__1::pair<solidity::frontend::ContractDefinition const* const, std::__1::basic_string_view<char, std::__1::char_traits<char> > const> > > const&)::$_0::operator()(solidity::frontend::IRGenerationContext const&) const::{lambda(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)#1}> >(ranges::transform_view<ranges::ref_view<std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const>, solidity::frontend::IRGenerator::generate(solidity::frontend::ContractDefinition const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&, std::__1::map<solidity::frontend::ContractDefinition const*, std::__1::basic_string_view<char, std::__1::char_traits<char> > const, std::__1::less<solidity::frontend::ContractDefinition const*>, std::__1::allocator<std::__1::pair<solidity::frontend::ContractDefinition const* const, std::__1::basic_string_view<char, std::__1::char_traits<char> > const> > > const&)::$_0::operator()(solidity::frontend::IRGenerationContext const&) const::{lambda(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)#1}> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)Line | Count | Source | 67 | 8.05k | { | 68 | 8.05k | auto const itEnd = end(_list); | 69 | | | 70 | 8.05k | std::stringstream result; | 71 | | | 72 | 16.1k | for (auto it = begin(_list); it != itEnd; ) | 73 | 8.06k | { | 74 | 8.06k | auto const& element = *it; | 75 | 8.06k | bool first = (it == begin(_list)); | 76 | 8.06k | ++it; | 77 | 8.06k | if (!first) | 78 | 18 | { | 79 | 18 | if (it == itEnd && !_lastSeparator.empty()) | 80 | 0 | result << _lastSeparator; // last iteration | 81 | 18 | else | 82 | 18 | result << _separator; | 83 | 18 | } | 84 | 8.06k | result << element; | 85 | 8.06k | } | 86 | | | 87 | 8.05k | return result.str(); | 88 | 8.05k | } |
IRGeneratorForStatements.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadable<ranges::transform_view<ranges::ref_view<std::__1::vector<solidity::frontend::IRVariable, std::__1::allocator<solidity::frontend::IRVariable> > >, solidity::frontend::IRGeneratorForStatements::endVisit(solidity::frontend::FunctionCall const&)::$_0> >(ranges::transform_view<ranges::ref_view<std::__1::vector<solidity::frontend::IRVariable, std::__1::allocator<solidity::frontend::IRVariable> > >, solidity::frontend::IRGeneratorForStatements::endVisit(solidity::frontend::FunctionCall const&)::$_0> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 67 | 898 | { | 68 | 898 | auto const itEnd = end(_list); | 69 | | | 70 | 898 | std::stringstream result; | 71 | | | 72 | 1.79k | for (auto it = begin(_list); it != itEnd; ) | 73 | 898 | { | 74 | 898 | auto const& element = *it; | 75 | 898 | bool first = (it == begin(_list)); | 76 | 898 | ++it; | 77 | 898 | if (!first) | 78 | 0 | { | 79 | 0 | if (it == itEnd && !_lastSeparator.empty()) | 80 | 0 | result << _lastSeparator; // last iteration | 81 | 0 | else | 82 | 0 | result << _separator; | 83 | 0 | } | 84 | 898 | result << element; | 85 | 898 | } | 86 | | | 87 | 898 | return result.str(); | 88 | 898 | } |
Object.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadable<ranges::transform_view<ranges::ref_view<std::__1::map<unsigned int, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const>, std::__1::less<unsigned int>, std::__1::allocator<std::__1::pair<unsigned int const, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const> > > > const>, solidity::yul::ObjectDebugData::formatUseSrcComment() const::$_0> >(ranges::transform_view<ranges::ref_view<std::__1::map<unsigned int, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const>, std::__1::less<unsigned int>, std::__1::allocator<std::__1::pair<unsigned int const, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const> > > > const>, solidity::yul::ObjectDebugData::formatUseSrcComment() const::$_0> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 67 | 25.0k | { | 68 | 25.0k | auto const itEnd = end(_list); | 69 | | | 70 | 25.0k | std::stringstream result; | 71 | | | 72 | 51.7k | for (auto it = begin(_list); it != itEnd; ) | 73 | 26.6k | { | 74 | 26.6k | auto const& element = *it; | 75 | 26.6k | bool first = (it == begin(_list)); | 76 | 26.6k | ++it; | 77 | 26.6k | if (!first) | 78 | 1.68k | { | 79 | 1.68k | if (it == itEnd && !_lastSeparator.empty()) | 80 | 0 | result << _lastSeparator; // last iteration | 81 | 1.68k | else | 82 | 1.68k | result << _separator; | 83 | 1.68k | } | 84 | 26.6k | result << element; | 85 | 26.6k | } | 86 | | | 87 | 25.0k | return result.str(); | 88 | 25.0k | } |
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadable<ranges::transform_view<ranges::ref_view<std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const>, ranges::detail::get_first> >(ranges::transform_view<ranges::ref_view<std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const>, ranges::detail::get_first> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) |
89 | | |
90 | | /// Joins collection of strings just like joinHumanReadable, but prepends the separator |
91 | | /// unless the collection is empty. |
92 | | template<class T> |
93 | | std::string joinHumanReadablePrefixed |
94 | | ( |
95 | | T const& _list, |
96 | | std::string const& _separator = ", ", |
97 | | std::string const& _lastSeparator = "" |
98 | | ) |
99 | 4.28k | { |
100 | 4.28k | if (begin(_list) == end(_list)) |
101 | 521 | return {}; |
102 | 3.76k | else |
103 | 3.76k | return _separator + joinHumanReadable(_list, _separator, _lastSeparator); |
104 | 4.28k | } std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadablePrefixed<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 99 | 3.39k | { | 100 | 3.39k | if (begin(_list) == end(_list)) | 101 | 521 | return {}; | 102 | 2.87k | else | 103 | 2.87k | return _separator + joinHumanReadable(_list, _separator, _lastSeparator); | 104 | 3.39k | } |
IRGeneratorForStatements.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > solidity::util::joinHumanReadablePrefixed<ranges::transform_view<ranges::ref_view<std::__1::vector<solidity::frontend::IRVariable, std::__1::allocator<solidity::frontend::IRVariable> > >, solidity::frontend::IRGeneratorForStatements::endVisit(solidity::frontend::FunctionCall const&)::$_0> >(ranges::transform_view<ranges::ref_view<std::__1::vector<solidity::frontend::IRVariable, std::__1::allocator<solidity::frontend::IRVariable> > >, solidity::frontend::IRGeneratorForStatements::endVisit(solidity::frontend::FunctionCall const&)::$_0> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 99 | 898 | { | 100 | 898 | if (begin(_list) == end(_list)) | 101 | 0 | return {}; | 102 | 898 | else | 103 | 898 | return _separator + joinHumanReadable(_list, _separator, _lastSeparator); | 104 | 898 | } |
|
105 | | |
106 | | /// Formats large numbers to be easily readable by humans. |
107 | | /// Returns decimal representation for smaller numbers; hex for large numbers. |
108 | | /// "Special" numbers, powers-of-two and powers-of-two minus 1, are returned in |
109 | | /// formulaic form like 0x01 * 2**24 - 1. |
110 | | /// @a T can be any integer type, will typically be u160, u256 or bigint. |
111 | | /// @param _value to be formatted |
112 | | /// @param _useTruncation if true, internal truncation is also applied, |
113 | | /// like 0x5555...{+56 more}...5555 |
114 | | /// @example formatNumberReadable((u256)0x7ffffff) = "2**27 - 1" |
115 | | /// @example formatNumberReadable(-57896044618658097711785492504343953926634992332820282019728792003956564819968) = -2**255 |
116 | | std::string formatNumberReadable(bigint const& _value, bool _useTruncation = false); |
117 | | |
118 | | /// Safely converts an unsigned integer as string into an unsigned int type. |
119 | | /// |
120 | | /// @return the converted number or nullopt in case of an failure (including if it would not fit). |
121 | | inline std::optional<unsigned> toUnsignedInt(std::string const& _value) |
122 | 27.2k | { |
123 | 27.2k | try |
124 | 27.2k | { |
125 | 27.2k | auto const ulong = stoul(_value); |
126 | 27.2k | if (ulong > std::numeric_limits<unsigned>::max()) |
127 | 20 | return std::nullopt; |
128 | 27.2k | return static_cast<unsigned>(ulong); |
129 | 27.2k | } |
130 | 27.2k | catch (...) |
131 | 27.2k | { |
132 | 19 | return std::nullopt; |
133 | 19 | } |
134 | 27.2k | } |
135 | | |
136 | | /// Converts parameter _c to its lowercase equivalent if c is an uppercase letter and has a lowercase equivalent. It uses the classic "C" locale semantics. |
137 | | /// @param _c value to be converted |
138 | | /// @return the converted value |
139 | | inline char toLower(char _c) |
140 | 241M | { |
141 | 241M | return tolower(_c, std::locale::classic()); |
142 | 241M | } |
143 | | |
144 | | /// Converts parameter _c to its uppercase equivalent if c is an lowercase letter and has a uppercase equivalent. It uses the classic "C" locale semantics. |
145 | | /// @param _c value to be converted |
146 | | /// @return the converted value |
147 | | inline char toUpper(char _c) |
148 | 2.81k | { |
149 | 2.81k | return toupper(_c, std::locale::classic()); |
150 | 2.81k | } |
151 | | |
152 | | /// Converts parameter _s to its lowercase equivalent. It uses the classic "C" locale semantics. |
153 | | /// @param _s value to be converted |
154 | | /// @return the converted value |
155 | | inline std::string toLower(std::string _s) |
156 | 41.4M | { |
157 | 241M | std::transform(_s.begin(), _s.end(), _s.begin(), [](char _c) { |
158 | 241M | return toLower(_c); |
159 | 241M | }); |
160 | 41.4M | return _s; |
161 | 41.4M | } |
162 | | |
163 | | /// Checks whether _c is a decimal digit character. It uses the classic "C" locale semantics. |
164 | | /// @param _c character to be checked |
165 | | /// @return true if _c is a decimal digit character, false otherwise |
166 | | inline bool isDigit(char _c) |
167 | 148M | { |
168 | 148M | return isdigit(_c, std::locale::classic()); |
169 | 148M | } |
170 | | |
171 | | /// Checks if character is printable using classic "C" locale |
172 | | /// @param _c character to be checked |
173 | | /// @return true if _c is a printable character, false otherwise. |
174 | | inline bool isPrint(char _c) |
175 | 7.76M | { |
176 | 7.76M | return isprint(_c, std::locale::classic()); |
177 | 7.76M | } |
178 | | |
179 | | /// Adds a prefix to every line in the input. |
180 | | /// @see printPrefixed() |
181 | | std::string prefixLines( |
182 | | std::string const& _input, |
183 | | std::string const& _prefix, |
184 | | bool _trimPrefix = true |
185 | | ); |
186 | | |
187 | | /// Prints to a stream, adding a prefix to every line in the input. |
188 | | /// Assumes \n as the line separator. |
189 | | /// @param _trimPrefix If true, the function avoids introducing trailing whitespace on empty lines. |
190 | | /// This is achieved by removing trailing spaces from the prefix on such lines. |
191 | | /// Note that tabs and newlines are not removed, only spaces are. |
192 | | /// @param _finalNewline If true, an extra \n will be printed at the end of @a _input if it does |
193 | | /// not already end with one. |
194 | | void printPrefixed( |
195 | | std::ostream& _output, |
196 | | std::string const& _input, |
197 | | std::string const& _prefix, |
198 | | bool _trimPrefix = true, |
199 | | bool _ensureFinalNewline = true |
200 | | ); |
201 | | |
202 | | /// Adds a standard indent of 4 spaces to every line in the input. |
203 | | /// Assumes \n as the line separator. |
204 | | /// @param _indentEmptyLines If true, the indent will be applied to empty lines as well, resulting |
205 | | /// such lines containing trailing whitespace. |
206 | | inline std::string indent(std::string const& _input, bool _indentEmptyLines = false) |
207 | 59.9k | { |
208 | 59.9k | return prefixLines(_input, " ", !_indentEmptyLines); |
209 | 59.9k | } |
210 | | |
211 | | /// Parses an arithmetic value from a `string_view` without allocating and/or throwing. Returns `nullopt` on error. |
212 | | template<concepts::arithmetic T> |
213 | | std::optional<T> parseArithmetic(std::string_view const sv) |
214 | | { |
215 | | T result; |
216 | | auto const errorCondition = std::from_chars(sv.data(), sv.data() + sv.size(), result).ec; |
217 | | if (errorCondition == std::errc()) |
218 | | return result; |
219 | | return std::nullopt; |
220 | | } |
221 | | |
222 | | } |