/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 | | |