Coverage Report

Created: 2022-08-24 06:43

/src/solidity/libsolutil/StringUtils.cpp
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
#include <libsolutil/StringUtils.h>
26
#include <string>
27
#include <vector>
28
29
using namespace std;
30
using namespace solidity::util;
31
32
bool solidity::util::stringWithinDistance(string const& _str1, string const& _str2, size_t _maxDistance, size_t _lenThreshold)
33
45.6k
{
34
45.6k
  if (_str1 == _str2)
35
49
    return true;
36
37
45.5k
  size_t n1 = _str1.size();
38
45.5k
  size_t n2 = _str2.size();
39
45.5k
  if (_lenThreshold > 0 && n1 * n2 > _lenThreshold)
40
3
    return false;
41
42
45.5k
  size_t distance = stringDistance(_str1, _str2);
43
44
  // if distance is not greater than _maxDistance, and distance is strictly less than length of both names, they can be considered similar
45
  // this is to avoid irrelevant suggestions
46
45.5k
  return distance <= _maxDistance && distance < n1 && distance < n2;
47
45.5k
}
48
49
size_t solidity::util::stringDistance(string const& _str1, string const& _str2)
50
45.5k
{
51
45.5k
  size_t n1 = _str1.size();
52
45.5k
  size_t n2 = _str2.size();
53
  // Optimize by storing only last 2 rows and current row. So first index is considered modulo 3
54
  // This is a two-dimensional array of size 3 x (n2 + 1).
55
45.5k
  vector<size_t> dp(3 * (n2 + 1));
56
57
  // In this dp formulation of Damerau–Levenshtein distance we are assuming that the strings are 1-based to make base case storage easier.
58
  // So index accesser to _name1 and _name2 have to be adjusted accordingly
59
299k
  for (size_t i1 = 0; i1 <= n1; ++i1)
60
2.04M
    for (size_t i2 = 0; i2 <= n2; ++i2)
61
1.79M
    {
62
1.79M
      size_t x = 0;
63
1.79M
      if (min(i1, i2) == 0) // base case
64
524k
        x = max(i1, i2);
65
1.27M
      else
66
1.27M
      {
67
1.27M
        size_t left = dp[(i1 - 1) % 3 + i2 * 3];
68
1.27M
        size_t up = dp[(i1 % 3) + (i2 - 1) * 3];
69
1.27M
        size_t upleft = dp[((i1 - 1) % 3) + (i2 - 1) * 3];
70
        // deletion and insertion
71
1.27M
        x = min(left + 1, up + 1);
72
1.27M
        if (_str1[i1-1] == _str2[i2-1])
73
          // same chars, can skip
74
53.5k
          x = min(x, upleft);
75
1.21M
        else
76
          // different chars so try substitution
77
1.21M
          x = min(x, upleft + 1);
78
79
        // transposing
80
1.27M
        if (i1 > 1 && i2 > 1 && _str1[i1 - 1] == _str2[i2 - 2] && _str1[i1 - 2] == _str2[i2 - 1])
81
8.67k
          x = min(x, dp[((i1 - 2) % 3) + (i2 - 2) * 3] + 1);
82
1.27M
      }
83
1.79M
      dp[(i1 % 3) + i2 * 3] = x;
84
1.79M
    }
85
86
45.5k
  return dp[(n1 % 3) + n2 * 3];
87
45.5k
}
88
89
string solidity::util::quotedAlternativesList(vector<string> const& suggestions)
90
1.90k
{
91
1.90k
  vector<string> quotedSuggestions;
92
93
1.90k
  for (auto& suggestion: suggestions)
94
1.01k
    quotedSuggestions.emplace_back("\"" + suggestion + "\"");
95
96
1.90k
  return joinHumanReadable(quotedSuggestions, ", ", " or ");
97
1.90k
}
98
99
string solidity::util::suffixedVariableNameList(string const& _baseName, size_t _startSuffix, size_t _endSuffix)
100
39.9k
{
101
39.9k
  string result;
102
39.9k
  if (_startSuffix < _endSuffix)
103
29.0k
  {
104
29.0k
    result = _baseName + to_string(_startSuffix++);
105
30.9k
    while (_startSuffix < _endSuffix)
106
1.92k
      result += ", " + _baseName + to_string(_startSuffix++);
107
29.0k
  }
108
10.9k
  else if (_endSuffix < _startSuffix)
109
6.08k
  {
110
6.08k
    result = _baseName + to_string(_endSuffix++);
111
9.56k
    while (_endSuffix < _startSuffix)
112
3.48k
      result = _baseName + to_string(_endSuffix++) + ", " + result;
113
6.08k
  }
114
39.9k
  return result;
115
39.9k
}