/proc/self/cwd/common/source.cc
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 | | #include "common/source.h" |
16 | | |
17 | | #include <algorithm> |
18 | | #include <cstddef> |
19 | | #include <cstdint> |
20 | | #include <limits> |
21 | | #include <memory> |
22 | | #include <optional> |
23 | | #include <string> |
24 | | #include <tuple> |
25 | | #include <utility> |
26 | | #include <vector> |
27 | | |
28 | | #include "absl/base/nullability.h" |
29 | | #include "absl/base/optimization.h" |
30 | | #include "absl/container/inlined_vector.h" |
31 | | #include "absl/functional/overload.h" |
32 | | #include "absl/log/absl_check.h" |
33 | | #include "absl/status/status.h" |
34 | | #include "absl/status/statusor.h" |
35 | | #include "absl/strings/cord.h" |
36 | | #include "absl/strings/str_cat.h" |
37 | | #include "absl/strings/str_replace.h" |
38 | | #include "absl/strings/string_view.h" |
39 | | #include "absl/types/optional.h" |
40 | | #include "absl/types/span.h" |
41 | | #include "absl/types/variant.h" |
42 | | #include "internal/unicode.h" |
43 | | #include "internal/utf8.h" |
44 | | |
45 | | namespace cel { |
46 | | |
47 | 169k | SourcePosition SourceContentView::size() const { |
48 | 169k | return static_cast<SourcePosition>(absl::visit( |
49 | 169k | absl::Overload( |
50 | 169k | [](absl::Span<const char> view) { return view.size(); }, |
51 | 169k | [](absl::Span<const uint8_t> view) { return view.size(); }, |
52 | 169k | [](absl::Span<const char16_t> view) { return view.size(); }, |
53 | 169k | [](absl::Span<const char32_t> view) { return view.size(); }), |
54 | 169k | view_)); |
55 | 169k | } |
56 | | |
57 | 187k | bool SourceContentView::empty() const { |
58 | 187k | return absl::visit( |
59 | 187k | absl::Overload( |
60 | 187k | [](absl::Span<const char> view) { return view.empty(); }, |
61 | 187k | [](absl::Span<const uint8_t> view) { return view.empty(); }, |
62 | 187k | [](absl::Span<const char16_t> view) { return view.empty(); }, |
63 | 187k | [](absl::Span<const char32_t> view) { return view.empty(); }), |
64 | 187k | view_); |
65 | 187k | } |
66 | | |
67 | 428M | char32_t SourceContentView::at(SourcePosition position) const { |
68 | 428M | ABSL_DCHECK_GE(position, 0); |
69 | 428M | ABSL_DCHECK_LT(position, size()); |
70 | 428M | return absl::visit( |
71 | 428M | absl::Overload( |
72 | 428M | [position = |
73 | 428M | static_cast<size_t>(position)](absl::Span<const char> view) { |
74 | 240M | return static_cast<char32_t>(static_cast<uint8_t>(view[position])); |
75 | 240M | }, |
76 | 428M | [position = |
77 | 428M | static_cast<size_t>(position)](absl::Span<const uint8_t> view) { |
78 | 11.8M | return static_cast<char32_t>(view[position]); |
79 | 11.8M | }, |
80 | 428M | [position = |
81 | 428M | static_cast<size_t>(position)](absl::Span<const char16_t> view) { |
82 | 63.1M | return static_cast<char32_t>(view[position]); |
83 | 63.1M | }, |
84 | 428M | [position = |
85 | 428M | static_cast<size_t>(position)](absl::Span<const char32_t> view) { |
86 | 113M | return static_cast<char32_t>(view[position]); |
87 | 113M | }), |
88 | 428M | view_); |
89 | 428M | } |
90 | | |
91 | | std::string SourceContentView::ToString(SourcePosition begin, |
92 | 18.5M | SourcePosition end) const { |
93 | 18.5M | ABSL_DCHECK_GE(begin, 0); |
94 | 18.5M | ABSL_DCHECK_LE(end, size()); |
95 | 18.5M | ABSL_DCHECK_LE(begin, end); |
96 | 18.5M | return absl::visit( |
97 | 18.5M | absl::Overload( |
98 | 18.5M | [begin = static_cast<size_t>(begin), |
99 | 18.5M | end = static_cast<size_t>(end)](absl::Span<const char> view) { |
100 | 14.4M | view = view.subspan(begin, end - begin); |
101 | 14.4M | return std::string(view.data(), view.size()); |
102 | 14.4M | }, |
103 | 18.5M | [begin = static_cast<size_t>(begin), |
104 | 18.5M | end = static_cast<size_t>(end)](absl::Span<const uint8_t> view) { |
105 | 585k | view = view.subspan(begin, end - begin); |
106 | 585k | std::string result; |
107 | 585k | result.reserve(view.size() * 2); |
108 | 111M | for (const auto& code_point : view) { |
109 | 111M | internal::Utf8Encode(result, code_point); |
110 | 111M | } |
111 | 585k | result.shrink_to_fit(); |
112 | 585k | return result; |
113 | 585k | }, |
114 | 18.5M | [begin = static_cast<size_t>(begin), |
115 | 18.5M | end = static_cast<size_t>(end)](absl::Span<const char16_t> view) { |
116 | 1.73M | view = view.subspan(begin, end - begin); |
117 | 1.73M | std::string result; |
118 | 1.73M | result.reserve(view.size() * 3); |
119 | 543M | for (const auto& code_point : view) { |
120 | 543M | internal::Utf8Encode(result, code_point); |
121 | 543M | } |
122 | 1.73M | result.shrink_to_fit(); |
123 | 1.73M | return result; |
124 | 1.73M | }, |
125 | 18.5M | [begin = static_cast<size_t>(begin), |
126 | 18.5M | end = static_cast<size_t>(end)](absl::Span<const char32_t> view) { |
127 | 1.78M | view = view.subspan(begin, end - begin); |
128 | 1.78M | std::string result; |
129 | 1.78M | result.reserve(view.size() * 4); |
130 | 343M | for (const auto& code_point : view) { |
131 | 343M | internal::Utf8Encode(result, code_point); |
132 | 343M | } |
133 | 1.78M | result.shrink_to_fit(); |
134 | 1.78M | return result; |
135 | 1.78M | }), |
136 | 18.5M | view_); |
137 | 18.5M | } |
138 | | |
139 | 0 | void SourceContentView::AppendToString(std::string& dest) const { |
140 | 0 | absl::visit(absl::Overload( |
141 | 0 | [&dest](absl::Span<const char> view) { |
142 | 0 | dest.append(view.data(), view.size()); |
143 | 0 | }, |
144 | 0 | [&dest](absl::Span<const uint8_t> view) { |
145 | 0 | for (const auto& code_point : view) { |
146 | 0 | internal::Utf8Encode(dest, code_point); |
147 | 0 | } |
148 | 0 | }, |
149 | 0 | [&dest](absl::Span<const char16_t> view) { |
150 | 0 | for (const auto& code_point : view) { |
151 | 0 | internal::Utf8Encode(dest, code_point); |
152 | 0 | } |
153 | 0 | }, |
154 | 0 | [&dest](absl::Span<const char32_t> view) { |
155 | 0 | for (const auto& code_point : view) { |
156 | 0 | internal::Utf8Encode(dest, code_point); |
157 | 0 | } |
158 | 0 | }), |
159 | 0 | view_); |
160 | 0 | } |
161 | | |
162 | | namespace common_internal { |
163 | | |
164 | | class SourceImpl : public Source { |
165 | | public: |
166 | | SourceImpl(std::string description, |
167 | | absl::InlinedVector<SourcePosition, 1> line_offsets) |
168 | 21.6k | : description_(std::move(description)), |
169 | 21.6k | line_offsets_(std::move(line_offsets)) {} |
170 | | |
171 | 225k | absl::string_view description() const final { return description_; } |
172 | | |
173 | 2.63M | absl::Span<const SourcePosition> line_offsets() const final { |
174 | 2.63M | return absl::MakeConstSpan(line_offsets_); |
175 | 2.63M | } |
176 | | |
177 | | private: |
178 | | const std::string description_; |
179 | | const absl::InlinedVector<SourcePosition, 1> line_offsets_; |
180 | | }; |
181 | | |
182 | | namespace { |
183 | | |
184 | | class AsciiSource final : public SourceImpl { |
185 | | public: |
186 | | AsciiSource(std::string description, |
187 | | absl::InlinedVector<SourcePosition, 1> line_offsets, |
188 | | std::vector<char> text) |
189 | 19.3k | : SourceImpl(std::move(description), std::move(line_offsets)), |
190 | 19.3k | text_(std::move(text)) {} |
191 | | |
192 | 152k | ContentView content() const override { |
193 | 152k | return MakeContentView(absl::MakeConstSpan(text_)); |
194 | 152k | } |
195 | | |
196 | | private: |
197 | | const std::vector<char> text_; |
198 | | }; |
199 | | |
200 | | class Latin1Source final : public SourceImpl { |
201 | | public: |
202 | | Latin1Source(std::string description, |
203 | | absl::InlinedVector<SourcePosition, 1> line_offsets, |
204 | | std::vector<uint8_t> text) |
205 | 351 | : SourceImpl(std::move(description), std::move(line_offsets)), |
206 | 351 | text_(std::move(text)) {} |
207 | | |
208 | 9.14k | ContentView content() const override { |
209 | 9.14k | return MakeContentView(absl::MakeConstSpan(text_)); |
210 | 9.14k | } |
211 | | |
212 | | private: |
213 | | const std::vector<uint8_t> text_; |
214 | | }; |
215 | | |
216 | | class BasicPlaneSource final : public SourceImpl { |
217 | | public: |
218 | | BasicPlaneSource(std::string description, |
219 | | absl::InlinedVector<SourcePosition, 1> line_offsets, |
220 | | std::vector<char16_t> text) |
221 | 981 | : SourceImpl(std::move(description), std::move(line_offsets)), |
222 | 981 | text_(std::move(text)) {} |
223 | | |
224 | 26.6k | ContentView content() const override { |
225 | 26.6k | return MakeContentView(absl::MakeConstSpan(text_)); |
226 | 26.6k | } |
227 | | |
228 | | private: |
229 | | const std::vector<char16_t> text_; |
230 | | }; |
231 | | |
232 | | class SupplementalPlaneSource final : public SourceImpl { |
233 | | public: |
234 | | SupplementalPlaneSource(std::string description, |
235 | | absl::InlinedVector<SourcePosition, 1> line_offsets, |
236 | | std::vector<char32_t> text) |
237 | 957 | : SourceImpl(std::move(description), std::move(line_offsets)), |
238 | 957 | text_(std::move(text)) {} |
239 | | |
240 | 24.1k | ContentView content() const override { |
241 | 24.1k | return MakeContentView(absl::MakeConstSpan(text_)); |
242 | 24.1k | } |
243 | | |
244 | | private: |
245 | | const std::vector<char32_t> text_; |
246 | | }; |
247 | | |
248 | | template <typename T> |
249 | | struct SourceTextTraits; |
250 | | |
251 | | template <> |
252 | | struct SourceTextTraits<absl::string_view> { |
253 | | using iterator_type = absl::string_view; |
254 | | |
255 | 21.8k | static iterator_type Begin(absl::string_view text) { return text; } |
256 | | |
257 | 169M | static void Advance(iterator_type& it, size_t n) { it.remove_prefix(n); } |
258 | | |
259 | | static void AppendTo(std::vector<uint8_t>& out, absl::string_view text, |
260 | 583 | size_t n) { |
261 | 583 | const auto* in = reinterpret_cast<const uint8_t*>(text.data()); |
262 | 583 | out.insert(out.end(), in, in + n); |
263 | 583 | } |
264 | | |
265 | 19.3k | static std::vector<char> ToVector(absl::string_view in) { |
266 | 19.3k | std::vector<char> out; |
267 | 19.3k | out.reserve(in.size()); |
268 | 19.3k | out.insert(out.end(), in.begin(), in.end()); |
269 | 19.3k | return out; |
270 | 19.3k | } |
271 | | }; |
272 | | |
273 | | template <> |
274 | | struct SourceTextTraits<absl::Cord> { |
275 | | using iterator_type = absl::Cord::CharIterator; |
276 | | |
277 | 0 | static iterator_type Begin(const absl::Cord& text) { |
278 | 0 | return text.char_begin(); |
279 | 0 | } |
280 | | |
281 | 0 | static void Advance(iterator_type& it, size_t n) { |
282 | 0 | absl::Cord::Advance(&it, n); |
283 | 0 | } |
284 | | |
285 | | static void AppendTo(std::vector<uint8_t>& out, const absl::Cord& text, |
286 | 0 | size_t n) { |
287 | 0 | auto it = text.char_begin(); |
288 | 0 | while (n > 0) { |
289 | 0 | auto str = absl::Cord::ChunkRemaining(it); |
290 | 0 | size_t to_append = std::min(n, str.size()); |
291 | 0 | const auto* in = reinterpret_cast<const uint8_t*>(str.data()); |
292 | 0 | out.insert(out.end(), in, in + to_append); |
293 | 0 | n -= to_append; |
294 | 0 | absl::Cord::Advance(&it, to_append); |
295 | 0 | } |
296 | 0 | } |
297 | | |
298 | 0 | static std::vector<char> ToVector(const absl::Cord& in) { |
299 | 0 | std::vector<char> out; |
300 | 0 | out.reserve(in.size()); |
301 | 0 | for (const auto& chunk : in.Chunks()) { |
302 | 0 | out.insert(out.end(), chunk.begin(), chunk.end()); |
303 | 0 | } |
304 | 0 | return out; |
305 | 0 | } |
306 | | }; |
307 | | |
308 | | template <typename T> |
309 | | absl::StatusOr<SourcePtr> NewSourceImpl(std::string description, const T& text, |
310 | 21.8k | const size_t text_size) { |
311 | 21.8k | if (ABSL_PREDICT_FALSE( |
312 | 21.8k | text_size > |
313 | 21.8k | static_cast<size_t>(std::numeric_limits<int32_t>::max()))) { |
314 | 0 | return absl::InvalidArgumentError("expression larger than 2GiB limit"); |
315 | 0 | } |
316 | 21.8k | using Traits = SourceTextTraits<T>; |
317 | 21.8k | size_t index = 0; |
318 | 21.8k | typename Traits::iterator_type it = Traits::Begin(text); |
319 | 21.8k | SourcePosition offset = 0; |
320 | 21.8k | char32_t code_point; |
321 | 21.8k | size_t code_units; |
322 | 21.8k | std::vector<uint8_t> data8; |
323 | 21.8k | std::vector<char16_t> data16; |
324 | 21.8k | std::vector<char32_t> data32; |
325 | 21.8k | absl::InlinedVector<SourcePosition, 1> line_offsets; |
326 | 116M | while (index < text_size) { |
327 | 116M | std::tie(code_point, code_units) = cel::internal::Utf8Decode(it); |
328 | 116M | if (ABSL_PREDICT_FALSE(code_point == |
329 | 116M | cel::internal::kUnicodeReplacementCharacter && |
330 | 116M | code_units == 1)) { |
331 | | // Thats an invalid UTF-8 encoding. |
332 | 49 | return absl::InvalidArgumentError("cannot parse malformed UTF-8 input"); |
333 | 49 | } |
334 | 116M | if (code_point == '\n') { |
335 | 35.0M | line_offsets.push_back(offset + 1); |
336 | 35.0M | } |
337 | 116M | if (code_point <= 0x7f) { |
338 | 116M | Traits::Advance(it, code_units); |
339 | 116M | index += code_units; |
340 | 116M | ++offset; |
341 | 116M | continue; |
342 | 116M | } |
343 | 2.42k | if (code_point <= 0xff) { |
344 | 583 | data8.reserve(text_size); |
345 | 583 | Traits::AppendTo(data8, text, index); |
346 | 583 | data8.push_back(static_cast<uint8_t>(code_point)); |
347 | 583 | Traits::Advance(it, code_units); |
348 | 583 | index += code_units; |
349 | 583 | ++offset; |
350 | 583 | goto latin1; |
351 | 583 | } |
352 | 1.83k | if (code_point <= 0xffff) { |
353 | 1.05k | data16.reserve(text_size); |
354 | 16.9M | for (size_t offset = 0; offset < index; offset++) { |
355 | 16.9M | data16.push_back(static_cast<uint8_t>(text[offset])); |
356 | 16.9M | } |
357 | 1.05k | data16.push_back(static_cast<char16_t>(code_point)); |
358 | 1.05k | Traits::Advance(it, code_units); |
359 | 1.05k | index += code_units; |
360 | 1.05k | ++offset; |
361 | 1.05k | goto basic; |
362 | 1.05k | } |
363 | 785 | data32.reserve(text_size); |
364 | 5.39M | for (size_t offset = 0; offset < index; offset++) { |
365 | 5.39M | data32.push_back(static_cast<char32_t>(text[offset])); |
366 | 5.39M | } |
367 | 785 | data32.push_back(code_point); |
368 | 785 | Traits::Advance(it, code_units); |
369 | 785 | index += code_units; |
370 | 785 | ++offset; |
371 | 785 | goto supplemental; |
372 | 1.83k | } |
373 | 19.3k | line_offsets.push_back(offset + 1); |
374 | 19.3k | return std::make_unique<AsciiSource>( |
375 | 19.3k | std::move(description), std::move(line_offsets), Traits::ToVector(text)); |
376 | 583 | latin1: |
377 | 7.76M | while (index < text_size) { |
378 | 7.76M | std::tie(code_point, code_units) = internal::Utf8Decode(it); |
379 | 7.76M | if (ABSL_PREDICT_FALSE(code_point == |
380 | 7.76M | internal::kUnicodeReplacementCharacter && |
381 | 7.76M | code_units == 1)) { |
382 | | // Thats an invalid UTF-8 encoding. |
383 | 36 | return absl::InvalidArgumentError("cannot parse malformed UTF-8 input"); |
384 | 36 | } |
385 | 7.76M | if (code_point == '\n') { |
386 | 4.76M | line_offsets.push_back(offset + 1); |
387 | 4.76M | } |
388 | 7.76M | if (code_point <= 0xff) { |
389 | 7.76M | data8.push_back(static_cast<uint8_t>(code_point)); |
390 | 7.76M | Traits::Advance(it, code_units); |
391 | 7.76M | index += code_units; |
392 | 7.76M | ++offset; |
393 | 7.76M | continue; |
394 | 7.76M | } |
395 | 196 | if (code_point <= 0xffff) { |
396 | 99 | data16.reserve(text_size); |
397 | 2.73M | for (const auto& value : data8) { |
398 | 2.73M | data16.push_back(value); |
399 | 2.73M | } |
400 | 99 | std::vector<uint8_t>().swap(data8); |
401 | 99 | data16.push_back(static_cast<char16_t>(code_point)); |
402 | 99 | Traits::Advance(it, code_units); |
403 | 99 | index += code_units; |
404 | 99 | ++offset; |
405 | 99 | goto basic; |
406 | 99 | } |
407 | 97 | data32.reserve(text_size); |
408 | 1.96M | for (const auto& value : data8) { |
409 | 1.96M | data32.push_back(value); |
410 | 1.96M | } |
411 | 97 | std::vector<uint8_t>().swap(data8); |
412 | 97 | data32.push_back(code_point); |
413 | 97 | Traits::Advance(it, code_units); |
414 | 97 | index += code_units; |
415 | 97 | ++offset; |
416 | 97 | goto supplemental; |
417 | 196 | } |
418 | 351 | line_offsets.push_back(offset + 1); |
419 | 351 | return std::make_unique<Latin1Source>( |
420 | 351 | std::move(description), std::move(line_offsets), std::move(data8)); |
421 | 1.15k | basic: |
422 | 15.4M | while (index < text_size) { |
423 | 15.4M | std::tie(code_point, code_units) = internal::Utf8Decode(it); |
424 | 15.4M | if (ABSL_PREDICT_FALSE(code_point == |
425 | 15.4M | internal::kUnicodeReplacementCharacter && |
426 | 15.4M | code_units == 1)) { |
427 | | // Thats an invalid UTF-8 encoding. |
428 | 43 | return absl::InvalidArgumentError("cannot parse malformed UTF-8 input"); |
429 | 43 | } |
430 | 15.4M | if (code_point == '\n') { |
431 | 6.97M | line_offsets.push_back(offset + 1); |
432 | 6.97M | } |
433 | 15.4M | if (code_point <= 0xffff) { |
434 | 15.4M | data16.push_back(static_cast<char16_t>(code_point)); |
435 | 15.4M | Traits::Advance(it, code_units); |
436 | 15.4M | index += code_units; |
437 | 15.4M | ++offset; |
438 | 15.4M | continue; |
439 | 15.4M | } |
440 | 129 | data32.reserve(text_size); |
441 | 3.23M | for (const auto& value : data16) { |
442 | 3.23M | data32.push_back(static_cast<char32_t>(value)); |
443 | 3.23M | } |
444 | 129 | std::vector<char16_t>().swap(data16); |
445 | 129 | data32.push_back(code_point); |
446 | 129 | Traits::Advance(it, code_units); |
447 | 129 | index += code_units; |
448 | 129 | ++offset; |
449 | 129 | goto supplemental; |
450 | 15.4M | } |
451 | 981 | line_offsets.push_back(offset + 1); |
452 | 981 | return std::make_unique<BasicPlaneSource>( |
453 | 981 | std::move(description), std::move(line_offsets), std::move(data16)); |
454 | 1.01k | supplemental: |
455 | 30.3M | while (index < text_size) { |
456 | 30.3M | std::tie(code_point, code_units) = internal::Utf8Decode(it); |
457 | 30.3M | if (ABSL_PREDICT_FALSE(code_point == |
458 | 30.3M | internal::kUnicodeReplacementCharacter && |
459 | 30.3M | code_units == 1)) { |
460 | | // Thats an invalid UTF-8 encoding. |
461 | 54 | return absl::InvalidArgumentError("cannot parse malformed UTF-8 input"); |
462 | 54 | } |
463 | 30.3M | if (code_point == '\n') { |
464 | 10.3M | line_offsets.push_back(offset + 1); |
465 | 10.3M | } |
466 | 30.3M | data32.push_back(code_point); |
467 | 30.3M | Traits::Advance(it, code_units); |
468 | 30.3M | index += code_units; |
469 | 30.3M | ++offset; |
470 | 30.3M | } |
471 | 957 | line_offsets.push_back(offset + 1); |
472 | 957 | return std::make_unique<SupplementalPlaneSource>( |
473 | 957 | std::move(description), std::move(line_offsets), std::move(data32)); |
474 | 1.01k | } source.cc:absl::lts_20260526::StatusOr<std::__1::unique_ptr<cel::Source, std::__1::default_delete<cel::Source> > > cel::common_internal::(anonymous namespace)::NewSourceImpl<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, unsigned long) Line | Count | Source | 310 | 21.8k | const size_t text_size) { | 311 | 21.8k | if (ABSL_PREDICT_FALSE( | 312 | 21.8k | text_size > | 313 | 21.8k | static_cast<size_t>(std::numeric_limits<int32_t>::max()))) { | 314 | 0 | return absl::InvalidArgumentError("expression larger than 2GiB limit"); | 315 | 0 | } | 316 | 21.8k | using Traits = SourceTextTraits<T>; | 317 | 21.8k | size_t index = 0; | 318 | 21.8k | typename Traits::iterator_type it = Traits::Begin(text); | 319 | 21.8k | SourcePosition offset = 0; | 320 | 21.8k | char32_t code_point; | 321 | 21.8k | size_t code_units; | 322 | 21.8k | std::vector<uint8_t> data8; | 323 | 21.8k | std::vector<char16_t> data16; | 324 | 21.8k | std::vector<char32_t> data32; | 325 | 21.8k | absl::InlinedVector<SourcePosition, 1> line_offsets; | 326 | 116M | while (index < text_size) { | 327 | 116M | std::tie(code_point, code_units) = cel::internal::Utf8Decode(it); | 328 | 116M | if (ABSL_PREDICT_FALSE(code_point == | 329 | 116M | cel::internal::kUnicodeReplacementCharacter && | 330 | 116M | code_units == 1)) { | 331 | | // Thats an invalid UTF-8 encoding. | 332 | 49 | return absl::InvalidArgumentError("cannot parse malformed UTF-8 input"); | 333 | 49 | } | 334 | 116M | if (code_point == '\n') { | 335 | 35.0M | line_offsets.push_back(offset + 1); | 336 | 35.0M | } | 337 | 116M | if (code_point <= 0x7f) { | 338 | 116M | Traits::Advance(it, code_units); | 339 | 116M | index += code_units; | 340 | 116M | ++offset; | 341 | 116M | continue; | 342 | 116M | } | 343 | 2.42k | if (code_point <= 0xff) { | 344 | 583 | data8.reserve(text_size); | 345 | 583 | Traits::AppendTo(data8, text, index); | 346 | 583 | data8.push_back(static_cast<uint8_t>(code_point)); | 347 | 583 | Traits::Advance(it, code_units); | 348 | 583 | index += code_units; | 349 | 583 | ++offset; | 350 | 583 | goto latin1; | 351 | 583 | } | 352 | 1.83k | if (code_point <= 0xffff) { | 353 | 1.05k | data16.reserve(text_size); | 354 | 16.9M | for (size_t offset = 0; offset < index; offset++) { | 355 | 16.9M | data16.push_back(static_cast<uint8_t>(text[offset])); | 356 | 16.9M | } | 357 | 1.05k | data16.push_back(static_cast<char16_t>(code_point)); | 358 | 1.05k | Traits::Advance(it, code_units); | 359 | 1.05k | index += code_units; | 360 | 1.05k | ++offset; | 361 | 1.05k | goto basic; | 362 | 1.05k | } | 363 | 785 | data32.reserve(text_size); | 364 | 5.39M | for (size_t offset = 0; offset < index; offset++) { | 365 | 5.39M | data32.push_back(static_cast<char32_t>(text[offset])); | 366 | 5.39M | } | 367 | 785 | data32.push_back(code_point); | 368 | 785 | Traits::Advance(it, code_units); | 369 | 785 | index += code_units; | 370 | 785 | ++offset; | 371 | 785 | goto supplemental; | 372 | 1.83k | } | 373 | 19.3k | line_offsets.push_back(offset + 1); | 374 | 19.3k | return std::make_unique<AsciiSource>( | 375 | 19.3k | std::move(description), std::move(line_offsets), Traits::ToVector(text)); | 376 | 583 | latin1: | 377 | 7.76M | while (index < text_size) { | 378 | 7.76M | std::tie(code_point, code_units) = internal::Utf8Decode(it); | 379 | 7.76M | if (ABSL_PREDICT_FALSE(code_point == | 380 | 7.76M | internal::kUnicodeReplacementCharacter && | 381 | 7.76M | code_units == 1)) { | 382 | | // Thats an invalid UTF-8 encoding. | 383 | 36 | return absl::InvalidArgumentError("cannot parse malformed UTF-8 input"); | 384 | 36 | } | 385 | 7.76M | if (code_point == '\n') { | 386 | 4.76M | line_offsets.push_back(offset + 1); | 387 | 4.76M | } | 388 | 7.76M | if (code_point <= 0xff) { | 389 | 7.76M | data8.push_back(static_cast<uint8_t>(code_point)); | 390 | 7.76M | Traits::Advance(it, code_units); | 391 | 7.76M | index += code_units; | 392 | 7.76M | ++offset; | 393 | 7.76M | continue; | 394 | 7.76M | } | 395 | 196 | if (code_point <= 0xffff) { | 396 | 99 | data16.reserve(text_size); | 397 | 2.73M | for (const auto& value : data8) { | 398 | 2.73M | data16.push_back(value); | 399 | 2.73M | } | 400 | 99 | std::vector<uint8_t>().swap(data8); | 401 | 99 | data16.push_back(static_cast<char16_t>(code_point)); | 402 | 99 | Traits::Advance(it, code_units); | 403 | 99 | index += code_units; | 404 | 99 | ++offset; | 405 | 99 | goto basic; | 406 | 99 | } | 407 | 97 | data32.reserve(text_size); | 408 | 1.96M | for (const auto& value : data8) { | 409 | 1.96M | data32.push_back(value); | 410 | 1.96M | } | 411 | 97 | std::vector<uint8_t>().swap(data8); | 412 | 97 | data32.push_back(code_point); | 413 | 97 | Traits::Advance(it, code_units); | 414 | 97 | index += code_units; | 415 | 97 | ++offset; | 416 | 97 | goto supplemental; | 417 | 196 | } | 418 | 351 | line_offsets.push_back(offset + 1); | 419 | 351 | return std::make_unique<Latin1Source>( | 420 | 351 | std::move(description), std::move(line_offsets), std::move(data8)); | 421 | 1.15k | basic: | 422 | 15.4M | while (index < text_size) { | 423 | 15.4M | std::tie(code_point, code_units) = internal::Utf8Decode(it); | 424 | 15.4M | if (ABSL_PREDICT_FALSE(code_point == | 425 | 15.4M | internal::kUnicodeReplacementCharacter && | 426 | 15.4M | code_units == 1)) { | 427 | | // Thats an invalid UTF-8 encoding. | 428 | 43 | return absl::InvalidArgumentError("cannot parse malformed UTF-8 input"); | 429 | 43 | } | 430 | 15.4M | if (code_point == '\n') { | 431 | 6.97M | line_offsets.push_back(offset + 1); | 432 | 6.97M | } | 433 | 15.4M | if (code_point <= 0xffff) { | 434 | 15.4M | data16.push_back(static_cast<char16_t>(code_point)); | 435 | 15.4M | Traits::Advance(it, code_units); | 436 | 15.4M | index += code_units; | 437 | 15.4M | ++offset; | 438 | 15.4M | continue; | 439 | 15.4M | } | 440 | 129 | data32.reserve(text_size); | 441 | 3.23M | for (const auto& value : data16) { | 442 | 3.23M | data32.push_back(static_cast<char32_t>(value)); | 443 | 3.23M | } | 444 | 129 | std::vector<char16_t>().swap(data16); | 445 | 129 | data32.push_back(code_point); | 446 | 129 | Traits::Advance(it, code_units); | 447 | 129 | index += code_units; | 448 | 129 | ++offset; | 449 | 129 | goto supplemental; | 450 | 15.4M | } | 451 | 981 | line_offsets.push_back(offset + 1); | 452 | 981 | return std::make_unique<BasicPlaneSource>( | 453 | 981 | std::move(description), std::move(line_offsets), std::move(data16)); | 454 | 1.01k | supplemental: | 455 | 30.3M | while (index < text_size) { | 456 | 30.3M | std::tie(code_point, code_units) = internal::Utf8Decode(it); | 457 | 30.3M | if (ABSL_PREDICT_FALSE(code_point == | 458 | 30.3M | internal::kUnicodeReplacementCharacter && | 459 | 30.3M | code_units == 1)) { | 460 | | // Thats an invalid UTF-8 encoding. | 461 | 54 | return absl::InvalidArgumentError("cannot parse malformed UTF-8 input"); | 462 | 54 | } | 463 | 30.3M | if (code_point == '\n') { | 464 | 10.3M | line_offsets.push_back(offset + 1); | 465 | 10.3M | } | 466 | 30.3M | data32.push_back(code_point); | 467 | 30.3M | Traits::Advance(it, code_units); | 468 | 30.3M | index += code_units; | 469 | 30.3M | ++offset; | 470 | 30.3M | } | 471 | 957 | line_offsets.push_back(offset + 1); | 472 | 957 | return std::make_unique<SupplementalPlaneSource>( | 473 | 957 | std::move(description), std::move(line_offsets), std::move(data32)); | 474 | 1.01k | } |
Unexecuted instantiation: source.cc:absl::lts_20260526::StatusOr<std::__1::unique_ptr<cel::Source, std::__1::default_delete<cel::Source> > > cel::common_internal::(anonymous namespace)::NewSourceImpl<absl::lts_20260526::Cord>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, absl::lts_20260526::Cord const&, unsigned long) |
475 | | |
476 | | } // namespace |
477 | | |
478 | | } // namespace common_internal |
479 | | |
480 | | absl::optional<SourceLocation> Source::GetLocation( |
481 | 190k | SourcePosition position) const { |
482 | 190k | if (auto line_and_offset = FindLine(position); |
483 | 190k | ABSL_PREDICT_TRUE(line_and_offset.has_value())) { |
484 | 187k | return SourceLocation{line_and_offset->first, |
485 | 187k | position - line_and_offset->second}; |
486 | 187k | } |
487 | 2.84k | return std::nullopt; |
488 | 190k | } |
489 | | |
490 | | absl::optional<SourcePosition> Source::GetPosition( |
491 | 8.20M | const SourceLocation& location) const { |
492 | 8.20M | if (ABSL_PREDICT_FALSE(location.line < 1 || location.column < 0)) { |
493 | 0 | return std::nullopt; |
494 | 0 | } |
495 | 8.20M | if (auto position = FindLinePosition(location.line); |
496 | 8.20M | ABSL_PREDICT_TRUE(position.has_value())) { |
497 | 8.20M | return *position + location.column; |
498 | 8.20M | } |
499 | 0 | return std::nullopt; |
500 | 8.20M | } |
501 | | |
502 | 191k | absl::optional<std::string> Source::Snippet(int32_t line) const { |
503 | 191k | auto content = this->content(); |
504 | 191k | auto start = FindLinePosition(line); |
505 | 191k | if (ABSL_PREDICT_FALSE(!start.has_value() || content.empty())) { |
506 | 3.63k | return std::nullopt; |
507 | 3.63k | } |
508 | 187k | auto end = FindLinePosition(line + 1); |
509 | 187k | if (end.has_value()) { |
510 | 39.4k | return content.ToString(*start, *end - 1); |
511 | 39.4k | } |
512 | 148k | return content.ToString(*start); |
513 | 187k | } |
514 | | |
515 | 191k | std::string Source::DisplayErrorLocation(SourceLocation location) const { |
516 | 191k | constexpr char32_t kDot = '.'; |
517 | 191k | constexpr char32_t kHat = '^'; |
518 | | |
519 | 191k | constexpr char32_t kWideDot = 0xff0e; |
520 | 191k | constexpr char32_t kWideHat = 0xff3e; |
521 | 191k | absl::optional<std::string> snippet = Snippet(location.line); |
522 | 191k | if (!snippet || snippet->empty()) { |
523 | 4.14k | return ""; |
524 | 4.14k | } |
525 | | |
526 | 186k | *snippet = absl::StrReplaceAll(*snippet, {{"\t", " "}}); |
527 | 186k | absl::string_view snippet_view(*snippet); |
528 | 186k | std::string result; |
529 | 186k | absl::StrAppend(&result, "\n | ", *snippet); |
530 | 186k | absl::StrAppend(&result, "\n | "); |
531 | | |
532 | 186k | std::string index_line; |
533 | 635M | for (int32_t i = 0; i < location.column && !snippet_view.empty(); ++i) { |
534 | 635M | size_t count; |
535 | 635M | std::tie(std::ignore, count) = internal::Utf8Decode(snippet_view); |
536 | 635M | snippet_view.remove_prefix(count); |
537 | 635M | if (count > 1) { |
538 | 149k | internal::Utf8Encode(index_line, kWideDot); |
539 | 635M | } else { |
540 | 635M | internal::Utf8Encode(index_line, kDot); |
541 | 635M | } |
542 | 635M | } |
543 | 186k | size_t count = 0; |
544 | 186k | if (!snippet_view.empty()) { |
545 | 180k | std::tie(std::ignore, count) = internal::Utf8Decode(snippet_view); |
546 | 180k | } |
547 | 186k | if (count > 1) { |
548 | 3.90k | internal::Utf8Encode(index_line, kWideHat); |
549 | 183k | } else { |
550 | 183k | internal::Utf8Encode(index_line, kHat); |
551 | 183k | } |
552 | 186k | absl::StrAppend(&result, index_line); |
553 | 186k | return result; |
554 | 191k | } |
555 | | |
556 | 8.58M | absl::optional<SourcePosition> Source::FindLinePosition(int32_t line) const { |
557 | 8.58M | if (ABSL_PREDICT_FALSE(line < 1)) { |
558 | 3.63k | return std::nullopt; |
559 | 3.63k | } |
560 | 8.58M | if (line == 1) { |
561 | 6.15M | return SourcePosition{0}; |
562 | 6.15M | } |
563 | 2.42M | const auto line_offsets = this->line_offsets(); |
564 | 2.42M | if (ABSL_PREDICT_TRUE(line <= static_cast<int32_t>(line_offsets.size()))) { |
565 | 2.27M | return line_offsets[static_cast<size_t>(line - 2)]; |
566 | 2.27M | } |
567 | 148k | return std::nullopt; |
568 | 2.42M | } |
569 | | |
570 | | absl::optional<std::pair<int32_t, SourcePosition>> Source::FindLine( |
571 | 190k | SourcePosition position) const { |
572 | 190k | if (ABSL_PREDICT_FALSE(position < 0)) { |
573 | 2.84k | return std::nullopt; |
574 | 2.84k | } |
575 | 187k | int32_t line = 1; |
576 | 187k | const auto line_offsets = this->line_offsets(); |
577 | 1.22G | for (const auto& line_offset : line_offsets) { |
578 | 1.22G | if (line_offset > position) { |
579 | 187k | break; |
580 | 187k | } |
581 | 1.22G | ++line; |
582 | 1.22G | } |
583 | 187k | if (line == 1) { |
584 | 148k | return std::make_pair(line, SourcePosition{0}); |
585 | 148k | } |
586 | 38.8k | return std::make_pair(line, line_offsets[static_cast<size_t>(line) - 2]); |
587 | 187k | } |
588 | | |
589 | | SourceSubrange::SourceSubrange(const Source& source, SourceRange range) |
590 | 0 | : source_(source), range_(range) { |
591 | 0 | SourcePosition size = source_.content().size(); |
592 | 0 | ABSL_DCHECK(range_.begin >= 0); |
593 | 0 | ABSL_DCHECK(range_.begin <= size); |
594 | 0 | ABSL_DCHECK(range_.end >= range_.begin); |
595 | 0 | ABSL_DCHECK(range_.end <= size); |
596 | 0 | if (range_.begin < 0) { |
597 | 0 | range_.begin = 0; |
598 | 0 | } |
599 | 0 | if (range_.begin > size) { |
600 | 0 | range_.begin = size; |
601 | 0 | } |
602 | 0 | if (range_.end < range_.begin) { |
603 | 0 | range_.end = range_.begin; |
604 | 0 | } |
605 | 0 | if (range_.end > size) { |
606 | 0 | range_.end = size; |
607 | 0 | } |
608 | 0 | for (const auto& line_offset : source_.line_offsets()) { |
609 | 0 | if (line_offset > range_.begin && line_offset <= range_.end) { |
610 | 0 | line_offsets_.push_back(line_offset - range_.begin); |
611 | 0 | } |
612 | 0 | } |
613 | 0 | line_offsets_.push_back(range_.end - range_.begin + 1); |
614 | 0 | } |
615 | | |
616 | 0 | SourceContentView SourceSubrange::content() const { |
617 | 0 | auto parent_content = source_.content(); |
618 | 0 | if (parent_content.empty() || range_.begin >= range_.end) { |
619 | 0 | return EmptyContentView(); |
620 | 0 | } |
621 | 0 | return absl::visit( |
622 | 0 | [this](auto view) { |
623 | 0 | return SourceContentView( |
624 | 0 | view.subspan(static_cast<size_t>(range_.begin), |
625 | 0 | static_cast<size_t>(range_.end - range_.begin))); |
626 | 0 | }, Unexecuted instantiation: source.cc:auto cel::SourceSubrange::content() const::$_0::operator()<absl::lts_20260526::Span<char const> >(absl::lts_20260526::Span<char const>) const Unexecuted instantiation: source.cc:auto cel::SourceSubrange::content() const::$_0::operator()<absl::lts_20260526::Span<unsigned char const> >(absl::lts_20260526::Span<unsigned char const>) const Unexecuted instantiation: source.cc:auto cel::SourceSubrange::content() const::$_0::operator()<absl::lts_20260526::Span<char16_t const> >(absl::lts_20260526::Span<char16_t const>) const Unexecuted instantiation: source.cc:auto cel::SourceSubrange::content() const::$_0::operator()<absl::lts_20260526::Span<char32_t const> >(absl::lts_20260526::Span<char32_t const>) const |
627 | 0 | parent_content.view_); |
628 | 0 | } |
629 | | |
630 | 0 | absl::Span<const SourcePosition> SourceSubrange::line_offsets() const { |
631 | 0 | return absl::MakeConstSpan(line_offsets_); |
632 | 0 | } |
633 | | |
634 | | absl::StatusOr<absl_nonnull SourcePtr> NewSource(absl::string_view content, |
635 | 21.8k | std::string description) { |
636 | 21.8k | return common_internal::NewSourceImpl(std::move(description), content, |
637 | 21.8k | content.size()); |
638 | 21.8k | } |
639 | | |
640 | | absl::StatusOr<absl_nonnull SourcePtr> NewSource(const absl::Cord& content, |
641 | 0 | std::string description) { |
642 | 0 | return common_internal::NewSourceImpl(std::move(description), content, |
643 | 0 | content.size()); |
644 | 0 | } |
645 | | |
646 | | } // namespace cel |