/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 | 23.4M | { |
68 | 23.4M | auto const itEnd = end(_list); |
69 | | |
70 | 23.4M | std::stringstream result; |
71 | | |
72 | 24.0M | for (auto it = begin(_list); it != itEnd; ) |
73 | 544k | { |
74 | 544k | auto const& element = *it; |
75 | 544k | bool first = (it == begin(_list)); |
76 | 544k | ++it; |
77 | 544k | if (!first) |
78 | 66.2k | { |
79 | 66.2k | if (it == itEnd && !_lastSeparator.empty()) |
80 | 910 | result << _lastSeparator; // last iteration |
81 | 65.3k | else |
82 | 65.3k | result << _separator; |
83 | 66.2k | } |
84 | 544k | result << element; |
85 | 544k | } |
86 | | |
87 | 23.4M | return result.str(); |
88 | 23.4M | } 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 | 184 | { | 68 | 184 | auto const itEnd = end(_list); | 69 | | | 70 | 184 | std::stringstream result; | 71 | | | 72 | 2.94k | for (auto it = begin(_list); it != itEnd; ) | 73 | 2.76k | { | 74 | 2.76k | auto const& element = *it; | 75 | 2.76k | bool first = (it == begin(_list)); | 76 | 2.76k | ++it; | 77 | 2.76k | if (!first) | 78 | 2.57k | { | 79 | 2.57k | if (it == itEnd && !_lastSeparator.empty()) | 80 | 0 | result << _lastSeparator; // last iteration | 81 | 2.57k | else | 82 | 2.57k | result << _separator; | 83 | 2.57k | } | 84 | 2.76k | result << element; | 85 | 2.76k | } | 86 | | | 87 | 184 | return result.str(); | 88 | 184 | } |
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 | 90 | { | 68 | 90 | auto const itEnd = end(_list); | 69 | | | 70 | 90 | std::stringstream result; | 71 | | | 72 | 309 | for (auto it = begin(_list); it != itEnd; ) | 73 | 219 | { | 74 | 219 | auto const& element = *it; | 75 | 219 | bool first = (it == begin(_list)); | 76 | 219 | ++it; | 77 | 219 | if (!first) | 78 | 129 | { | 79 | 129 | if (it == itEnd && !_lastSeparator.empty()) | 80 | 88 | result << _lastSeparator; // last iteration | 81 | 41 | else | 82 | 41 | result << _separator; | 83 | 129 | } | 84 | 219 | result << element; | 85 | 219 | } | 86 | | | 87 | 90 | return result.str(); | 88 | 90 | } |
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 | 23.4M | { | 68 | 23.4M | auto const itEnd = end(_list); | 69 | | | 70 | 23.4M | std::stringstream result; | 71 | | | 72 | 23.9M | for (auto it = begin(_list); it != itEnd; ) | 73 | 500k | { | 74 | 500k | auto const& element = *it; | 75 | 500k | bool first = (it == begin(_list)); | 76 | 500k | ++it; | 77 | 500k | if (!first) | 78 | 62.0k | { | 79 | 62.0k | if (it == itEnd && !_lastSeparator.empty()) | 80 | 604 | result << _lastSeparator; // last iteration | 81 | 61.4k | else | 82 | 61.4k | result << _separator; | 83 | 62.0k | } | 84 | 500k | result << element; | 85 | 500k | } | 86 | | | 87 | 23.4M | return result.str(); | 88 | 23.4M | } |
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 | 325 | { | 68 | 325 | auto const itEnd = end(_list); | 69 | | | 70 | 325 | std::stringstream result; | 71 | | | 72 | 989 | for (auto it = begin(_list); it != itEnd; ) | 73 | 664 | { | 74 | 664 | auto const& element = *it; | 75 | 664 | bool first = (it == begin(_list)); | 76 | 664 | ++it; | 77 | 664 | if (!first) | 78 | 339 | { | 79 | 339 | if (it == itEnd && !_lastSeparator.empty()) | 80 | 218 | result << _lastSeparator; // last iteration | 81 | 121 | else | 82 | 121 | result << _separator; | 83 | 339 | } | 84 | 664 | result << element; | 85 | 664 | } | 86 | | | 87 | 325 | return result.str(); | 88 | 325 | } |
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.75k | { | 68 | 3.75k | auto const itEnd = end(_list); | 69 | | | 70 | 3.75k | std::stringstream result; | 71 | | | 72 | 6.31k | for (auto it = begin(_list); it != itEnd; ) | 73 | 2.56k | { | 74 | 2.56k | auto const& element = *it; | 75 | 2.56k | bool first = (it == begin(_list)); | 76 | 2.56k | ++it; | 77 | 2.56k | if (!first) | 78 | 182 | { | 79 | 182 | if (it == itEnd && !_lastSeparator.empty()) | 80 | 0 | result << _lastSeparator; // last iteration | 81 | 182 | else | 82 | 182 | result << _separator; | 83 | 182 | } | 84 | 2.56k | result << element; | 85 | 2.56k | } | 86 | | | 87 | 3.75k | return result.str(); | 88 | 3.75k | } |
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.69k | { | 68 | 8.69k | auto const itEnd = end(_list); | 69 | | | 70 | 8.69k | std::stringstream result; | 71 | | | 72 | 17.4k | for (auto it = begin(_list); it != itEnd; ) | 73 | 8.71k | { | 74 | 8.71k | auto const& element = *it; | 75 | 8.71k | bool first = (it == begin(_list)); | 76 | 8.71k | ++it; | 77 | 8.71k | if (!first) | 78 | 15 | { | 79 | 15 | if (it == itEnd && !_lastSeparator.empty()) | 80 | 0 | result << _lastSeparator; // last iteration | 81 | 15 | else | 82 | 15 | result << _separator; | 83 | 15 | } | 84 | 8.71k | result << element; | 85 | 8.71k | } | 86 | | | 87 | 8.69k | return result.str(); | 88 | 8.69k | } |
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 | 1.06k | { | 68 | 1.06k | auto const itEnd = end(_list); | 69 | | | 70 | 1.06k | std::stringstream result; | 71 | | | 72 | 2.12k | for (auto it = begin(_list); it != itEnd; ) | 73 | 1.06k | { | 74 | 1.06k | auto const& element = *it; | 75 | 1.06k | bool first = (it == begin(_list)); | 76 | 1.06k | ++it; | 77 | 1.06k | 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 | 1.06k | result << element; | 85 | 1.06k | } | 86 | | | 87 | 1.06k | return result.str(); | 88 | 1.06k | } |
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 | 27.0k | { | 68 | 27.0k | auto const itEnd = end(_list); | 69 | | | 70 | 27.0k | std::stringstream result; | 71 | | | 72 | 55.1k | for (auto it = begin(_list); it != itEnd; ) | 73 | 28.0k | { | 74 | 28.0k | auto const& element = *it; | 75 | 28.0k | bool first = (it == begin(_list)); | 76 | 28.0k | ++it; | 77 | 28.0k | if (!first) | 78 | 1.04k | { | 79 | 1.04k | if (it == itEnd && !_lastSeparator.empty()) | 80 | 0 | result << _lastSeparator; // last iteration | 81 | 1.04k | else | 82 | 1.04k | result << _separator; | 83 | 1.04k | } | 84 | 28.0k | result << element; | 85 | 28.0k | } | 86 | | | 87 | 27.0k | return result.str(); | 88 | 27.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 | 5.14k | { |
100 | 5.14k | if (begin(_list) == end(_list)) |
101 | 551 | return {}; |
102 | 4.59k | else |
103 | 4.59k | return _separator + joinHumanReadable(_list, _separator, _lastSeparator); |
104 | 5.14k | } 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 | 4.08k | { | 100 | 4.08k | if (begin(_list) == end(_list)) | 101 | 551 | return {}; | 102 | 3.53k | else | 103 | 3.53k | return _separator + joinHumanReadable(_list, _separator, _lastSeparator); | 104 | 4.08k | } |
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 | 1.06k | { | 100 | 1.06k | if (begin(_list) == end(_list)) | 101 | 0 | return {}; | 102 | 1.06k | else | 103 | 1.06k | return _separator + joinHumanReadable(_list, _separator, _lastSeparator); | 104 | 1.06k | } |
|
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 | 28.4k | { |
123 | 28.4k | try |
124 | 28.4k | { |
125 | 28.4k | auto const ulong = stoul(_value); |
126 | 28.4k | if (ulong > std::numeric_limits<unsigned>::max()) |
127 | 19 | return std::nullopt; |
128 | 28.4k | return static_cast<unsigned>(ulong); |
129 | 28.4k | } |
130 | 28.4k | catch (...) |
131 | 28.4k | { |
132 | 26 | return std::nullopt; |
133 | 26 | } |
134 | 28.4k | } |
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 | 230M | { |
141 | 230M | return tolower(_c, std::locale::classic()); |
142 | 230M | } |
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 | 3.29k | { |
149 | 3.29k | return toupper(_c, std::locale::classic()); |
150 | 3.29k | } |
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 | 39.5M | { |
157 | 230M | std::transform(_s.begin(), _s.end(), _s.begin(), [](char _c) { |
158 | 230M | return toLower(_c); |
159 | 230M | }); |
160 | 39.5M | return _s; |
161 | 39.5M | } |
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 | 159M | { |
168 | 159M | return isdigit(_c, std::locale::classic()); |
169 | 159M | } |
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 | 8.25M | { |
176 | 8.25M | return isprint(_c, std::locale::classic()); |
177 | 8.25M | } |
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 | 62.3k | { |
208 | 62.3k | return prefixLines(_input, " ", !_indentEmptyLines); |
209 | 62.3k | } |
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 | | } |