10 #if defined(__unix__) || defined(__APPLE__)
13 # include <sys/mman.h>
21 explicit raii_fd(
int file) noexcept : _file(file) {}
23 raii_fd(
const raii_fd&) =
delete;
24 raii_fd& operator=(
const raii_fd&) =
delete;
32 operator int() const noexcept
59 constexpr std::size_t small_file_size = 4 * 1024;
60 constexpr std::size_t medium_file_size = 32 * 1024;
65 raii_fd fd(::
open(path, O_RDONLY));
67 return get_file_error();
69 auto off = ::lseek(fd, 0, SEEK_END);
70 if (off ==
static_cast<::off_t
>(-1))
72 auto size =
static_cast<std::size_t
>(off);
74 if (
size <= small_file_size)
76 if (::lseek(fd, 0, SEEK_SET) != 0)
79 char buffer[small_file_size];
85 else if (
size <= medium_file_size)
87 if (::lseek(fd, 0, SEEK_SET) != 0)
91 if (::read(fd, builder.data(), builder.size()) !=
static_cast<::ssize_t
>(
size))
94 cb(user_data, builder.data(), builder.size());
98 auto memory = ::mmap(
nullptr,
size, PROT_READ, MAP_PRIVATE, fd, 0);
99 if (memory == MAP_FAILED)
102 cb(user_data,
reinterpret_cast<const char*
>(memory),
size);
104 ::munmap(memory,
size);
110 #else // portable read_file() using C I/O
117 explicit raii_file(std::FILE* file) noexcept : _file(file) {}
119 raii_file(
const raii_file&) =
delete;
120 raii_file& operator=(
const raii_file&) =
delete;
122 ~raii_file() noexcept
128 operator std::FILE*()
const noexcept
159 raii_file file(std::fopen(path,
"rb"));
161 return get_file_error();
164 if (std::fseek(file, 0, SEEK_END) != 0)
167 auto size = std::ftell(file);
171 if (std::fseek(file, 0, SEEK_SET) != 0)
176 if (std::fread(builder.data(),
sizeof(
char), builder.size(), file) != builder.size())
178 LEXY_ASSERT(std::fgetc(file) == EOF,
"we haven't read everything?!");
182 cb(user_data, builder.data(), builder.size());
183 return file_error::_success;
197 const auto buffer_size = builder.
write_size();
202 const auto read = std::fread(builder.
write_data(),
sizeof(
char), buffer_size, stdin);
206 if (read < buffer_size)
208 if (std::ferror(stdin) != 0)
213 LEXY_ASSERT(std::feof(stdin),
"why did fread() not read enough?");
225 return file_error::_success;