1/**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
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 * http://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
16#include "sourceLocation.h"
17
18#include "lexer/token/letters.h"
19
20#include <cstdint>
21
22namespace ark::es2panda::lexer {
23void OffsetEntry::AddCol(size_t offset)
24{
25    size_t diff = offset - offset_;
26    offset_ = offset;
27
28    if (ranges.empty()) {
29        ranges.emplace_back(Range {diff});
30        return;
31    }
32
33    auto &range = ranges.back();
34
35    if (diff == range.byteSize) {
36        range.cnt++;
37    } else {
38        ranges.emplace_back(Range {diff});
39    }
40}
41
42LineIndex::LineIndex(const util::StringView &source) noexcept
43{
44    auto iter = util::StringView::Iterator(source);
45    entries_.emplace_back(0);
46
47    while (true) {
48        switch (iter.Next()) {
49            case util::StringView::Iterator::INVALID_CP: {
50                return;
51            }
52            case LEX_CHAR_CR: {
53                if (iter.HasNext() && iter.Peek() == LEX_CHAR_LF) {
54                    iter.Forward(1);
55                }
56
57                [[fallthrough]];
58            }
59            case LEX_CHAR_LF:
60            case LEX_CHAR_PS:
61            case LEX_CHAR_LS: {
62                entries_.emplace_back(iter.Index());
63                break;
64            }
65            default: {
66                entries_.back().AddCol(iter.Index());
67            }
68        }
69    }
70}
71
72SourceLocation LineIndex::GetLocation(SourcePosition pos) const noexcept
73{
74    size_t line = pos.line;
75
76    size_t col = 0;
77
78    // It can occur during stdlib parsing where entries does not uploaded
79    if (line > entries_.size()) {
80        return SourceLocation(line + 1, col + 1);
81    }
82
83    if (line == entries_.size()) {
84        --line;
85    }
86
87    const auto &entry = entries_[line];
88    size_t diff = pos.index - entry.lineStart;
89
90    for (const auto &range : entry.ranges) {
91        if (diff < range.cnt) {
92            col += diff;
93            break;
94        }
95
96        diff -= range.cnt * range.byteSize;
97        col += range.cnt;
98    }
99
100    return SourceLocation(line + 1, col + 1);
101}
102}  // namespace ark::es2panda::lexer
103