Coverage Report

Created: 2026-09-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
219k
SourcePosition SourceContentView::size() const {
48
219k
  return static_cast<SourcePosition>(absl::visit(
49
219k
      absl::Overload(
50
219k
          [](absl::Span<const char> view) { return view.size(); },
51
219k
          [](absl::Span<const uint8_t> view) { return view.size(); },
52
219k
          [](absl::Span<const char16_t> view) { return view.size(); },
53
219k
          [](absl::Span<const char32_t> view) { return view.size(); }),
54
219k
      view_));
55
219k
}
56
57
227k
bool SourceContentView::empty() const {
58
227k
  return absl::visit(
59
227k
      absl::Overload(
60
227k
          [](absl::Span<const char> view) { return view.empty(); },
61
227k
          [](absl::Span<const uint8_t> view) { return view.empty(); },
62
227k
          [](absl::Span<const char16_t> view) { return view.empty(); },
63
227k
          [](absl::Span<const char32_t> view) { return view.empty(); }),
64
227k
      view_);
65
227k
}
66
67
192M
char32_t SourceContentView::at(SourcePosition position) const {
68
192M
  ABSL_DCHECK_GE(position, 0);
69
192M
  ABSL_DCHECK_LT(position, size());
70
192M
  return absl::visit(
71
192M
      absl::Overload(
72
192M
          [position =
73
192M
               static_cast<size_t>(position)](absl::Span<const char> view) {
74
97.0M
            return static_cast<char32_t>(static_cast<uint8_t>(view[position]));
75
97.0M
          },
76
192M
          [position =
77
192M
               static_cast<size_t>(position)](absl::Span<const uint8_t> view) {
78
11.1M
            return static_cast<char32_t>(view[position]);
79
11.1M
          },
80
192M
          [position =
81
192M
               static_cast<size_t>(position)](absl::Span<const char16_t> view) {
82
16.4M
            return static_cast<char32_t>(view[position]);
83
16.4M
          },
84
192M
          [position =
85
192M
               static_cast<size_t>(position)](absl::Span<const char32_t> view) {
86
67.8M
            return static_cast<char32_t>(view[position]);
87
67.8M
          }),
88
192M
      view_);
89
192M
}
90
91
std::string SourceContentView::ToString(SourcePosition begin,
92
12.7M
                                        SourcePosition end) const {
93
12.7M
  ABSL_DCHECK_GE(begin, 0);
94
12.7M
  ABSL_DCHECK_LE(end, size());
95
12.7M
  ABSL_DCHECK_LE(begin, end);
96
12.7M
  return absl::visit(
97
12.7M
      absl::Overload(
98
12.7M
          [begin = static_cast<size_t>(begin),
99
12.7M
           end = static_cast<size_t>(end)](absl::Span<const char> view) {
100
9.01M
            view = view.subspan(begin, end - begin);
101
9.01M
            return std::string(view.data(), view.size());
102
9.01M
          },
103
12.7M
          [begin = static_cast<size_t>(begin),
104
12.7M
           end = static_cast<size_t>(end)](absl::Span<const uint8_t> view) {
105
677k
            view = view.subspan(begin, end - begin);
106
677k
            std::string result;
107
677k
            result.reserve(view.size() * 2);
108
106M
            for (const auto& code_point : view) {
109
106M
              internal::Utf8Encode(result, code_point);
110
106M
            }
111
677k
            result.shrink_to_fit();
112
677k
            return result;
113
677k
          },
114
12.7M
          [begin = static_cast<size_t>(begin),
115
12.7M
           end = static_cast<size_t>(end)](absl::Span<const char16_t> view) {
116
1.52M
            view = view.subspan(begin, end - begin);
117
1.52M
            std::string result;
118
1.52M
            result.reserve(view.size() * 3);
119
266M
            for (const auto& code_point : view) {
120
266M
              internal::Utf8Encode(result, code_point);
121
266M
            }
122
1.52M
            result.shrink_to_fit();
123
1.52M
            return result;
124
1.52M
          },
125
12.7M
          [begin = static_cast<size_t>(begin),
126
12.7M
           end = static_cast<size_t>(end)](absl::Span<const char32_t> view) {
127
1.53M
            view = view.subspan(begin, end - begin);
128
1.53M
            std::string result;
129
1.53M
            result.reserve(view.size() * 4);
130
262M
            for (const auto& code_point : view) {
131
262M
              internal::Utf8Encode(result, code_point);
132
262M
            }
133
1.53M
            result.shrink_to_fit();
134
1.53M
            return result;
135
1.53M
          }),
136
12.7M
      view_);
137
12.7M
}
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
35.3k
      : description_(std::move(description)),
169
35.3k
        line_offsets_(std::move(line_offsets)) {}
170
171
290k
  absl::string_view description() const final { return description_; }
172
173
846k
  absl::Span<const SourcePosition> line_offsets() const final {
174
846k
    return absl::MakeConstSpan(line_offsets_);
175
846k
  }
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
32.2k
      : SourceImpl(std::move(description), std::move(line_offsets)),
190
32.2k
        text_(std::move(text)) {}
191
192
193k
  ContentView content() const override {
193
193k
    return MakeContentView(absl::MakeConstSpan(text_));
194
193k
  }
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
442
      : SourceImpl(std::move(description), std::move(line_offsets)),
206
442
        text_(std::move(text)) {}
207
208
11.9k
  ContentView content() const override {
209
11.9k
    return MakeContentView(absl::MakeConstSpan(text_));
210
11.9k
  }
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
1.40k
      : SourceImpl(std::move(description), std::move(line_offsets)),
222
1.40k
        text_(std::move(text)) {}
223
224
31.8k
  ContentView content() const override {
225
31.8k
    return MakeContentView(absl::MakeConstSpan(text_));
226
31.8k
  }
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
1.19k
      : SourceImpl(std::move(description), std::move(line_offsets)),
238
1.19k
        text_(std::move(text)) {}
239
240
30.7k
  ContentView content() const override {
241
30.7k
    return MakeContentView(absl::MakeConstSpan(text_));
242
30.7k
  }
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
35.5k
  static iterator_type Begin(absl::string_view text) { return text; }
256
257
46.7M
  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
737
                       size_t n) {
261
737
    const auto* in = reinterpret_cast<const uint8_t*>(text.data());
262
737
    out.insert(out.end(), in, in + n);
263
737
  }
264
265
32.2k
  static std::vector<char> ToVector(absl::string_view in) {
266
32.2k
    std::vector<char> out;
267
32.2k
    out.reserve(in.size());
268
32.2k
    out.insert(out.end(), in.begin(), in.end());
269
32.2k
    return out;
270
32.2k
  }
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
                                        const size_t text_size,
311
35.6k
                                        const size_t max_codepoints) {
312
35.6k
  if (ABSL_PREDICT_FALSE(
313
35.6k
          text_size >
314
35.6k
          static_cast<size_t>(std::numeric_limits<int32_t>::max()))) {
315
0
    return absl::InvalidArgumentError("expression larger than 2GiB limit");
316
0
  }
317
35.6k
  if ((text_size >> 2) > max_codepoints) {
318
    // If byte size is 4 times the codepoint limit, then definitely exceeded.
319
29
    return absl::InvalidArgumentError(absl::StrCat(
320
29
        "expression is larger than codepoint limit ", max_codepoints));
321
29
  }
322
35.5k
  using Traits = SourceTextTraits<T>;
323
35.5k
  size_t index = 0;
324
35.5k
  typename Traits::iterator_type it = Traits::Begin(text);
325
35.5k
  SourcePosition offset = 0;
326
35.5k
  char32_t code_point;
327
35.5k
  size_t code_units;
328
35.5k
  std::vector<uint8_t> data8;
329
35.5k
  std::vector<char16_t> data16;
330
35.5k
  std::vector<char32_t> data32;
331
35.5k
  absl::InlinedVector<SourcePosition, 1> line_offsets;
332
30.9M
  while (index < text_size) {
333
30.9M
    if (offset >= max_codepoints) {
334
14
      return absl::InvalidArgumentError(absl::StrCat(
335
14
          "expression is larger than codepoint limit ", max_codepoints));
336
14
    }
337
30.9M
    std::tie(code_point, code_units) = cel::internal::Utf8Decode(it);
338
30.9M
    if (ABSL_PREDICT_FALSE(code_point ==
339
30.9M
                               cel::internal::kUnicodeReplacementCharacter &&
340
30.9M
                           code_units == 1)) {
341
      // Thats an invalid UTF-8 encoding.
342
73
      return absl::InvalidArgumentError("cannot parse malformed UTF-8 input");
343
73
    }
344
30.9M
    if (code_point == '\n') {
345
6.17M
      line_offsets.push_back(offset + 1);
346
6.17M
    }
347
30.9M
    if (code_point <= 0x7f) {
348
30.9M
      Traits::Advance(it, code_units);
349
30.9M
      index += code_units;
350
30.9M
      ++offset;
351
30.9M
      continue;
352
30.9M
    }
353
3.20k
    if (code_point <= 0xff) {
354
737
      data8.reserve(text_size);
355
737
      Traits::AppendTo(data8, text, index);
356
737
      data8.push_back(static_cast<uint8_t>(code_point));
357
737
      Traits::Advance(it, code_units);
358
737
      index += code_units;
359
737
      ++offset;
360
737
      goto latin1;
361
737
    }
362
2.46k
    if (code_point <= 0xffff) {
363
1.50k
      data16.reserve(text_size);
364
3.54M
      for (size_t offset = 0; offset < index; offset++) {
365
3.54M
        data16.push_back(static_cast<uint8_t>(text[offset]));
366
3.54M
      }
367
1.50k
      data16.push_back(static_cast<char16_t>(code_point));
368
1.50k
      Traits::Advance(it, code_units);
369
1.50k
      index += code_units;
370
1.50k
      ++offset;
371
1.50k
      goto basic;
372
1.50k
    }
373
960
    data32.reserve(text_size);
374
1.44M
    for (size_t offset = 0; offset < index; offset++) {
375
1.44M
      data32.push_back(static_cast<char32_t>(text[offset]));
376
1.44M
    }
377
960
    data32.push_back(code_point);
378
960
    Traits::Advance(it, code_units);
379
960
    index += code_units;
380
960
    ++offset;
381
960
    goto supplemental;
382
2.46k
  }
383
32.2k
  line_offsets.push_back(offset + 1);
384
32.2k
  return std::make_unique<AsciiSource>(
385
32.2k
      std::move(description), std::move(line_offsets), Traits::ToVector(text));
386
737
latin1:
387
4.16M
  while (index < text_size) {
388
4.15M
    if (offset >= max_codepoints) {
389
10
      return absl::InvalidArgumentError(absl::StrCat(
390
10
          "expression is larger than codepoint limit ", max_codepoints));
391
10
    }
392
4.15M
    std::tie(code_point, code_units) = internal::Utf8Decode(it);
393
4.15M
    if (ABSL_PREDICT_FALSE(code_point ==
394
4.15M
                               internal::kUnicodeReplacementCharacter &&
395
4.15M
                           code_units == 1)) {
396
      // Thats an invalid UTF-8 encoding.
397
30
      return absl::InvalidArgumentError("cannot parse malformed UTF-8 input");
398
30
    }
399
4.15M
    if (code_point == '\n') {
400
291k
      line_offsets.push_back(offset + 1);
401
291k
    }
402
4.15M
    if (code_point <= 0xff) {
403
4.15M
      data8.push_back(static_cast<uint8_t>(code_point));
404
4.15M
      Traits::Advance(it, code_units);
405
4.15M
      index += code_units;
406
4.15M
      ++offset;
407
4.15M
      continue;
408
4.15M
    }
409
255
    if (code_point <= 0xffff) {
410
144
      data16.reserve(text_size);
411
608k
      for (const auto& value : data8) {
412
608k
        data16.push_back(value);
413
608k
      }
414
144
      std::vector<uint8_t>().swap(data8);
415
144
      data16.push_back(static_cast<char16_t>(code_point));
416
144
      Traits::Advance(it, code_units);
417
144
      index += code_units;
418
144
      ++offset;
419
144
      goto basic;
420
144
    }
421
111
    data32.reserve(text_size);
422
1.38M
    for (const auto& value : data8) {
423
1.38M
      data32.push_back(value);
424
1.38M
    }
425
111
    std::vector<uint8_t>().swap(data8);
426
111
    data32.push_back(code_point);
427
111
    Traits::Advance(it, code_units);
428
111
    index += code_units;
429
111
    ++offset;
430
111
    goto supplemental;
431
255
  }
432
442
  line_offsets.push_back(offset + 1);
433
442
  return std::make_unique<Latin1Source>(
434
442
      std::move(description), std::move(line_offsets), std::move(data8));
435
1.64k
basic:
436
5.90M
  while (index < text_size) {
437
5.90M
    if (offset >= max_codepoints) {
438
12
      return absl::InvalidArgumentError(absl::StrCat(
439
12
          "expression is larger than codepoint limit ", max_codepoints));
440
12
    }
441
5.90M
    std::tie(code_point, code_units) = internal::Utf8Decode(it);
442
5.90M
    if (ABSL_PREDICT_FALSE(code_point ==
443
5.90M
                               internal::kUnicodeReplacementCharacter &&
444
5.90M
                           code_units == 1)) {
445
      // Thats an invalid UTF-8 encoding.
446
38
      return absl::InvalidArgumentError("cannot parse malformed UTF-8 input");
447
38
    }
448
5.90M
    if (code_point == '\n') {
449
1.57M
      line_offsets.push_back(offset + 1);
450
1.57M
    }
451
5.90M
    if (code_point <= 0xffff) {
452
5.90M
      data16.push_back(static_cast<char16_t>(code_point));
453
5.90M
      Traits::Advance(it, code_units);
454
5.90M
      index += code_units;
455
5.90M
      ++offset;
456
5.90M
      continue;
457
5.90M
    }
458
190
    data32.reserve(text_size);
459
1.77M
    for (const auto& value : data16) {
460
1.77M
      data32.push_back(static_cast<char32_t>(value));
461
1.77M
    }
462
190
    std::vector<char16_t>().swap(data16);
463
190
    data32.push_back(code_point);
464
190
    Traits::Advance(it, code_units);
465
190
    index += code_units;
466
190
    ++offset;
467
190
    goto supplemental;
468
5.90M
  }
469
1.40k
  line_offsets.push_back(offset + 1);
470
1.40k
  return std::make_unique<BasicPlaneSource>(
471
1.40k
      std::move(description), std::move(line_offsets), std::move(data16));
472
1.26k
supplemental:
473
5.80M
  while (index < text_size) {
474
5.79M
    if (offset >= max_codepoints) {
475
16
      return absl::InvalidArgumentError(absl::StrCat(
476
16
          "expression is larger than codepoint limit ", max_codepoints));
477
16
    }
478
5.79M
    std::tie(code_point, code_units) = internal::Utf8Decode(it);
479
5.79M
    if (ABSL_PREDICT_FALSE(code_point ==
480
5.79M
                               internal::kUnicodeReplacementCharacter &&
481
5.79M
                           code_units == 1)) {
482
      // Thats an invalid UTF-8 encoding.
483
53
      return absl::InvalidArgumentError("cannot parse malformed UTF-8 input");
484
53
    }
485
5.79M
    if (code_point == '\n') {
486
2.17M
      line_offsets.push_back(offset + 1);
487
2.17M
    }
488
5.79M
    data32.push_back(code_point);
489
5.79M
    Traits::Advance(it, code_units);
490
5.79M
    index += code_units;
491
5.79M
    ++offset;
492
5.79M
  }
493
1.19k
  line_offsets.push_back(offset + 1);
494
1.19k
  return std::make_unique<SupplementalPlaneSource>(
495
1.19k
      std::move(description), std::move(line_offsets), std::move(data32));
496
1.26k
}
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, unsigned long)
Line
Count
Source
311
35.6k
                                        const size_t max_codepoints) {
312
35.6k
  if (ABSL_PREDICT_FALSE(
313
35.6k
          text_size >
314
35.6k
          static_cast<size_t>(std::numeric_limits<int32_t>::max()))) {
315
0
    return absl::InvalidArgumentError("expression larger than 2GiB limit");
316
0
  }
317
35.6k
  if ((text_size >> 2) > max_codepoints) {
318
    // If byte size is 4 times the codepoint limit, then definitely exceeded.
319
29
    return absl::InvalidArgumentError(absl::StrCat(
320
29
        "expression is larger than codepoint limit ", max_codepoints));
321
29
  }
322
35.5k
  using Traits = SourceTextTraits<T>;
323
35.5k
  size_t index = 0;
324
35.5k
  typename Traits::iterator_type it = Traits::Begin(text);
325
35.5k
  SourcePosition offset = 0;
326
35.5k
  char32_t code_point;
327
35.5k
  size_t code_units;
328
35.5k
  std::vector<uint8_t> data8;
329
35.5k
  std::vector<char16_t> data16;
330
35.5k
  std::vector<char32_t> data32;
331
35.5k
  absl::InlinedVector<SourcePosition, 1> line_offsets;
332
30.9M
  while (index < text_size) {
333
30.9M
    if (offset >= max_codepoints) {
334
14
      return absl::InvalidArgumentError(absl::StrCat(
335
14
          "expression is larger than codepoint limit ", max_codepoints));
336
14
    }
337
30.9M
    std::tie(code_point, code_units) = cel::internal::Utf8Decode(it);
338
30.9M
    if (ABSL_PREDICT_FALSE(code_point ==
339
30.9M
                               cel::internal::kUnicodeReplacementCharacter &&
340
30.9M
                           code_units == 1)) {
341
      // Thats an invalid UTF-8 encoding.
342
73
      return absl::InvalidArgumentError("cannot parse malformed UTF-8 input");
343
73
    }
344
30.9M
    if (code_point == '\n') {
345
6.17M
      line_offsets.push_back(offset + 1);
346
6.17M
    }
347
30.9M
    if (code_point <= 0x7f) {
348
30.9M
      Traits::Advance(it, code_units);
349
30.9M
      index += code_units;
350
30.9M
      ++offset;
351
30.9M
      continue;
352
30.9M
    }
353
3.20k
    if (code_point <= 0xff) {
354
737
      data8.reserve(text_size);
355
737
      Traits::AppendTo(data8, text, index);
356
737
      data8.push_back(static_cast<uint8_t>(code_point));
357
737
      Traits::Advance(it, code_units);
358
737
      index += code_units;
359
737
      ++offset;
360
737
      goto latin1;
361
737
    }
362
2.46k
    if (code_point <= 0xffff) {
363
1.50k
      data16.reserve(text_size);
364
3.54M
      for (size_t offset = 0; offset < index; offset++) {
365
3.54M
        data16.push_back(static_cast<uint8_t>(text[offset]));
366
3.54M
      }
367
1.50k
      data16.push_back(static_cast<char16_t>(code_point));
368
1.50k
      Traits::Advance(it, code_units);
369
1.50k
      index += code_units;
370
1.50k
      ++offset;
371
1.50k
      goto basic;
372
1.50k
    }
373
960
    data32.reserve(text_size);
374
1.44M
    for (size_t offset = 0; offset < index; offset++) {
375
1.44M
      data32.push_back(static_cast<char32_t>(text[offset]));
376
1.44M
    }
377
960
    data32.push_back(code_point);
378
960
    Traits::Advance(it, code_units);
379
960
    index += code_units;
380
960
    ++offset;
381
960
    goto supplemental;
382
2.46k
  }
383
32.2k
  line_offsets.push_back(offset + 1);
384
32.2k
  return std::make_unique<AsciiSource>(
385
32.2k
      std::move(description), std::move(line_offsets), Traits::ToVector(text));
386
737
latin1:
387
4.16M
  while (index < text_size) {
388
4.15M
    if (offset >= max_codepoints) {
389
10
      return absl::InvalidArgumentError(absl::StrCat(
390
10
          "expression is larger than codepoint limit ", max_codepoints));
391
10
    }
392
4.15M
    std::tie(code_point, code_units) = internal::Utf8Decode(it);
393
4.15M
    if (ABSL_PREDICT_FALSE(code_point ==
394
4.15M
                               internal::kUnicodeReplacementCharacter &&
395
4.15M
                           code_units == 1)) {
396
      // Thats an invalid UTF-8 encoding.
397
30
      return absl::InvalidArgumentError("cannot parse malformed UTF-8 input");
398
30
    }
399
4.15M
    if (code_point == '\n') {
400
291k
      line_offsets.push_back(offset + 1);
401
291k
    }
402
4.15M
    if (code_point <= 0xff) {
403
4.15M
      data8.push_back(static_cast<uint8_t>(code_point));
404
4.15M
      Traits::Advance(it, code_units);
405
4.15M
      index += code_units;
406
4.15M
      ++offset;
407
4.15M
      continue;
408
4.15M
    }
409
255
    if (code_point <= 0xffff) {
410
144
      data16.reserve(text_size);
411
608k
      for (const auto& value : data8) {
412
608k
        data16.push_back(value);
413
608k
      }
414
144
      std::vector<uint8_t>().swap(data8);
415
144
      data16.push_back(static_cast<char16_t>(code_point));
416
144
      Traits::Advance(it, code_units);
417
144
      index += code_units;
418
144
      ++offset;
419
144
      goto basic;
420
144
    }
421
111
    data32.reserve(text_size);
422
1.38M
    for (const auto& value : data8) {
423
1.38M
      data32.push_back(value);
424
1.38M
    }
425
111
    std::vector<uint8_t>().swap(data8);
426
111
    data32.push_back(code_point);
427
111
    Traits::Advance(it, code_units);
428
111
    index += code_units;
429
111
    ++offset;
430
111
    goto supplemental;
431
255
  }
432
442
  line_offsets.push_back(offset + 1);
433
442
  return std::make_unique<Latin1Source>(
434
442
      std::move(description), std::move(line_offsets), std::move(data8));
435
1.64k
basic:
436
5.90M
  while (index < text_size) {
437
5.90M
    if (offset >= max_codepoints) {
438
12
      return absl::InvalidArgumentError(absl::StrCat(
439
12
          "expression is larger than codepoint limit ", max_codepoints));
440
12
    }
441
5.90M
    std::tie(code_point, code_units) = internal::Utf8Decode(it);
442
5.90M
    if (ABSL_PREDICT_FALSE(code_point ==
443
5.90M
                               internal::kUnicodeReplacementCharacter &&
444
5.90M
                           code_units == 1)) {
445
      // Thats an invalid UTF-8 encoding.
446
38
      return absl::InvalidArgumentError("cannot parse malformed UTF-8 input");
447
38
    }
448
5.90M
    if (code_point == '\n') {
449
1.57M
      line_offsets.push_back(offset + 1);
450
1.57M
    }
451
5.90M
    if (code_point <= 0xffff) {
452
5.90M
      data16.push_back(static_cast<char16_t>(code_point));
453
5.90M
      Traits::Advance(it, code_units);
454
5.90M
      index += code_units;
455
5.90M
      ++offset;
456
5.90M
      continue;
457
5.90M
    }
458
190
    data32.reserve(text_size);
459
1.77M
    for (const auto& value : data16) {
460
1.77M
      data32.push_back(static_cast<char32_t>(value));
461
1.77M
    }
462
190
    std::vector<char16_t>().swap(data16);
463
190
    data32.push_back(code_point);
464
190
    Traits::Advance(it, code_units);
465
190
    index += code_units;
466
190
    ++offset;
467
190
    goto supplemental;
468
5.90M
  }
469
1.40k
  line_offsets.push_back(offset + 1);
470
1.40k
  return std::make_unique<BasicPlaneSource>(
471
1.40k
      std::move(description), std::move(line_offsets), std::move(data16));
472
1.26k
supplemental:
473
5.80M
  while (index < text_size) {
474
5.79M
    if (offset >= max_codepoints) {
475
16
      return absl::InvalidArgumentError(absl::StrCat(
476
16
          "expression is larger than codepoint limit ", max_codepoints));
477
16
    }
478
5.79M
    std::tie(code_point, code_units) = internal::Utf8Decode(it);
479
5.79M
    if (ABSL_PREDICT_FALSE(code_point ==
480
5.79M
                               internal::kUnicodeReplacementCharacter &&
481
5.79M
                           code_units == 1)) {
482
      // Thats an invalid UTF-8 encoding.
483
53
      return absl::InvalidArgumentError("cannot parse malformed UTF-8 input");
484
53
    }
485
5.79M
    if (code_point == '\n') {
486
2.17M
      line_offsets.push_back(offset + 1);
487
2.17M
    }
488
5.79M
    data32.push_back(code_point);
489
5.79M
    Traits::Advance(it, code_units);
490
5.79M
    index += code_units;
491
5.79M
    ++offset;
492
5.79M
  }
493
1.19k
  line_offsets.push_back(offset + 1);
494
1.19k
  return std::make_unique<SupplementalPlaneSource>(
495
1.19k
      std::move(description), std::move(line_offsets), std::move(data32));
496
1.26k
}
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, unsigned long)
497
498
}  // namespace
499
500
}  // namespace common_internal
501
502
absl::optional<SourceLocation> Source::GetLocation(
503
232k
    SourcePosition position) const {
504
232k
  if (auto line_and_offset = FindLine(position);
505
232k
      ABSL_PREDICT_TRUE(line_and_offset.has_value())) {
506
227k
    return SourceLocation{line_and_offset->first,
507
227k
                          position - line_and_offset->second};
508
227k
  }
509
4.25k
  return std::nullopt;
510
232k
}
511
512
absl::optional<SourcePosition> Source::GetPosition(
513
1.74M
    const SourceLocation& location) const {
514
1.74M
  if (ABSL_PREDICT_FALSE(location.line < 1 || location.column < 0)) {
515
0
    return std::nullopt;
516
0
  }
517
1.74M
  if (auto position = FindLinePosition(location.line);
518
1.74M
      ABSL_PREDICT_TRUE(position.has_value())) {
519
1.74M
    return *position + location.column;
520
1.74M
  }
521
0
  return std::nullopt;
522
1.74M
}
523
524
233k
absl::optional<std::string> Source::Snippet(int32_t line) const {
525
233k
  auto content = this->content();
526
233k
  auto start = FindLinePosition(line);
527
233k
  if (ABSL_PREDICT_FALSE(!start.has_value() || content.empty())) {
528
5.18k
    return std::nullopt;
529
5.18k
  }
530
227k
  auto end = FindLinePosition(line + 1);
531
227k
  if (end.has_value()) {
532
44.2k
    return content.ToString(*start, *end - 1);
533
44.2k
  }
534
183k
  return content.ToString(*start);
535
227k
}
536
537
233k
std::string Source::DisplayErrorLocation(SourceLocation location) const {
538
233k
  constexpr char32_t kDot = '.';
539
233k
  constexpr char32_t kHat = '^';
540
541
233k
  constexpr char32_t kWideDot = 0xff0e;
542
233k
  constexpr char32_t kWideHat = 0xff3e;
543
233k
  absl::optional<std::string> snippet = Snippet(location.line);
544
233k
  if (!snippet || snippet->empty()) {
545
5.92k
    return "";
546
5.92k
  }
547
548
227k
  *snippet = absl::StrReplaceAll(*snippet, {{"\t", " "}});
549
227k
  absl::string_view snippet_view(*snippet);
550
227k
  std::string result;
551
227k
  absl::StrAppend(&result, "\n | ", *snippet);
552
227k
  absl::StrAppend(&result, "\n | ");
553
554
227k
  std::string index_line;
555
316M
  for (int32_t i = 0; i < location.column && !snippet_view.empty(); ++i) {
556
316M
    size_t count;
557
316M
    std::tie(std::ignore, count) = internal::Utf8Decode(snippet_view);
558
316M
    snippet_view.remove_prefix(count);
559
316M
    if (count > 1) {
560
5.68M
      internal::Utf8Encode(index_line, kWideDot);
561
310M
    } else {
562
310M
      internal::Utf8Encode(index_line, kDot);
563
310M
    }
564
316M
  }
565
227k
  size_t count = 0;
566
227k
  if (!snippet_view.empty()) {
567
217k
    std::tie(std::ignore, count) = internal::Utf8Decode(snippet_view);
568
217k
  }
569
227k
  if (count > 1) {
570
5.52k
    internal::Utf8Encode(index_line, kWideHat);
571
221k
  } else {
572
221k
    internal::Utf8Encode(index_line, kHat);
573
221k
  }
574
227k
  absl::StrAppend(&result, index_line);
575
227k
  return result;
576
233k
}
577
578
2.20M
absl::optional<SourcePosition> Source::FindLinePosition(int32_t line) const {
579
2.20M
  if (ABSL_PREDICT_FALSE(line < 1)) {
580
5.18k
    return std::nullopt;
581
5.18k
  }
582
2.19M
  if (line == 1) {
583
1.62M
    return SourcePosition{0};
584
1.62M
  }
585
573k
  const auto line_offsets = this->line_offsets();
586
573k
  if (ABSL_PREDICT_TRUE(line <= static_cast<int32_t>(line_offsets.size()))) {
587
390k
    return line_offsets[static_cast<size_t>(line - 2)];
588
390k
  }
589
183k
  return std::nullopt;
590
573k
}
591
592
absl::optional<std::pair<int32_t, SourcePosition>> Source::FindLine(
593
232k
    SourcePosition position) const {
594
232k
  if (ABSL_PREDICT_FALSE(position < 0)) {
595
4.25k
    return std::nullopt;
596
4.25k
  }
597
227k
  int32_t line = 1;
598
227k
  const auto line_offsets = this->line_offsets();
599
217M
  for (const auto& line_offset : line_offsets) {
600
217M
    if (line_offset > position) {
601
227k
      break;
602
227k
    }
603
217M
    ++line;
604
217M
  }
605
227k
  if (line == 1) {
606
188k
    return std::make_pair(line, SourcePosition{0});
607
188k
  }
608
39.1k
  return std::make_pair(line, line_offsets[static_cast<size_t>(line) - 2]);
609
227k
}
610
611
SourceSubrange::SourceSubrange(const Source& source, SourceRange range)
612
0
    : source_(source), range_(range) {
613
0
  SourcePosition size = source_.content().size();
614
0
  ABSL_DCHECK(range_.begin >= 0);
615
0
  ABSL_DCHECK(range_.begin <= size);
616
0
  ABSL_DCHECK(range_.end >= range_.begin);
617
0
  ABSL_DCHECK(range_.end <= size);
618
0
  if (range_.begin < 0) {
619
0
    range_.begin = 0;
620
0
  }
621
0
  if (range_.begin > size) {
622
0
    range_.begin = size;
623
0
  }
624
0
  if (range_.end < range_.begin) {
625
0
    range_.end = range_.begin;
626
0
  }
627
0
  if (range_.end > size) {
628
0
    range_.end = size;
629
0
  }
630
0
  for (const auto& line_offset : source_.line_offsets()) {
631
0
    if (line_offset > range_.begin && line_offset <= range_.end) {
632
0
      line_offsets_.push_back(line_offset - range_.begin);
633
0
    }
634
0
  }
635
0
  line_offsets_.push_back(range_.end - range_.begin + 1);
636
0
}
637
638
0
SourceContentView SourceSubrange::content() const {
639
0
  auto parent_content = source_.content();
640
0
  if (parent_content.empty() || range_.begin >= range_.end) {
641
0
    return EmptyContentView();
642
0
  }
643
0
  return absl::visit(
644
0
      [this](auto view) {
645
0
        return SourceContentView(
646
0
            view.subspan(static_cast<size_t>(range_.begin),
647
0
                         static_cast<size_t>(range_.end - range_.begin)));
648
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
649
0
      parent_content.view_);
650
0
}
651
652
0
absl::Span<const SourcePosition> SourceSubrange::line_offsets() const {
653
0
  return absl::MakeConstSpan(line_offsets_);
654
0
}
655
656
35.6k
static size_t ClampLimit(int value) {
657
35.6k
  if (value < 0) {
658
0
    return std::numeric_limits<size_t>::max();
659
0
  }
660
35.6k
  return static_cast<size_t>(value);
661
35.6k
}
662
663
absl::StatusOr<absl_nonnull SourcePtr> NewSource(absl::string_view content,
664
                                                 std::string description,
665
35.6k
                                                 const SourceOptions& options) {
666
35.6k
  return common_internal::NewSourceImpl(std::move(description), content,
667
35.6k
                                        content.size(),
668
35.6k
                                        ClampLimit(options.max_codepoint_size));
669
35.6k
}
670
671
absl::StatusOr<absl_nonnull SourcePtr> NewSource(const absl::Cord& content,
672
                                                 std::string description,
673
0
                                                 const SourceOptions& options) {
674
0
  return common_internal::NewSourceImpl(std::move(description), content,
675
0
                                        content.size(),
676
0
                                        ClampLimit(options.max_codepoint_size));
677
0
}
678
679
}  // namespace cel