From afd086b2a062c5d69a07b777b6ae43d2e1d2d4bc Mon Sep 17 00:00:00 2001 From: q66 Date: Thu, 9 Mar 2017 19:21:01 +0100 Subject: [PATCH] move some more bits into impl files --- build.sh | 2 +- ostd/filesystem.hh | 90 +------------------------------ ostd/io.hh | 132 +++++++++------------------------------------ ostd/stream.hh | 8 ++- src/filesystem.cc | 97 +++++++++++++++++++++++++++++++++ src/io.cc | 117 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 248 insertions(+), 198 deletions(-) create mode 100644 src/filesystem.cc create mode 100644 src/io.cc diff --git a/build.sh b/build.sh index b4eac9c..f0ae867 100755 --- a/build.sh +++ b/build.sh @@ -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" diff --git a/ostd/filesystem.hh b/ostd/filesystem.hh index 6e6a2c8..8af202e 100644 --- a/ostd/filesystem.hh +++ b/ostd/filesystem.hh @@ -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((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; diff --git a/ostd/io.hh b/ostd/io.hh index 9289c29..9f4d7d3 100644 --- a/ostd/io.hh +++ b/ostd/io.hh @@ -6,13 +6,9 @@ #ifndef OSTD_IO_HH #define OSTD_IO_HH -#include +#include #include -#include -#include -#include - #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 && std::is_same_v>, 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 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 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()}; } } diff --git a/ostd/stream.hh b/ostd/stream.hh index d1e47cf..62a7ea1 100644 --- a/ostd/stream.hh +++ b/ostd/stream.hh @@ -6,10 +6,16 @@ #ifndef OSTD_STREAM_HH #define OSTD_STREAM_HH -#include +#include #include #include #include +#include +#include + +#ifndef OSTD_PLATFORM_WIN32 +#include +#endif #include "ostd/platform.hh" #include "ostd/types.hh" diff --git a/src/filesystem.cc b/src/filesystem.cc new file mode 100644 index 0000000..8210cba --- /dev/null +++ b/src/filesystem.cc @@ -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((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 */ diff --git a/src/io.cc b/src/io.cc new file mode 100644 index 0000000..8917d51 --- /dev/null +++ b/src/io.cc @@ -0,0 +1,117 @@ +/* I/O streams implementation bits. + * + * This file is part of OctaSTD. See COPYING.md for futher information. + */ + +#include +#include +#include + +#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 */