/proc/self/cwd/common/source.h
Line | Count | Source |
1 | | // Copyright 2023 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #ifndef THIRD_PARTY_CEL_CPP_COMMON_SOURCE_H_ |
16 | | #define THIRD_PARTY_CEL_CPP_COMMON_SOURCE_H_ |
17 | | |
18 | | #include <cstdint> |
19 | | #include <memory> |
20 | | #include <string> |
21 | | #include <utility> |
22 | | |
23 | | #include "absl/base/attributes.h" |
24 | | #include "absl/base/nullability.h" |
25 | | #include "absl/status/statusor.h" |
26 | | #include "absl/strings/cord.h" |
27 | | #include "absl/strings/string_view.h" |
28 | | #include "absl/types/optional.h" |
29 | | #include "absl/types/span.h" |
30 | | #include "absl/types/variant.h" |
31 | | |
32 | | namespace cel { |
33 | | |
34 | | namespace common_internal { |
35 | | class SourceImpl; |
36 | | } // namespace common_internal |
37 | | |
38 | | class Source; |
39 | | |
40 | | // SourcePosition represents an offset in source text. |
41 | | using SourcePosition = int32_t; |
42 | | |
43 | | // SourceRange represents a range of positions, where `begin` is inclusive and |
44 | | // `end` is exclusive. |
45 | | struct SourceRange final { |
46 | | SourcePosition begin = -1; |
47 | | SourcePosition end = -1; |
48 | | }; |
49 | | |
50 | 0 | inline bool operator==(const SourceRange& lhs, const SourceRange& rhs) { |
51 | 0 | return lhs.begin == rhs.begin && lhs.end == rhs.end; |
52 | 0 | } |
53 | | |
54 | 0 | inline bool operator!=(const SourceRange& lhs, const SourceRange& rhs) { |
55 | 0 | return !operator==(lhs, rhs); |
56 | 0 | } |
57 | | |
58 | | // `SourceLocation` is a representation of a line and column in source text. |
59 | | struct SourceLocation final { |
60 | | int32_t line = -1; // 1-based line number. |
61 | | int32_t column = -1; // 0-based column number. |
62 | | }; |
63 | | |
64 | 0 | inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs) { |
65 | 0 | return lhs.line == rhs.line && lhs.column == rhs.column; |
66 | 0 | } |
67 | | |
68 | 0 | inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs) { |
69 | 0 | return !operator==(lhs, rhs); |
70 | 0 | } |
71 | | |
72 | | // `SourceContentView` is a view of the content owned by `Source`, which is a |
73 | | // sequence of Unicode code points. |
74 | | class SourceContentView final { |
75 | | public: |
76 | | SourceContentView(const SourceContentView&) = default; |
77 | | SourceContentView(SourceContentView&&) = default; |
78 | | SourceContentView& operator=(const SourceContentView&) = default; |
79 | | SourceContentView& operator=(SourceContentView&&) = default; |
80 | | |
81 | | SourcePosition size() const; |
82 | | |
83 | | bool empty() const; |
84 | | |
85 | | char32_t at(SourcePosition position) const; |
86 | | |
87 | | std::string ToString(SourcePosition begin, SourcePosition end) const; |
88 | 43.1k | std::string ToString(SourcePosition begin) const { |
89 | 43.1k | return ToString(begin, size()); |
90 | 43.1k | } |
91 | 0 | std::string ToString() const { return ToString(0); } |
92 | | |
93 | | void AppendToString(std::string& dest) const; |
94 | | |
95 | | private: |
96 | | friend class Source; |
97 | | |
98 | | constexpr SourceContentView() = default; |
99 | | |
100 | | constexpr explicit SourceContentView(absl::Span<const char> view) |
101 | 40.4k | : view_(view) {} |
102 | | |
103 | | constexpr explicit SourceContentView(absl::Span<const uint8_t> view) |
104 | 3.48k | : view_(view) {} |
105 | | |
106 | | constexpr explicit SourceContentView(absl::Span<const char16_t> view) |
107 | 7.67k | : view_(view) {} |
108 | | |
109 | | constexpr explicit SourceContentView(absl::Span<const char32_t> view) |
110 | 11.0k | : view_(view) {} |
111 | | |
112 | | absl::variant<absl::Span<const char>, absl::Span<const uint8_t>, |
113 | | absl::Span<const char16_t>, absl::Span<const char32_t>> |
114 | | view_; |
115 | | }; |
116 | | |
117 | | // `Source` represents the source expression. |
118 | | class Source { |
119 | | public: |
120 | | using ContentView = SourceContentView; |
121 | | |
122 | | Source(const Source&) = delete; |
123 | | Source(Source&&) = delete; |
124 | | |
125 | 4.20k | virtual ~Source() = default; |
126 | | |
127 | | Source& operator=(const Source&) = delete; |
128 | | Source& operator=(Source&&) = delete; |
129 | | |
130 | | virtual absl::string_view description() const |
131 | | ABSL_ATTRIBUTE_LIFETIME_BOUND = 0; |
132 | | |
133 | | // Maps a `SourcePosition` to a `SourceLocation`. Returns an empty |
134 | | // `absl::optional` when `SourcePosition` is invalid or the information |
135 | | // required to perform the mapping is not present. |
136 | | absl::optional<SourceLocation> GetLocation(SourcePosition position) const; |
137 | | |
138 | | // Maps a `SourceLocation` to a `SourcePosition`. Returns an empty |
139 | | // `absl::optional` when `SourceLocation` is invalid or the information |
140 | | // required to perform the mapping is not present. |
141 | | absl::optional<SourcePosition> GetPosition( |
142 | | const SourceLocation& location) const; |
143 | | |
144 | | absl::optional<std::string> Snippet(int32_t line) const; |
145 | | |
146 | | // Formats an annotated snippet highlighting an error at location, e.g. |
147 | | // |
148 | | // "\n | $SOURCE_SNIPPET" + |
149 | | // "\n | .......^" |
150 | | // |
151 | | // Returns an empty string if location is not a valid location in this source. |
152 | | std::string DisplayErrorLocation(SourceLocation location) const; |
153 | | |
154 | | // Returns a view of the underlying expression text, if present. |
155 | | virtual ContentView content() const ABSL_ATTRIBUTE_LIFETIME_BOUND = 0; |
156 | | |
157 | | // Returns a `absl::Span` of `SourcePosition` which represent the positions |
158 | | // where new lines occur. |
159 | | virtual absl::Span<const SourcePosition> line_offsets() const |
160 | | ABSL_ATTRIBUTE_LIFETIME_BOUND = 0; |
161 | | |
162 | | protected: |
163 | 0 | static constexpr ContentView EmptyContentView() { return ContentView(); } |
164 | 40.4k | static constexpr ContentView MakeContentView(absl::Span<const char> view) { |
165 | 40.4k | return ContentView(view); |
166 | 40.4k | } |
167 | 3.48k | static constexpr ContentView MakeContentView(absl::Span<const uint8_t> view) { |
168 | 3.48k | return ContentView(view); |
169 | 3.48k | } |
170 | | static constexpr ContentView MakeContentView( |
171 | 7.67k | absl::Span<const char16_t> view) { |
172 | 7.67k | return ContentView(view); |
173 | 7.67k | } |
174 | | static constexpr ContentView MakeContentView( |
175 | 11.0k | absl::Span<const char32_t> view) { |
176 | 11.0k | return ContentView(view); |
177 | 11.0k | } |
178 | | |
179 | | private: |
180 | | friend class common_internal::SourceImpl; |
181 | | |
182 | 4.20k | Source() = default; |
183 | | |
184 | | absl::optional<SourcePosition> FindLinePosition(int32_t line) const; |
185 | | |
186 | | absl::optional<std::pair<int32_t, SourcePosition>> FindLine( |
187 | | SourcePosition position) const; |
188 | | }; |
189 | | |
190 | | using SourcePtr = std::unique_ptr<Source>; |
191 | | |
192 | | absl::StatusOr<absl_nonnull SourcePtr> NewSource( |
193 | | absl::string_view content, std::string description = "<input>"); |
194 | | |
195 | | absl::StatusOr<absl_nonnull SourcePtr> NewSource( |
196 | | const absl::Cord& content, std::string description = "<input>"); |
197 | | |
198 | | } // namespace cel |
199 | | |
200 | | #endif // THIRD_PARTY_CEL_CPP_COMMON_SOURCE_H_ |