FE 0.17.1
Fast, Effecient FrontEnds
Loading...
Searching...
No Matches
src.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4
5#include <filesystem>
6#include <iosfwd>
7#include <string>
8#include <string_view>
9#include <utility>
10#include <vector>
11
12#include <ankerl/unordered_dense.h>
13
14#include "fe/loc.h"
15
16namespace fe {
17
18/// Hashes a `std::filesystem::path` - consistent with its `operator==`, which compares lexically.
19struct PathHash {
20 size_t operator()(const std::filesystem::path& path) const noexcept { return std::filesystem::hash_value(path); }
21};
22
23/// Maps a `std::filesystem::path` to @p V.
24/// @warning An insert never moves a value, which fe::SrcMap relies on: a Loc points to the Src it stores in here.
25/// An erase, however, moves the last value into the freed slot.
26template<class V>
27using PathMap = ankerl::unordered_dense::segmented_map<std::filesystem::path, V, PathHash>;
28
29/// The content of one source file together with the offsets its rows start at.
30/// This is what turns a Pos back into the row/column a human wants to read.
31class Src {
32public:
33 Src(std::filesystem::path path, std::string buf);
34
35 /// @name Getters
36 ///@{
37 const std::filesystem::path& path() const { return path_; }
38 std::string_view buf() const { return buf_; }
39 /// The number of rows the file actually has.
40 /// @note A trailing line terminator does *not* open one more, empty row - it ends the last one.
41 uint32_t num_rows() const;
42 Pos begin() const { return Pos(0); }
43 Pos end() const { return Pos((uint32_t)buf_.size()); }
44 bool contains(Pos pos) const { return pos && pos.off <= buf_.size(); }
45 ///@}
46
47 /// @name Resolve a Pos
48 ///@{
49 /// 1-based row and column @p pos sits at, or `{0, 0}` if @p pos does not belong to this file.
50 /// The column counts code points, not bytes, and a leading utf8::Bom occupies none.
51 /// @note Never names a row Src::num_rows does not count - see there.
52 std::pair<uint32_t, uint32_t> rowcol(Pos pos) const;
53
54 uint32_t row(Pos pos) const { return rowcol(pos).first; }
55 uint32_t col(Pos pos) const { return rowcol(pos).second; }
56
57 /// Text of the 1-based @p row without its line terminator - or a leading utf8::Bom;
58 /// empty if @p row is out of range.
59 std::string_view line(uint32_t row) const;
60
61 /// Start of the last code point before @p pos - the character a half-open Loc::end points *past*.
62 Pos prev(Pos pos) const;
63 ///@}
64
65private:
66 /// Scanning for `\n` appends one more offset when buf_ ends with a terminator: a row with
67 /// nothing in it and nothing after it. A terminator *ends* its row rather than opening a new
68 /// one, so that entry is an artifact of the scan and not a row the file has.
69 uint32_t phantom_() const { return rows_.size() > 1 && rows_.back() == buf_.size() ? 1 : 0; }
70
71 std::string_view sub(uint32_t begin, uint32_t end) const {
72 return std::string_view(buf_).substr(begin, end - begin);
73 }
74
75 std::filesystem::path path_;
76 std::string buf_;
77 std::vector<uint32_t> rows_; ///< Offset each row starts at; `rows_.front() == 0`.
78 uint32_t bom_ = 0; ///< Byte size of a leading utf8::Bom, which is not a column.
79};
80
81/// Interns the text - and the `std::filesystem::path` - of every file a Loc may point into.
82/// Keep one in your Driver: a Loc is only as good as the SrcMap that keeps its Src alive.
83/// Each file lives here exactly once, so Loc::src identifies it by pointer - see SrcMap::key.
84class SrcMap {
85public:
86 /// @name Register a File
87 ///@{
88 /// Registers @p path with @p buf as its content and reports whether it is fresh.
89 /// A @p path with the same SrcMap::key as an already registered one yields that entry instead.
90 std::pair<const Src*, bool> add(std::filesystem::path path, std::string buf);
91
92 /// As above, but reads the content from @p path.
93 /// @returns a `nullptr` Src if @p path cannot be opened.
94 std::pair<const Src*, bool> add(std::filesystem::path path);
95
96 /// Reads all of @p is into a `std::string`.
97 static std::string slurp(std::istream& is);
98 ///@}
99
100 /// @name Lookup
101 ///@{
102 /// @returns `nullptr` if @p path has not been registered.
103 /// @note Compares SrcMap::key%s, so a @p path that merely *spells* a registered file
104 /// differently still finds it.
105 const Src* lookup(const std::filesystem::path& path) const;
106
107 /// The key @p path is interned under - absolute, symlink-free, and normalized.
108 /// This is where "do these two paths name the same file?" is decided - once, upon SrcMap::add -
109 /// so that every comparison afterwards is a plain Loc::src pointer comparison.
110 /// @note Resolves symlinks and `.`/`..` as far as @p path exists on disk and normalizes the rest
111 /// lexically. A relative @p path is resolved against the current working directory *now*.
112 static std::filesystem::path key(const std::filesystem::path& path);
113 ///@}
114
115private:
116 PathMap<Src> path2src_; ///< Keyed by SrcMap::key; insert-only, so a Src never moves.
117};
118
119} // namespace fe
Interns the text - and the std::filesystem::path - of every file a Loc may point into.
Definition src.h:84
std::pair< const Src *, bool > add(std::filesystem::path path)
As above, but reads the content from path.
static std::filesystem::path key(const std::filesystem::path &path)
The key path is interned under - absolute, symlink-free, and normalized.
const Src * lookup(const std::filesystem::path &path) const
std::pair< const Src *, bool > add(std::filesystem::path path, std::string buf)
static std::string slurp(std::istream &is)
Reads all of is into a std::string.
The content of one source file together with the offsets its rows start at.
Definition src.h:31
std::string_view buf() const
Definition src.h:38
Pos begin() const
Definition src.h:42
std::string_view line(uint32_t row) const
Text of the 1-based row without its line terminator - or a leading utf8::Bom; empty if row is out of ...
uint32_t num_rows() const
The number of rows the file actually has.
Pos end() const
Definition src.h:43
bool contains(Pos pos) const
Definition src.h:44
uint32_t col(Pos pos) const
Definition src.h:55
Src(std::filesystem::path path, std::string buf)
const std::filesystem::path & path() const
Definition src.h:37
Pos prev(Pos pos) const
Start of the last code point before pos - the character a half-open Loc::end points past.
uint32_t row(Pos pos) const
Definition src.h:54
std::pair< uint32_t, uint32_t > rowcol(Pos pos) const
Definition algo.h:17
ankerl::unordered_dense::segmented_map< std::filesystem::path, V, PathHash > PathMap
Maps a std::filesystem::path to V.
Definition src.h:27
Hashes a std::filesystem::path - consistent with its operator==, which compares lexically.
Definition src.h:19
size_t operator()(const std::filesystem::path &path) const noexcept
Definition src.h:20
Byte offset into a Src; pass around as value.
Definition loc.h:16
uint32_t off
Definition loc.h:31
constexpr Pos() noexcept=default
Creates an invalid Position.