move some more bits into impl files

master
Daniel Kolesa 2017-03-09 19:21:01 +01:00
parent 41f4fd4064
commit afd086b2a0
6 changed files with 248 additions and 198 deletions

View File

@ -13,7 +13,7 @@ ASM_SOURCES="jump_all_gas make_all_gas ontop_all_gas"
# c++ sources
CXX_SOURCE_DIR="src"
CXX_SOURCES="context_stack"
CXX_SOURCES="context_stack io filesystem"
# output lib
OSTD_LIB="libostd"

View File

@ -39,22 +39,11 @@ static constexpr char PATH_SEPARATOR = '\\';
static constexpr char PATH_SEPARATOR = '/';
#endif
#ifdef OSTD_PLATFORM_WIN32
namespace detail {
inline time_t filetime_to_time_t(FILETIME const &ft) {
ULARGE_INTEGER ul;
ul.LowPart = ft.dwLowDateTime;
ul.HighPart = ft.dwHighDateTime;
return static_cast<time_t>((ul.QuadPart / 10000000ULL) - 11644473600ULL);
}
}
#endif
inline void path_normalize(char_range) {
/* TODO */
}
struct file_info {
struct OSTD_EXPORT file_info {
file_info() {}
file_info(file_info const &i):
@ -137,82 +126,7 @@ struct file_info {
}
private:
void init_from_str(string_range path) {
/* TODO: implement a version that will follow symbolic links */
p_path = path;
#ifdef OSTD_PLATFORM_WIN32
WIN32_FILE_ATTRIBUTE_DATA attr;
if (!GetFileAttributesEx(p_path.data(), GetFileExInfoStandard, &attr) ||
attr.dwFileAttributes == INVALID_FILE_ATTRIBUTES)
#else
struct stat st;
if (lstat(p_path.data(), &st) < 0)
#endif
{
p_slash = p_dot = std::string::npos;
p_type = file_type::UNKNOWN;
p_path.clear();
p_atime = p_mtime = p_ctime = 0;
return;
}
string_range r = p_path;
string_range found = find_last(r, PATH_SEPARATOR);
if (found.empty()) {
p_slash = std::string::npos;
} else {
p_slash = r.distance_front(found);
}
found = find(filename(), '.');
if (found.empty()) {
p_dot = std::string::npos;
} else {
p_dot = r.distance_front(found);
}
#ifdef OSTD_PLATFORM_WIN32
if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
p_type = file_type::DIRECTORY;
} else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
p_type = file_type::SYMLINK;
} else if (attr.dwFileAttributes & (
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED |
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL |
FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_TEMPORARY
)) {
p_type = file_type::REGULAR;
} else {
p_type = file_type::UNKNOWN;
}
p_atime = detail::filetime_to_time_t(attr.ftLastAccessTime);
p_mtime = detail::filetime_to_time_t(attr.ftLastWriteTime);
p_ctime = detail::filetime_to_time_t(attr.ftCreationTime);
#else
if (S_ISREG(st.st_mode)) {
p_type = file_type::REGULAR;
} else if (S_ISDIR(st.st_mode)) {
p_type = file_type::DIRECTORY;
} else if (S_ISCHR(st.st_mode)) {
p_type = file_type::CHARACTER;
} else if (S_ISBLK(st.st_mode)) {
p_type = file_type::BLOCK;
} else if (S_ISFIFO(st.st_mode)) {
p_type = file_type::FIFO;
} else if (S_ISLNK(st.st_mode)) {
p_type = file_type::SYMLINK;
} else if (S_ISSOCK(st.st_mode)) {
p_type = file_type::SOCKET;
} else {
p_type = file_type::UNKNOWN;
}
p_atime = st.st_atime;
p_mtime = st.st_mtime;
p_ctime = st.st_ctime;
#endif
}
void init_from_str(string_range path);
size_t p_slash = std::string::npos, p_dot = std::string::npos;
file_type p_type = file_type::UNKNOWN;

View File

@ -6,13 +6,9 @@
#ifndef OSTD_IO_HH
#define OSTD_IO_HH
#include <stdio.h>
#include <cstdio>
#include <cerrno>
#include <vector>
#include <stdexcept>
#include <system_error>
#include "ostd/platform.hh"
#include "ostd/string.hh"
#include "ostd/stream.hh"
@ -24,13 +20,7 @@ enum class stream_mode {
READ = 0, WRITE, APPEND, READ_U, WRITE_U, APPEND_U
};
namespace detail {
static char const *filemodes[] = {
"rb", "wb", "ab", "rb+", "wb+", "ab+"
};
}
struct file_stream: stream {
struct OSTD_EXPORT file_stream: stream {
file_stream(): p_f(), p_owned(false) {}
file_stream(file_stream const &) = delete;
file_stream(file_stream &&s): p_f(s.p_f), p_owned(s.p_owned) {
@ -38,7 +28,9 @@ struct file_stream: stream {
s.p_owned = false;
}
file_stream(string_range path, stream_mode mode = stream_mode::READ): p_f() {
file_stream(string_range path, stream_mode mode = stream_mode::READ):
p_f()
{
open(path, mode);
}
@ -53,103 +45,27 @@ struct file_stream: stream {
return *this;
}
bool open(string_range path, stream_mode mode = stream_mode::READ) {
if (p_f || (path.size() > FILENAME_MAX)) {
return false;
}
char buf[FILENAME_MAX + 1];
memcpy(buf, &path[0], path.size());
buf[path.size()] = '\0';
p_owned = false;
#ifndef OSTD_PLATFORM_WIN32
p_f = fopen(buf, detail::filemodes[size_t(mode)]);
#else
if (fopen_s(&p_f, buf, detail::filemodes[size_t(mode)]) != 0) {
return false;
}
#endif
p_owned = !!p_f;
return is_open();
}
bool open(string_range path, stream_mode mode = stream_mode::READ);
bool open(FILE *f) {
if (p_f) {
return false;
}
p_f = f;
p_owned = false;
return is_open();
}
bool open(FILE *f);
bool is_open() const { return p_f != nullptr; }
bool is_owned() const { return p_owned; }
void close() {
if (p_f && p_owned) {
fclose(p_f);
}
p_f = nullptr;
p_owned = false;
}
void close();
bool end() const;
bool end() const {
return feof(p_f) != 0;
}
void seek(stream_off_t pos, stream_seek whence = stream_seek::SET);
void seek(stream_off_t pos, stream_seek whence = stream_seek::SET) {
#ifndef OSTD_PLATFORM_WIN32
if (fseeko(p_f, pos, int(whence)))
#else
if (_fseeki64(p_f, pos, int(whence)))
#endif
{
throw stream_error{errno, std::generic_category()};
}
}
stream_off_t tell() const;
stream_off_t tell() const {
#ifndef OSTD_PLATFORM_WIN32
auto ret = ftello(p_f);
#else
auto ret = _ftelli64(p_f);
#endif
if (ret < 0) {
throw stream_error{errno, std::generic_category()};
}
return ret;
}
void flush();
void flush() {
if (fflush(p_f)) {
throw stream_error{EIO, std::generic_category()};
}
}
void read_bytes(void *buf, size_t count);
void write_bytes(void const *buf, size_t count);
void read_bytes(void *buf, size_t count) {
if (fread(buf, 1, count, p_f) != count) {
throw stream_error{EIO, std::generic_category()};
}
}
void write_bytes(void const *buf, size_t count) {
if (fwrite(buf, 1, count, p_f) != count) {
throw stream_error{EIO, std::generic_category()};
}
}
int get_char() {
int ret = fgetc(p_f);
if (ret == EOF) {
throw stream_error{EIO, std::generic_category()};
}
return ret;
}
void put_char(int c) {
if (fputc(c, p_f) == EOF) {
throw stream_error{EIO, std::generic_category()};
}
}
int get_char();
void put_char(int c);
void swap(file_stream &s) {
using std::swap;
@ -157,7 +73,7 @@ struct file_stream: stream {
swap(p_owned, s.p_owned);
}
FILE *get_file() { return p_f; }
FILE *get_file() const { return p_f; }
private:
FILE *p_f;
@ -168,9 +84,9 @@ inline void swap(file_stream &a, file_stream &b) {
a.swap(b);
}
static file_stream cin{stdin};
static file_stream cout{stdout};
static file_stream cerr{stderr};
OSTD_EXPORT extern file_stream cin;
OSTD_EXPORT extern file_stream cout;
OSTD_EXPORT extern file_stream cerr;
/* no need to call anything from file_stream, prefer simple calls... */
@ -184,7 +100,7 @@ namespace detail {
stdout_range() {}
void put(char c) {
if (putchar(c) == EOF) {
if (std::putchar(c) == EOF) {
throw stream_error{EIO, std::generic_category()};
}
}
@ -196,7 +112,7 @@ namespace detail {
is_contiguous_range<R> &&
std::is_same_v<std::remove_const_t<range_value_t<R>>, char>
) {
if (fwrite(range.data(), 1, range.size(), stdout) != range.size()) {
if (std::fwrite(range.data(), 1, range.size(), stdout) != range.size()) {
throw stream_error{EIO, std::generic_category()};
}
} else {
@ -216,7 +132,7 @@ inline void write(A const &...args) {
template<typename ...A>
inline void writeln(A const &...args) {
write(args...);
if (putchar('\n') == EOF) {
if (std::putchar('\n') == EOF) {
throw stream_error{EIO, std::generic_category()};
}
}
@ -230,7 +146,7 @@ inline void writef(string_range fmt, A const &...args) {
template<typename ...A>
inline void writefln(string_range fmt, A const &...args) {
writef(fmt, args...);
if (putchar('\n') == EOF) {
if (std::putchar('\n') == EOF) {
throw stream_error{EIO, std::generic_category()};
}
}

View File

@ -6,10 +6,16 @@
#ifndef OSTD_STREAM_HH
#define OSTD_STREAM_HH
#include <sys/types.h>
#include <cstdlib>
#include <type_traits>
#include <locale>
#include <optional>
#include <stdexcept>
#include <system_error>
#ifndef OSTD_PLATFORM_WIN32
#include <sys/types.h>
#endif
#include "ostd/platform.hh"
#include "ostd/types.hh"

97
src/filesystem.cc 100644
View File

@ -0,0 +1,97 @@
/* Filesystem implementation bits.
*
* This file is part of OctaSTD. See COPYING.md for futher information.
*/
#include "ostd/filesystem.hh"
#include "ostd/io.hh"
namespace ostd {
#ifdef OSTD_PLATFORM_WIN32
static inline time_t filetime_to_time_t(FILETIME const &ft) {
ULARGE_INTEGER ul;
ul.LowPart = ft.dwLowDateTime;
ul.HighPart = ft.dwHighDateTime;
return static_cast<time_t>((ul.QuadPart / 10000000ULL) - 11644473600ULL);
}
#endif
void file_info::init_from_str(string_range path) {
/* TODO: implement a version that will follow symbolic links */
p_path = path;
#ifdef OSTD_PLATFORM_WIN32
WIN32_FILE_ATTRIBUTE_DATA attr;
if (!GetFileAttributesEx(p_path.data(), GetFileExInfoStandard, &attr) ||
attr.dwFileAttributes == INVALID_FILE_ATTRIBUTES)
#else
struct stat st;
if (lstat(p_path.data(), &st) < 0)
#endif
{
p_slash = p_dot = std::string::npos;
p_type = file_type::UNKNOWN;
p_path.clear();
p_atime = p_mtime = p_ctime = 0;
return;
}
string_range r = p_path;
string_range found = find_last(r, PATH_SEPARATOR);
if (found.empty()) {
p_slash = std::string::npos;
} else {
p_slash = r.distance_front(found);
}
found = find(filename(), '.');
if (found.empty()) {
p_dot = std::string::npos;
} else {
p_dot = r.distance_front(found);
}
#ifdef OSTD_PLATFORM_WIN32
if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
p_type = file_type::DIRECTORY;
} else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
p_type = file_type::SYMLINK;
} else if (attr.dwFileAttributes & (
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED |
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL |
FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_TEMPORARY
)) {
p_type = file_type::REGULAR;
} else {
p_type = file_type::UNKNOWN;
}
p_atime = detail::filetime_to_time_t(attr.ftLastAccessTime);
p_mtime = detail::filetime_to_time_t(attr.ftLastWriteTime);
p_ctime = detail::filetime_to_time_t(attr.ftCreationTime);
#else
if (S_ISREG(st.st_mode)) {
p_type = file_type::REGULAR;
} else if (S_ISDIR(st.st_mode)) {
p_type = file_type::DIRECTORY;
} else if (S_ISCHR(st.st_mode)) {
p_type = file_type::CHARACTER;
} else if (S_ISBLK(st.st_mode)) {
p_type = file_type::BLOCK;
} else if (S_ISFIFO(st.st_mode)) {
p_type = file_type::FIFO;
} else if (S_ISLNK(st.st_mode)) {
p_type = file_type::SYMLINK;
} else if (S_ISSOCK(st.st_mode)) {
p_type = file_type::SOCKET;
} else {
p_type = file_type::UNKNOWN;
}
p_atime = st.st_atime;
p_mtime = st.st_mtime;
p_ctime = st.st_ctime;
#endif
}
} /* namespace ostd */

117
src/io.cc 100644
View File

@ -0,0 +1,117 @@
/* I/O streams implementation bits.
*
* This file is part of OctaSTD. See COPYING.md for futher information.
*/
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include "ostd/io.hh"
namespace ostd {
static char const *filemodes[] = {
"rb", "wb", "ab", "rb+", "wb+", "ab+"
};
bool file_stream::open(string_range path, stream_mode mode) {
if (p_f || (path.size() > FILENAME_MAX)) {
return false;
}
char buf[FILENAME_MAX + 1];
std::memcpy(buf, &path[0], path.size());
buf[path.size()] = '\0';
p_owned = false;
#ifndef OSTD_PLATFORM_WIN32
p_f = std::fopen(buf, filemodes[size_t(mode)]);
#else
if (fopen_s(&p_f, buf, filemodes[size_t(mode)]) != 0) {
return false;
}
#endif
p_owned = !!p_f;
return is_open();
}
bool file_stream::open(FILE *f) {
if (p_f) {
return false;
}
p_f = f;
p_owned = false;
return is_open();
}
void file_stream::close() {
if (p_f && p_owned) {
std::fclose(p_f);
}
p_f = nullptr;
p_owned = false;
}
bool file_stream::end() const {
return std::feof(p_f) != 0;
}
void file_stream::seek(stream_off_t pos, stream_seek whence) {
#ifndef OSTD_PLATFORM_WIN32
if (fseeko(p_f, pos, int(whence)))
#else
if (_fseeki64(p_f, pos, int(whence)))
#endif
{
throw stream_error{errno, std::generic_category()};
}
}
stream_off_t file_stream::tell() const {
#ifndef OSTD_PLATFORM_WIN32
auto ret = ftello(p_f);
#else
auto ret = _ftelli64(p_f);
#endif
if (ret < 0) {
throw stream_error{errno, std::generic_category()};
}
return ret;
}
void file_stream::flush() {
if (std::fflush(p_f)) {
throw stream_error{EIO, std::generic_category()};
}
}
void file_stream::read_bytes(void *buf, size_t count) {
if (std::fread(buf, 1, count, p_f) != count) {
throw stream_error{EIO, std::generic_category()};
}
}
void file_stream::write_bytes(void const *buf, size_t count) {
if (std::fwrite(buf, 1, count, p_f) != count) {
throw stream_error{EIO, std::generic_category()};
}
}
int file_stream::get_char() {
int ret = std::fgetc(p_f);
if (ret == EOF) {
throw stream_error{EIO, std::generic_category()};
}
return ret;
}
void file_stream::put_char(int c) {
if (std::fputc(c, p_f) == EOF) {
throw stream_error{EIO, std::generic_category()};
}
}
OSTD_EXPORT file_stream cin{stdin};
OSTD_EXPORT file_stream cout{stdout};
OSTD_EXPORT file_stream cerr{stderr};
} /* namespace ostd */