no bug - Correct some typos in the comments. a=typo-fix
[gecko.git] / third_party / wasm2c / src / lexer-source-line-finder.cc
blob4d407e9d8e1490059b6b7a14307b88e1cd3f7f67
1 /*
2 * Copyright 2017 WebAssembly Community Group participants
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "wabt/lexer-source-line-finder.h"
19 #include <algorithm>
21 #include "wabt/lexer-source.h"
23 namespace wabt {
25 LexerSourceLineFinder::LexerSourceLineFinder(
26 std::unique_ptr<LexerSource> source)
27 : source_(std::move(source)),
28 next_line_start_(0),
29 last_cr_(false),
30 eof_(false) {
31 source_->Seek(0);
32 // Line 0 should not be used; but it makes indexing simpler.
33 line_ranges_.emplace_back(0, 0);
36 Result LexerSourceLineFinder::GetSourceLine(const Location& loc,
37 Offset max_line_length,
38 SourceLine* out_source_line) {
39 ColumnRange column_range(loc.first_column, loc.last_column);
40 OffsetRange original;
41 CHECK_RESULT(GetLineOffsets(loc.line, &original));
43 OffsetRange clamped =
44 ClampSourceLineOffsets(original, column_range, max_line_length);
45 bool has_start_ellipsis = original.start != clamped.start;
46 bool has_end_ellipsis = original.end != clamped.end;
48 out_source_line->column_offset = clamped.start - original.start;
50 if (has_start_ellipsis) {
51 out_source_line->line += "...";
52 clamped.start += 3;
54 if (has_end_ellipsis) {
55 clamped.end -= 3;
58 std::vector<char> read_line;
59 CHECK_RESULT(source_->ReadRange(clamped, &read_line));
60 out_source_line->line.append(read_line.begin(), read_line.end());
62 if (has_end_ellipsis) {
63 out_source_line->line += "...";
66 return Result::Ok;
69 bool LexerSourceLineFinder::IsLineCached(int line) const {
70 return static_cast<size_t>(line) < line_ranges_.size();
73 OffsetRange LexerSourceLineFinder::GetCachedLine(int line) const {
74 assert(IsLineCached(line));
75 return line_ranges_[line];
78 Result LexerSourceLineFinder::GetLineOffsets(int find_line,
79 OffsetRange* out_range) {
80 if (IsLineCached(find_line)) {
81 *out_range = GetCachedLine(find_line);
82 return Result::Ok;
85 const size_t kBufferSize = 1 << 16;
86 std::vector<char> buffer(kBufferSize);
88 assert(!line_ranges_.empty());
89 Offset buffer_file_offset = 0;
90 while (!IsLineCached(find_line) && !eof_) {
91 CHECK_RESULT(source_->Tell(&buffer_file_offset));
92 size_t read_size = source_->Fill(buffer.data(), buffer.size());
93 if (read_size < buffer.size()) {
94 eof_ = true;
97 for (auto iter = buffer.begin(), end = iter + read_size; iter < end;
98 ++iter) {
99 if (*iter == '\n') {
100 // Don't include \n or \r in the line range.
101 Offset line_offset =
102 buffer_file_offset + (iter - buffer.begin()) - last_cr_;
103 line_ranges_.emplace_back(next_line_start_, line_offset);
104 next_line_start_ = line_offset + last_cr_ + 1;
106 last_cr_ = *iter == '\r';
109 if (eof_) {
110 // Add the final line as an empty range.
111 Offset end = buffer_file_offset + read_size;
112 line_ranges_.emplace_back(next_line_start_, end);
116 if (IsLineCached(find_line)) {
117 *out_range = GetCachedLine(find_line);
118 return Result::Ok;
119 } else {
120 assert(eof_);
121 return Result::Error;
125 // static
126 OffsetRange LexerSourceLineFinder::ClampSourceLineOffsets(
127 OffsetRange offset_range,
128 ColumnRange column_range,
129 Offset max_line_length) {
130 Offset line_length = offset_range.size();
131 if (line_length > max_line_length) {
132 size_t column_count = column_range.size();
133 size_t center_on;
134 if (column_count > max_line_length) {
135 // The column range doesn't fit, just center on first_column.
136 center_on = column_range.start - 1;
137 } else {
138 // the entire range fits, display it all in the center.
139 center_on = (column_range.start + column_range.end) / 2 - 1;
141 if (center_on > max_line_length / 2) {
142 offset_range.start += center_on - max_line_length / 2;
144 offset_range.start =
145 std::min(offset_range.start, offset_range.end - max_line_length);
146 offset_range.end = offset_range.start + max_line_length;
149 return offset_range;
152 } // namespace wabt