Skip to content

Commit 4fa7674

Browse files
committed
More file managment.
1 parent c326241 commit 4fa7674

File tree

4 files changed

+227
-19
lines changed

4 files changed

+227
-19
lines changed

src/cursor.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
#include "cursor.hpp"
3+
#include "file.hpp"
4+
#include <cassert>
5+
6+
namespace hl {
7+
8+
constexpr void cursor::set_line(std::string file_name, size_t line)
9+
{
10+
auto &file = get_file(file_name);
11+
_source_file_id = file.id();
12+
}
13+
14+
}

src/cursor.hpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
#ifndef HL_CURSOR_HPP
3+
#define HL_CURSOR_HPP
4+
5+
#include "utf8.hpp"
6+
#include <cstddef>
7+
8+
9+
namespace hl {
10+
11+
class cursor {
12+
public:
13+
constexpr cursor() noexcept = default;
14+
constexpr cursor(std::size_t file_id) noexcept : _file_id(file_id), _source_file_id(file_id) {}
15+
16+
constexpr void set_line(size_t line) noexcept
17+
{
18+
_source_line = line;
19+
}
20+
21+
/** Synchronize the cursor with the source file.
22+
*
23+
* This function should be called after advancing beyond the vertical space
24+
* after the #line directive.
25+
*/
26+
constexpr void set_line(std::string file_name, size_t line) noexcept;
27+
28+
constexpr void set_line(std::size_t line) noexcept
29+
{
30+
_line = line;
31+
_source_line = line;
32+
_column = 0;
33+
}
34+
35+
constexpr void advance(char32_t cp) noexcept
36+
{
37+
if (is_vertical_space(cp)) {
38+
++_line;
39+
++_source_line;
40+
_column = 0;
41+
} else {
42+
++_column;
43+
}
44+
}
45+
46+
private:
47+
std::size_t _file_id = 0;
48+
std::size_t _offset = 0;
49+
std::size_t _line = 0;
50+
std::size_t _column = 0;
51+
52+
std::size_t _source_file_id = 0;
53+
std::size_t _source_line = 0;
54+
};
55+
56+
}
57+
58+
#endif

src/file.cpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11

22
#include "file.hpp"
33
#include <vector>
4+
#include <map>
5+
#include <memory>
6+
#include <cassert>
7+
#include <limits>
48

59
namespace hl {
610

7-
static std::vector<file> files;
11+
static std::vector<std::unique_ptr<file>> files_by_id;
12+
static std::map<std::string, file*> files_by_name;
813

914
file::file(std::size_t id, std::filesystem::path const& path) : _id(id), _path(path)
1015
{
@@ -39,4 +44,68 @@ std::filesystem::path const& file::path() const
3944
return make_file(std::filesystem::path("dummy_file_" + std::to_string(file_id)));
4045
}
4146

47+
file_handle::file_handle(std::size_t id)
48+
{
49+
assert(id < files.size());
50+
_id = id;
51+
}
52+
53+
file_handle::file_handle(std::string_view path)
54+
{
55+
assert(not path.empty());
56+
57+
58+
}
59+
file_handle(std::filesystem::path const& path);
60+
61+
[[nodiscard]] file *file_handle::operator->() const
62+
{
63+
assert(_id < files_by_id.size());
64+
return files_by_id[_id].get();
65+
}
66+
67+
[[nodiscard]] file &operator*() const
68+
{
69+
assert(_id < files_by_id.size());
70+
return *files_by_id[_id];
71+
}
72+
73+
[[nodiscard]] std::size_t file::read(std::size_t position, std::span<char> buffer) const
74+
{
75+
assert(position < _file_size);
76+
77+
if (buffer.size() == 0) {
78+
return 0; // No data to read
79+
}
80+
81+
auto const _ = std::scoped_lock(_mutex);
82+
83+
if (not _file_stream.is_open()) {
84+
_file_stream.open(_path, std::ios::binary);
85+
if (not _file_stream) {
86+
throw std::runtime_error("Failed to open file stream: " + _path.string());
87+
}
88+
}
89+
90+
_file_stream.seekg(position);
91+
if (not _file_stream) {
92+
throw std::runtime_error("Failed to seek in file stream: " + _path.string());
93+
}
94+
95+
_file_stream.read(buffer.data(), buffer.size());
96+
if (not _file_stream) {
97+
throw std::runtime_error("Failed to read from file stream: " + _path.string());
98+
}
99+
100+
return _file_stream.gcount();
101+
}
102+
103+
void file::close() noexcept
104+
{
105+
auto const _ = std::scoped_lock(_mutex);
106+
if (_file_stream.is_open()) {
107+
_file_stream.close();
108+
}
109+
}
110+
42111
} // namespace hl

src/file.hpp

Lines changed: 85 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,68 @@
44

55
#include <filesystem>
66
#include <cstddef>
7+
#include <string>
8+
#include <string_view>
9+
#include <limits>
10+
#include <memory>
11+
#include <cassert>
12+
#include <vector>
13+
#include <map>
14+
#include <array>
15+
#include <span>
16+
#include <mutex>
717

818
namespace hl {
919

1020
class file {
1121
public:
22+
class handle {
23+
public:
24+
constexpr handle() noexcept = default;
25+
handle(handle const&) noexcept = default;
26+
handle(handle&&) noexcept = default;
27+
handle& operator=(handle const&) noexcept = default;
28+
handle& operator=(handle&&) noexcept = default;
29+
[[nodiscard]] friend bool operator==(handle const&, handle const&) noexcept = default;
30+
31+
[[nodiscard]] explicit operator bool() const noexcept
32+
{
33+
return _id != std::numeric_limits<std::size_t>::max();
34+
}
35+
36+
[[nodiscard]] std::size_t id() const noexcept
37+
{
38+
return _id;
39+
}
40+
41+
[[nodiscard]] file* operator->() const;
42+
43+
[[nodiscard]] file& operator*() const;
44+
45+
private:
46+
std::size_t _id = std::numeric_limits<std::size_t>::max();
47+
48+
handle(std::size_t id) : _id(id) {}
49+
50+
friend class file;
51+
};
52+
53+
class reader {
54+
public:
55+
56+
[[nodiscard]] char32_t operator[](std::size_t index) const
57+
{
58+
assert(_file != nullptr);
59+
assert(index < _lookahead.size());
60+
return _lookahead[index];
61+
}
62+
63+
private:
64+
file* _file = nullptr;
65+
std::size_t _position = 0;
66+
std::array<char32_t, 8> _lookahead = {};
67+
};
68+
1269
/** Create a file object with the given path.
1370
*
1471
* @param path The absolute normalized path to the file.
@@ -25,43 +82,53 @@ class file {
2582
*/
2683
[[nodiscard]] std::filesystem::path const& path() const;
2784

28-
/** The file's content.
29-
*
30-
* @return The content of the file as a string view.
31-
*/
32-
[[nodiscard]] std::string_view view() const;
85+
[[nodiscard]] std::size_t size() const noexcept
86+
{
87+
return _file_size;
88+
}
3389

34-
/** Get the line and column at the offset of the file.
90+
/** Read the file content into a buffer.
3591
*
36-
* @param offset The offset in the file.
37-
* @return A pair containing the line number (0-based) and column number
38-
* (0-based).
92+
* @param position The position in the file to start reading from.
93+
* @param buffer The buffer to read the content into.
94+
* @return The number of bytes read.
3995
*/
40-
[[nodiscard]] std::pair<size_t, size_t> line_column(std::size_t offset) const;
96+
[[nodiscard]] std::size_t read(std::size_t position, std::span<char> buffer) const;
97+
98+
void close() noexcept;
99+
100+
[[nodiscard]] static handle make_file(std::string_view path);
101+
[[nodiscard]] static handle make_file(std::string_view path, handle relative_to);
41102

42103
private:
104+
inline static std::vector<std::unique_ptr<file>> _files_by_id;
105+
inline static std::map<std::string, file*> _files_by_name;
106+
43107
std::size_t _id = 0;
44108

45-
/** The absolute normalized path to the file.
109+
std::mutex _mutex;
110+
111+
/** The size of the file in bytes.
112+
*
113+
* This is set when the file is read for the first time.
46114
*/
47-
std::filesystem::path _path;
115+
std::size_t _file_size = 0;
48116

49-
/** The offset where each line starts in the file.
50-
*
51-
* The first element is always 0, representing the start of the file.
117+
/** The absolute normalized path to the file.
52118
*/
53-
std::vector<size_t> _line_offsets;
119+
std::filesystem::path _path;
54120

55121
/** Is this file a .hic source file.
56122
*
57123
* This may be false when #line directives are used to track the source of
58124
* generated code.
59125
*/
60126
bool _is_source_code = false;
127+
128+
std::ifstream _file_stream;
61129
};
62130

63-
[[nodiscard]] file& make_file(std::filesystem::path const& path);
64-
[[nodiscard]] file& get_file(std::size_t file_id);
131+
65132

66133
} // namespace hl
67134

0 commit comments

Comments
 (0)