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