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 /**
19  * @author Lefteris Karapetsas <lefteris@ethdev.com>
20  * @date 2015
21  * Represents a location in a source file
22  */
23 
24 #pragma once
25 
26 #include <iosfwd>
27 #include <memory>
28 #include <string>
29 #include <tuple>
30 #include <vector>
31 
32 namespace solidity::langutil
33 {
34 
35 /**
36  * Representation of an interval of source positions.
37  * The interval includes start and excludes end.
38  */
39 struct SourceLocation
40 {
41 	bool operator==(SourceLocation const& _other) const
42 	{
43 		return start == _other.start && end == _other.end && equalSources(_other);
44 	}
45 	bool operator!=(SourceLocation const& _other) const { return !operator==(_other); }
46 
47 	bool operator<(SourceLocation const& _other) const
48 	{
49 		if (!sourceName || !_other.sourceName)
50 			return std::make_tuple(int(!!sourceName), start, end) < std::make_tuple(int(!!_other.sourceName), _other.start, _other.end);
51 		else
52 			return std::make_tuple(*sourceName, start, end) < std::make_tuple(*_other.sourceName, _other.start, _other.end);
53 	}
54 
containsSourceLocation55 	bool contains(SourceLocation const& _other) const
56 	{
57 		if (!hasText() || !_other.hasText() || !equalSources(_other))
58 			return false;
59 		return start <= _other.start && _other.end <= end;
60 	}
61 
containsOffsetSourceLocation62 	bool containsOffset(int _pos) const
63 	{
64 		if (!hasText() || _pos < 0)
65 			return false;
66 		return start <= _pos && _pos < end;
67 	}
68 
intersectsSourceLocation69 	bool intersects(SourceLocation const& _other) const
70 	{
71 		if (!hasText() || !_other.hasText() || !equalSources(_other))
72 			return false;
73 		return _other.start < end && start < _other.end;
74 	}
75 
equalSourcesSourceLocation76 	bool equalSources(SourceLocation const& _other) const
77 	{
78 		if (!!sourceName != !!_other.sourceName)
79 			return false;
80 		if (sourceName && *sourceName != *_other.sourceName)
81 			return false;
82 		return true;
83 	}
84 
isValidSourceLocation85 	bool isValid() const { return sourceName || start != -1 || end != -1; }
86 
hasTextSourceLocation87 	bool hasText() const { return sourceName && 0 <= start && start <= end; }
88 
89 	/// @returns the smallest SourceLocation that contains both @param _a and @param _b.
90 	/// Assumes that @param _a and @param _b refer to the same source (exception: if the source of either one
91 	/// is unset, the source of the other will be used for the result, even if that is unset as well).
92 	/// Invalid start and end positions (with value of -1) are ignored (if start or end are -1 for both @param _a and
93 	/// @param _b, then start resp. end of the result will be -1 as well).
smallestCoveringSourceLocation94 	static SourceLocation smallestCovering(SourceLocation _a, SourceLocation const& _b)
95 	{
96 		if (!_a.sourceName)
97 			_a.sourceName = _b.sourceName;
98 
99 		if (_a.start < 0)
100 			_a.start = _b.start;
101 		else if (_b.start >= 0 && _b.start < _a.start)
102 			_a.start = _b.start;
103 		if (_b.end > _a.end)
104 			_a.end = _b.end;
105 
106 		return _a;
107 	}
108 
109 	int start = -1;
110 	int end = -1;
111 	std::shared_ptr<std::string const> sourceName;
112 };
113 
114 SourceLocation parseSourceLocation(
115 	std::string const& _input,
116 	std::vector<std::shared_ptr<std::string const>> const& _sourceNames
117 );
118 
119 /// Stream output for Location (used e.g. in boost exceptions).
120 std::ostream& operator<<(std::ostream& _out, SourceLocation const& _location);
121 
122 
123 /**
124  * Alternative, line-column-based representation for source locations.
125  * Both line and column are zero-based.
126  * If used as a range, the second location is considered exclusive.
127  * Negative values are invalid.
128  */
129 struct LineColumn
130 {
131 	/// Line value, can be between zero and number of `\n` characters in the source file.
132 	int line = -1;
133 	/// Column value, can be between zero and number of characters in the line (inclusive).
134 	int column = -1;
135 
136 	LineColumn() = default;
LineColumnLineColumn137 	explicit LineColumn(int _line, int _column): line(_line), column(_column) {}
138 };
139 
140 
141 }
142