Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-source.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
47# ifndef AH_SOURCE_H
48# define AH_SOURCE_H
49
50# include <cstddef>
51# include <fstream>
52# include <sstream>
53# include <string>
54# include <utility>
55
56# include <ah-errors.H>
57# include <tpl_dynArray.H>
58
59namespace Aleph
60{
61 using Source_File_Id = size_t;
62 using Source_Offset = size_t;
63
70 {
72 std::string file_name;
74 size_t line = 1;
75 size_t column = 1;
76
79 {
80 return file_id != 0;
81 }
82
84 std::string to_string() const
85 {
86 std::ostringstream out;
87 if (not file_name.empty())
88 out << file_name << ":";
89 out << line << ":" << column;
90 return out.str();
91 }
92 };
93
100 {
104
107 {
108 return file_id != 0 and begin <= end;
109 }
110
113 {
114 return begin == end;
115 }
116
119 {
120 return end - begin;
121 }
122
124 bool contains(const Source_Offset offset) const noexcept
125 {
126 return begin <= offset and offset < end;
127 }
128
130 std::string to_string() const
131 {
132 std::ostringstream out;
133 if (not is_valid())
134 {
135 out << "<invalid-span>";
136 return out.str();
137 }
138
139 out << "#" << file_id << ":[" << begin << "," << end << ")";
140 return out.str();
141 }
142 };
143
151 {
153 std::string name;
154 std::string text;
156 };
157
164 {
165 std::string file_name;
166 size_t line = 1;
167 size_t column = 1;
168 std::string line_text;
169 size_t highlight_column = 1;
170 size_t highlight_width = 1;
171 };
172
184 {
186
188 compute_line_starts(const std::string & text)
189 {
191 starts.append(0);
192
193 for (size_t i = 0; i < text.size(); ++i)
194 if (text[i] == '\n')
195 starts.append(i + 1);
196
197 return starts;
198 }
199
200 size_t checked_index(const Source_File_Id id) const
201 {
202 ah_out_of_range_error_unless(id > 0 and id <= files.size())
203 << "Source_Manager: invalid file id " << id;
204 return id - 1;
205 }
206
208 {
209 return files.access(checked_index(id));
210 }
211
213 const Source_Offset off) const
214 {
216 << "Source_Manager: offset " << off
217 << " out of range for file '" << file.name << "'";
218
219 size_t lo = 0;
220 size_t hi = file.line_starts.size();
221 while (lo + 1 < hi)
222 {
223 const size_t mid = lo + (hi - lo)/2;
224 if (file.line_starts.access(mid) <= off)
225 lo = mid;
226 else
227 hi = mid;
228 }
229
230 return lo;
231 }
232
233 size_t line_end_offset(const Source_File & file, const size_t line_idx) const
234 {
235 ah_out_of_range_error_unless(line_idx < file.line_starts.size())
236 << "Source_Manager: invalid line index " << line_idx;
237
238 size_t end = line_idx + 1 < file.line_starts.size() ?
239 file.line_starts.access(line_idx + 1) : file.text.size();
240
241 if (end > file.line_starts.access(line_idx)
242 and end <= file.text.size() and file.text[end - 1] == '\n')
243 --end;
244 if (end > file.line_starts.access(line_idx)
245 and end <= file.text.size() and file.text[end - 1] == '\r')
246 --end;
247
248 return end;
249 }
250
251 public:
258 Source_File_Id add_virtual_file(const std::string & name,
259 const std::string & text)
260 {
262 file.id = files.size() + 1;
263 file.name = name;
264 file.text = text;
265 file.line_starts = compute_line_starts(file.text);
266 files.append(std::move(file));
267 return files.size();
268 }
269
276 Source_File_Id load_file(const std::string & path)
277 {
278 std::ifstream input(path, std::ios::binary);
280 << "Source_Manager: cannot open file '" << path << "'";
281
282 std::ostringstream out;
283 out << input.rdbuf();
284 return add_virtual_file(path, out.str());
285 }
286
288 const Source_File & file(const Source_File_Id id) const
289 {
290 return checked_file(id);
291 }
292
294 const std::string & file_name(const Source_File_Id id) const
295 {
296 return checked_file(id).name;
297 }
298
300 const std::string & file_text(const Source_File_Id id) const
301 {
302 return checked_file(id).text;
303 }
304
306 size_t file_size(const Source_File_Id id) const
307 {
308 return checked_file(id).text.size();
309 }
310
313 {
314 return files.size();
315 }
316
326 const Source_Offset begin,
327 const Source_Offset end) const
328 {
329 const auto & src = checked_file(id);
330 ah_out_of_range_error_unless(begin <= end and end <= src.text.size())
331 << "Source_Manager: invalid span [" << begin << ", " << end
332 << ") for file '" << src.name << "'";
333
334 return {id, begin, end};
335 }
336
339 {
340 const auto & src = checked_file(id);
341 const size_t line_idx = line_index_from_offset(src, off);
342 const Source_Offset line_start = src.line_starts.access(line_idx);
343 return {id, src.name, off, line_idx + 1, off - line_start + 1};
344 }
345
348 {
350 << "Source_Manager::begin_position(): invalid span";
351 return position(span.file_id, span.begin);
352 }
353
356 {
358 << "Source_Manager::end_position(): invalid span";
359 return position(span.file_id, span.end);
360 }
361
363 std::string slice(const Source_Span & span) const
364 {
366 << "Source_Manager::slice(): invalid span";
367
368 const auto & src = checked_file(span.file_id);
369 ah_out_of_range_error_unless(span.end <= src.text.size())
370 << "Source_Manager::slice(): span end out of range";
371
372 return src.text.substr(span.begin, span.size());
373 }
374
384 {
386 << "Source_Manager::snippet(): invalid span";
387
388 const auto & src = checked_file(span.file_id);
389 const auto begin_pos = begin_position(span);
390 const size_t line_idx = begin_pos.line - 1;
391 const Source_Offset line_begin = src.line_starts.access(line_idx);
393
395 if (clipped_end > line_end)
397 if (clipped_end < span.begin)
399
400 size_t width = clipped_end - span.begin;
401 if (width == 0)
402 width = 1;
403
404 return {
405 src.name,
406 begin_pos.line,
407 begin_pos.column,
408 src.text.substr(line_begin, line_end - line_begin),
409 begin_pos.column,
410 width
411 };
412 }
413 };
414}
415
416# endif // AH_SOURCE_H
Exception handling system with formatted messages for Aleph-w.
#define ah_runtime_error_unless(C)
Throws std::runtime_error if condition does NOT hold.
Definition ah-errors.H:255
#define ah_out_of_range_error_unless(C)
Throws std::out_of_range if condition does NOT hold.
Definition ah-errors.H:600
#define ah_invalid_argument_unless(C)
Throws std::invalid_argument if condition does NOT hold.
Definition ah-errors.H:660
size_t size_t int32_t * out
Definition ca-c-api.h:120
T & append()
Allocate a new entry to the end of array.
Stores source files and resolves offsets into human-readable data.
Definition ah-source.H:184
const std::string & file_name(const Source_File_Id id) const
Returns the display name of file id.
Definition ah-source.H:294
static DynArray< Source_Offset > compute_line_starts(const std::string &text)
Definition ah-source.H:188
const Source_File & checked_file(const Source_File_Id id) const
Definition ah-source.H:207
std::string slice(const Source_Span &span) const
Returns the exact text covered by span.
Definition ah-source.H:363
size_t line_end_offset(const Source_File &file, const size_t line_idx) const
Definition ah-source.H:233
Source_Snippet snippet(const Source_Span &span) const
Builds a single-line diagnostic snippet from span.
Definition ah-source.H:383
Source_Position begin_position(const Source_Span &span) const
Resolves the begin of span to a concrete source position.
Definition ah-source.H:347
size_t line_index_from_offset(const Source_File &file, const Source_Offset off) const
Definition ah-source.H:212
const std::string & file_text(const Source_File_Id id) const
Returns the full text of file id.
Definition ah-source.H:300
const Source_File & file(const Source_File_Id id) const
Returns the registered file record for id.
Definition ah-source.H:288
DynArray< Source_File > files
Definition ah-source.H:185
Source_Span span(const Source_File_Id id, const Source_Offset begin, const Source_Offset end) const
Creates a validated span in file id.
Definition ah-source.H:325
Source_File_Id load_file(const std::string &path)
Loads a file from disk and registers it.
Definition ah-source.H:276
size_t checked_index(const Source_File_Id id) const
Definition ah-source.H:200
size_t num_files() const noexcept
Returns the number of registered files.
Definition ah-source.H:312
Source_File_Id add_virtual_file(const std::string &name, const std::string &text)
Registers an in-memory source file.
Definition ah-source.H:258
Source_Position end_position(const Source_Span &span) const
Resolves the end of span to a concrete source position.
Definition ah-source.H:355
size_t file_size(const Source_File_Id id) const
Returns the size in bytes of file id.
Definition ah-source.H:306
Source_Position position(const Source_File_Id id, const Source_Offset off) const
Resolves off to file/offset/line/column information.
Definition ah-source.H:338
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
const long double offset[]
Offset values indexed by symbol string length (bounded by MAX_OFFSET_INDEX)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
size_t Source_File_Id
Definition ah-source.H:61
size_t Source_Offset
Definition ah-source.H:62
Registered source file with cached line starts.
Definition ah-source.H:151
DynArray< Source_Offset > line_starts
Byte offsets for each line start.
Definition ah-source.H:155
std::string name
User-facing file name or path.
Definition ah-source.H:153
Source_File_Id id
Stable file identifier.
Definition ah-source.H:152
std::string text
Full file contents.
Definition ah-source.H:154
Fully resolved source position.
Definition ah-source.H:70
std::string file_name
Human-readable file name.
Definition ah-source.H:72
size_t column
1-based column number.
Definition ah-source.H:75
Source_File_Id file_id
Stable file identifier; 0 means invalid.
Definition ah-source.H:71
std::string to_string() const
Formats the position as file:line:column or line:column.
Definition ah-source.H:84
bool is_valid() const noexcept
Returns whether the position refers to a registered file.
Definition ah-source.H:78
size_t line
1-based line number.
Definition ah-source.H:74
Source_Offset offset
Byte offset in the file text.
Definition ah-source.H:73
Render-ready excerpt for a single source line.
Definition ah-source.H:164
std::string file_name
File name owning the snippet.
Definition ah-source.H:165
std::string line_text
Raw line contents without trailing newline.
Definition ah-source.H:168
size_t highlight_column
1-based column where the underline starts.
Definition ah-source.H:169
size_t line
1-based line number.
Definition ah-source.H:166
size_t column
1-based begin column.
Definition ah-source.H:167
size_t highlight_width
Width of the underline, always >= 1.
Definition ah-source.H:170
Half-open byte range inside a source file.
Definition ah-source.H:100
bool empty() const noexcept
Returns whether the span contains no bytes.
Definition ah-source.H:112
Source_Offset begin
Inclusive begin byte offset.
Definition ah-source.H:102
bool contains(const Source_Offset offset) const noexcept
Returns whether offset lies inside the half-open range.
Definition ah-source.H:124
bool is_valid() const noexcept
Returns whether the span belongs to a registered file.
Definition ah-source.H:106
size_t size() const noexcept
Returns the span length in bytes.
Definition ah-source.H:118
Source_Offset end
Exclusive end byte offset.
Definition ah-source.H:103
Source_File_Id file_id
Stable file identifier; 0 means invalid.
Definition ah-source.H:101
std::string to_string() const
Formats the span as #file:[begin,end).
Definition ah-source.H:130
Lazy and scalable dynamic array implementation.
ofstream file
Definition writeRb.C:51