Coverage Report

Created: 2022-08-24 06:38

/src/solidity/liblangutil/CharStream.cpp
Line
Count
Source (jump to first uncovered line)
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
 * This file is derived from the file "scanner.cc", which was part of the
18
 * V8 project. The original copyright header follows:
19
 *
20
 * Copyright 2006-2012, the V8 project authors. All rights reserved.
21
 * Redistribution and use in source and binary forms, with or without
22
 * modification, are permitted provided that the following conditions are
23
 * met:
24
 *
25
 * * Redistributions of source code must retain the above copyright
26
 *   notice, this list of conditions and the following disclaimer.
27
 * * Redistributions in binary form must reproduce the above
28
 *   copyright notice, this list of conditions and the following
29
 *   disclaimer in the documentation and/or other materials provided
30
 *   with the distribution.
31
 * * Neither the name of Google Inc. nor the names of its
32
 *   contributors may be used to endorse or promote products derived
33
 *   from this software without specific prior written permission.
34
 *
35
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46
*/
47
/**
48
 * Character stream / input file.
49
 */
50
51
#include <liblangutil/CharStream.h>
52
#include <liblangutil/Exceptions.h>
53
54
using namespace std;
55
using namespace solidity;
56
using namespace solidity::langutil;
57
58
char CharStream::advanceAndGet(size_t _chars)
59
8.42M
{
60
8.42M
  if (isPastEndOfInput())
61
0
    return 0;
62
8.42M
  m_position += _chars;
63
8.42M
  if (isPastEndOfInput())
64
18.3k
    return 0;
65
8.40M
  return m_source[m_position];
66
8.42M
}
67
68
char CharStream::rollback(size_t _amount)
69
39.6k
{
70
39.6k
  solAssert(m_position >= _amount, "");
71
39.6k
  m_position -= _amount;
72
39.6k
  return get();
73
39.6k
}
74
75
char CharStream::setPosition(size_t _location)
76
0
{
77
0
  solAssert(_location <= m_source.size(), "Attempting to set position past end of source.");
78
0
  m_position = _location;
79
0
  return get();
80
0
}
81
82
string CharStream::lineAtPosition(int _position) const
83
0
{
84
  // if _position points to \n, it returns the line before the \n
85
0
  using size_type = string::size_type;
86
0
  size_type searchStart = min<size_type>(m_source.size(), size_type(_position));
87
0
  if (searchStart > 0)
88
0
    searchStart--;
89
0
  size_type lineStart = m_source.rfind('\n', searchStart);
90
0
  if (lineStart == string::npos)
91
0
    lineStart = 0;
92
0
  else
93
0
    lineStart++;
94
0
  string line = m_source.substr(
95
0
    lineStart,
96
0
    min(m_source.find('\n', lineStart), m_source.size()) - lineStart
97
0
  );
98
0
  if (!line.empty() && line.back() == '\r')
99
0
    line.pop_back();
100
0
  return line;
101
0
}
102
103
LineColumn CharStream::translatePositionToLineColumn(int _position) const
104
0
{
105
0
  using size_type = string::size_type;
106
0
  using diff_type = string::difference_type;
107
0
  size_type searchPosition = min<size_type>(m_source.size(), size_type(_position));
108
0
  int lineNumber = static_cast<int>(count(m_source.begin(), m_source.begin() + diff_type(searchPosition), '\n'));
109
0
  size_type lineStart;
110
0
  if (searchPosition == 0)
111
0
    lineStart = 0;
112
0
  else
113
0
  {
114
0
    lineStart = m_source.rfind('\n', searchPosition - 1);
115
0
    lineStart = lineStart == string::npos ? 0 : lineStart + 1;
116
0
  }
117
0
  return LineColumn{lineNumber, static_cast<int>(searchPosition - lineStart)};
118
0
}
119
120
string_view CharStream::text(SourceLocation const& _location) const
121
0
{
122
0
  if (!_location.hasText())
123
0
    return {};
124
0
  solAssert(_location.sourceName && *_location.sourceName == m_name, "");
125
0
  solAssert(static_cast<size_t>(_location.end) <= m_source.size(), "");
126
0
  return string_view{m_source}.substr(
127
0
    static_cast<size_t>(_location.start),
128
0
    static_cast<size_t>(_location.end - _location.start)
129
0
  );
130
0
}
131
132
string CharStream::singleLineSnippet(string const& _sourceCode, SourceLocation const& _location)
133
0
{
134
0
  if (!_location.hasText())
135
0
    return {};
136
137
0
  if (static_cast<size_t>(_location.start) >= _sourceCode.size())
138
0
    return {};
139
140
0
  string cut = _sourceCode.substr(static_cast<size_t>(_location.start), static_cast<size_t>(_location.end - _location.start));
141
0
  auto newLinePos = cut.find_first_of("\n\r");
142
0
  if (newLinePos != string::npos)
143
0
    cut = cut.substr(0, newLinePos) + "...";
144
145
0
  return cut;
146
0
}
147
148
optional<int> CharStream::translateLineColumnToPosition(LineColumn const& _lineColumn) const
149
0
{
150
0
  return translateLineColumnToPosition(m_source, _lineColumn);
151
0
}
152
153
optional<int> CharStream::translateLineColumnToPosition(std::string const& _text, LineColumn const& _input)
154
0
{
155
0
  if (_input.line < 0)
156
0
    return nullopt;
157
158
0
  size_t offset = 0;
159
0
  for (int i = 0; i < _input.line; i++)
160
0
  {
161
0
    offset = _text.find('\n', offset);
162
0
    if (offset == _text.npos)
163
0
      return nullopt;
164
0
    offset++; // Skip linefeed.
165
0
  }
166
167
0
  size_t endOfLine = _text.find('\n', offset);
168
0
  if (endOfLine == string::npos)
169
0
    endOfLine = _text.size();
170
171
0
  if (offset + static_cast<size_t>(_input.column) > endOfLine)
172
0
    return nullopt;
173
0
  return offset + static_cast<size_t>(_input.column);
174
0
}
175