forked from OctaForge/libostd
update to new style everywhere
parent
68c19a80fb
commit
8e40841219
|
@ -13,7 +13,7 @@ struct Foo {
|
||||||
|
|
||||||
/* implementing formatting for custom objects - external function */
|
/* implementing formatting for custom objects - external function */
|
||||||
template<typename R>
|
template<typename R>
|
||||||
void to_format(Foo const &, R &writer, FormatSpec const &fs) {
|
void to_format(Foo const &, R &writer, format_spec const &fs) {
|
||||||
switch (fs.spec()) {
|
switch (fs.spec()) {
|
||||||
case 'i':
|
case 'i':
|
||||||
writer.put_string("Foo1");
|
writer.put_string("Foo1");
|
||||||
|
@ -27,7 +27,7 @@ void to_format(Foo const &, R &writer, FormatSpec const &fs) {
|
||||||
struct Bar {
|
struct Bar {
|
||||||
/* implementing formatting for custom objects - method */
|
/* implementing formatting for custom objects - method */
|
||||||
template<typename R>
|
template<typename R>
|
||||||
void to_format(R &writer, FormatSpec const &fs) const {
|
void to_format(R &writer, format_spec const &fs) const {
|
||||||
switch (fs.spec()) {
|
switch (fs.spec()) {
|
||||||
case 'i':
|
case 'i':
|
||||||
writer.put_string("Bar1");
|
writer.put_string("Bar1");
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
using namespace ostd;
|
using namespace ostd;
|
||||||
|
|
||||||
void list_dirs(string_range path, int off = 0) {
|
void list_dirs(string_range path, int off = 0) {
|
||||||
DirectoryStream ds{path};
|
directory_stream ds{path};
|
||||||
/* iterate all items in directory */
|
/* iterate all items in directory */
|
||||||
for (auto v: iter(ds)) {
|
for (auto v: iter(ds)) {
|
||||||
if (v.type() != FileType::directory) {
|
if (v.type() != file_type::DIRECTORY) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for_each(range(off), [](int) { write(' '); });
|
for_each(range(off), [](int) { write(' '); });
|
||||||
|
|
|
@ -4,17 +4,17 @@
|
||||||
|
|
||||||
using namespace ostd;
|
using namespace ostd;
|
||||||
|
|
||||||
struct SignalTest {
|
struct signal_test {
|
||||||
/* const on the class means that a const reference to the event
|
/* const on the class means that a const reference to the event
|
||||||
* can actually emit (in that case, the reference passed to each
|
* can actually emit (in that case, the reference passed to each
|
||||||
* callback will always be const to make sure nothing changes)
|
* callback will always be const to make sure nothing changes)
|
||||||
*/
|
*/
|
||||||
Signal<SignalTest const, int, string_range> on_simple = this;
|
signal<signal_test const, int, string_range> on_simple = this;
|
||||||
Signal<SignalTest , float > on_param = this;
|
signal<signal_test , float > on_param = this;
|
||||||
|
|
||||||
SignalTest(): p_param(3.14f) {
|
signal_test(): p_param(3.14f) {
|
||||||
/* we can connect methods */
|
/* we can connect methods */
|
||||||
on_simple.connect(&SignalTest::simple_method);
|
on_simple.connect(&signal_test::simple_method);
|
||||||
writeln("constructed signal test");
|
writeln("constructed signal test");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ private:
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
writeln("=== program start ===");
|
writeln("=== program start ===");
|
||||||
SignalTest st;
|
signal_test st;
|
||||||
|
|
||||||
int test = 42;
|
int test = 42;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ int main() {
|
||||||
* this callback can access "test" easily and it will still work
|
* this callback can access "test" easily and it will still work
|
||||||
*/
|
*/
|
||||||
auto idx = st.on_simple.connect([&](
|
auto idx = st.on_simple.connect([&](
|
||||||
SignalTest const &, int v, string_range str
|
signal_test const &, int v, string_range str
|
||||||
) {
|
) {
|
||||||
writefln("and lambda test: %d, %s (%d)", v, str, test);
|
writefln("and lambda test: %d, %s (%d)", v, str, test);
|
||||||
});
|
});
|
||||||
|
@ -67,8 +67,8 @@ int main() {
|
||||||
writeln("--- set value ---");
|
writeln("--- set value ---");
|
||||||
st.set_param(6.28f);
|
st.set_param(6.28f);
|
||||||
|
|
||||||
/* the reference to SignalTest here is mutable */
|
/* the reference to signal_test here is mutable */
|
||||||
st.on_param.connect([](SignalTest &self, float oldval) {
|
st.on_param.connect([](signal_test &self, float oldval) {
|
||||||
writeln("value changed...");
|
writeln("value changed...");
|
||||||
writefln(
|
writefln(
|
||||||
" old value: %f, new value: %f", oldval, self.get_param()
|
" old value: %f, new value: %f", oldval, self.get_param()
|
||||||
|
|
|
@ -8,17 +8,17 @@ void print_result(uint32_t x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
FileStream wtest{"test.bin", StreamMode::write};
|
file_stream wtest{"test.bin", stream_mode::WRITE};
|
||||||
copy(
|
copy(
|
||||||
iter({ 0xABCD1214, 0xBADC3264, 0xDEADBEEF, 0xBEEFDEAD }),
|
iter({ 0xABCD1214, 0xBADC3264, 0xDEADBEEF, 0xBEEFDEAD }),
|
||||||
wtest.iter<uint32_t>()
|
wtest.iter<uint32_t>()
|
||||||
);
|
);
|
||||||
wtest.close();
|
wtest.close();
|
||||||
|
|
||||||
FileStream rtest{"test.bin"};
|
file_stream rtest{"test.bin"};
|
||||||
writefln("stream size: %d", rtest.size());
|
writefln("stream size: %d", rtest.size());
|
||||||
|
|
||||||
for (uint32_t x: map(rtest.iter<uint32_t>(), FromBigEndian<uint32_t>())) {
|
for (uint32_t x: map(rtest.iter<uint32_t>(), from_big_endian<uint32_t>())) {
|
||||||
print_result(x);
|
print_result(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ using namespace ostd;
|
||||||
int main() {
|
int main() {
|
||||||
writeln("writing sample file...");
|
writeln("writing sample file...");
|
||||||
|
|
||||||
FileStream wtest{"test.txt", StreamMode::write};
|
file_stream wtest{"test.txt", stream_mode::WRITE};
|
||||||
|
|
||||||
std::string smpl =
|
std::string smpl =
|
||||||
"This is a test file for later read.\n"
|
"This is a test file for later read.\n"
|
||||||
|
@ -20,7 +20,7 @@ int main() {
|
||||||
copy(iter(smpl), wtest.iter());
|
copy(iter(smpl), wtest.iter());
|
||||||
wtest.close();
|
wtest.close();
|
||||||
|
|
||||||
FileStream test{"test.txt"};
|
file_stream test{"test.txt"};
|
||||||
|
|
||||||
writeln("## WHOLE FILE READ ##\n");
|
writeln("## WHOLE FILE READ ##\n");
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "ostd/range.hh"
|
#include "ostd/range.hh"
|
||||||
#include "ostd/utility.hh"
|
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Signals/slots for OctaSTD.
|
/* signals/slots for OctaSTD.
|
||||||
*
|
*
|
||||||
* This file is part of OctaSTD. See COPYING.md for futher information.
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
||||||
*/
|
*/
|
||||||
|
@ -7,17 +7,16 @@
|
||||||
#define OSTD_EVENT_HH
|
#define OSTD_EVENT_HH
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
#include "ostd/utility.hh"
|
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename C, typename ...A>
|
template<typename C, typename ...A>
|
||||||
struct SignalBase {
|
struct signal_base {
|
||||||
SignalBase(C *cl): p_class(cl), p_funcs(nullptr), p_nfuncs(0) {}
|
signal_base(C *cl): p_class(cl), p_funcs(nullptr), p_nfuncs(0) {}
|
||||||
|
|
||||||
SignalBase(SignalBase const &ev):
|
signal_base(signal_base const &ev):
|
||||||
p_class(ev.p_class), p_nfuncs(ev.p_nfuncs)
|
p_class(ev.p_class), p_nfuncs(ev.p_nfuncs)
|
||||||
{
|
{
|
||||||
using func_t = std::function<void(C &, A...)>;
|
using func_t = std::function<void(C &, A...)>;
|
||||||
|
@ -28,13 +27,13 @@ namespace detail {
|
||||||
p_funcs = nbuf;
|
p_funcs = nbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalBase(SignalBase &&ev):
|
signal_base(signal_base &&ev):
|
||||||
p_class(nullptr), p_funcs(nullptr), p_nfuncs(0)
|
p_class(nullptr), p_funcs(nullptr), p_nfuncs(0)
|
||||||
{
|
{
|
||||||
swap(ev);
|
swap(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalBase &operator=(SignalBase const &ev) {
|
signal_base &operator=(signal_base const &ev) {
|
||||||
using func_t = std::function<void(C &, A...)>;
|
using func_t = std::function<void(C &, A...)>;
|
||||||
p_class = ev.p_class;
|
p_class = ev.p_class;
|
||||||
p_nfuncs = ev.p_nfuncs;
|
p_nfuncs = ev.p_nfuncs;
|
||||||
|
@ -47,12 +46,12 @@ namespace detail {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalBase &operator=(SignalBase &&ev) {
|
signal_base &operator=(signal_base &&ev) {
|
||||||
swap(ev);
|
swap(ev);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~SignalBase() { clear(); }
|
~signal_base() { clear(); }
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
for (size_t i = 0; i < p_nfuncs; ++i) {
|
for (size_t i = 0; i < p_nfuncs; ++i) {
|
||||||
|
@ -115,7 +114,7 @@ namespace detail {
|
||||||
return ocl;
|
return ocl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(SignalBase &ev) {
|
void swap(signal_base &ev) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(p_class, ev.p_class);
|
swap(p_class, ev.p_class);
|
||||||
swap(p_funcs, ev.p_funcs);
|
swap(p_funcs, ev.p_funcs);
|
||||||
|
@ -130,21 +129,21 @@ namespace detail {
|
||||||
} /* namespace detail */
|
} /* namespace detail */
|
||||||
|
|
||||||
template<typename C, typename ...A>
|
template<typename C, typename ...A>
|
||||||
struct Signal {
|
struct signal {
|
||||||
private:
|
private:
|
||||||
using Base = detail::SignalBase<C, A...>;
|
using base_t = detail::signal_base<C, A...>;
|
||||||
Base p_base;
|
base_t p_base;
|
||||||
public:
|
public:
|
||||||
Signal(C *cl): p_base(cl) {}
|
signal(C *cl): p_base(cl) {}
|
||||||
Signal(Signal const &ev): p_base(ev.p_base) {}
|
signal(signal const &ev): p_base(ev.p_base) {}
|
||||||
Signal(Signal &&ev): p_base(std::move(ev.p_base)) {}
|
signal(signal &&ev): p_base(std::move(ev.p_base)) {}
|
||||||
|
|
||||||
Signal &operator=(Signal const &ev) {
|
signal &operator=(signal const &ev) {
|
||||||
p_base = ev.p_base;
|
p_base = ev.p_base;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Signal &operator=(Signal &&ev) {
|
signal &operator=(signal &&ev) {
|
||||||
p_base = std::move(ev.p_base);
|
p_base = std::move(ev.p_base);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -165,25 +164,25 @@ public:
|
||||||
C *get_class() const { return p_base.get_class(); }
|
C *get_class() const { return p_base.get_class(); }
|
||||||
C *set_class(C *cl) { return p_base.set_class(cl); }
|
C *set_class(C *cl) { return p_base.set_class(cl); }
|
||||||
|
|
||||||
void swap(Signal &ev) { p_base.swap(ev.p_base); }
|
void swap(signal &ev) { p_base.swap(ev.p_base); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename C, typename ...A>
|
template<typename C, typename ...A>
|
||||||
struct Signal<C const, A...> {
|
struct signal<C const, A...> {
|
||||||
private:
|
private:
|
||||||
using Base = detail::SignalBase<C const, A...>;
|
using base_t = detail::signal_base<C const, A...>;
|
||||||
Base p_base;
|
base_t p_base;
|
||||||
public:
|
public:
|
||||||
Signal(C *cl): p_base(cl) {}
|
signal(C *cl): p_base(cl) {}
|
||||||
Signal(Signal const &ev): p_base(ev.p_base) {}
|
signal(signal const &ev): p_base(ev.p_base) {}
|
||||||
Signal(Signal &&ev): p_base(std::move(ev.p_base)) {}
|
signal(signal &&ev): p_base(std::move(ev.p_base)) {}
|
||||||
|
|
||||||
Signal &operator=(Signal const &ev) {
|
signal &operator=(signal const &ev) {
|
||||||
p_base = ev.p_base;
|
p_base = ev.p_base;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Signal &operator=(Signal &&ev) {
|
signal &operator=(signal &&ev) {
|
||||||
p_base = std::move(ev.p_base);
|
p_base = std::move(ev.p_base);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -204,11 +203,11 @@ public:
|
||||||
C *get_class() const { return p_base.get_class(); }
|
C *get_class() const { return p_base.get_class(); }
|
||||||
C *set_class(C *cl) { return p_base.set_class(cl); }
|
C *set_class(C *cl) { return p_base.set_class(cl); }
|
||||||
|
|
||||||
void swap(Signal &ev) { p_base.swap(ev.p_base); }
|
void swap(signal &ev) { p_base.swap(ev.p_base); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename C, typename ...A>
|
template<typename C, typename ...A>
|
||||||
inline void swap(Signal<C, A...> &a, Signal<C, A...> &b) {
|
inline void swap(signal<C, A...> &a, signal<C, A...> &b) {
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,11 @@
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
enum class FileType {
|
enum class file_type {
|
||||||
unknown, regular, fifo, character, directory, block, symlink, socket
|
UNKNOWN, REGULAR, FIFO, CHARACTER, DIRECTORY, BLOCK, SYMLINK, SOCKET
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FileInfo;
|
struct file_info;
|
||||||
|
|
||||||
#ifdef OSTD_PLATFORM_WIN32
|
#ifdef OSTD_PLATFORM_WIN32
|
||||||
static constexpr char PathSeparator = '\\';
|
static constexpr char PathSeparator = '\\';
|
||||||
|
@ -54,30 +54,30 @@ inline void path_normalize(char_range) {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileInfo {
|
struct file_info {
|
||||||
FileInfo() {}
|
file_info() {}
|
||||||
|
|
||||||
FileInfo(FileInfo const &i):
|
file_info(file_info const &i):
|
||||||
p_slash(i.p_slash), p_dot(i.p_dot), p_type(i.p_type),
|
p_slash(i.p_slash), p_dot(i.p_dot), p_type(i.p_type),
|
||||||
p_path(i.p_path), p_atime(i.p_atime), p_mtime(i.p_mtime),
|
p_path(i.p_path), p_atime(i.p_atime), p_mtime(i.p_mtime),
|
||||||
p_ctime(i.p_ctime)
|
p_ctime(i.p_ctime)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
FileInfo(FileInfo &&i):
|
file_info(file_info &&i):
|
||||||
p_slash(i.p_slash), p_dot(i.p_dot), p_type(i.p_type),
|
p_slash(i.p_slash), p_dot(i.p_dot), p_type(i.p_type),
|
||||||
p_path(std::move(i.p_path)), p_atime(i.p_atime), p_mtime(i.p_mtime),
|
p_path(std::move(i.p_path)), p_atime(i.p_atime), p_mtime(i.p_mtime),
|
||||||
p_ctime(i.p_ctime)
|
p_ctime(i.p_ctime)
|
||||||
{
|
{
|
||||||
i.p_slash = i.p_dot = std::string::npos;
|
i.p_slash = i.p_dot = std::string::npos;
|
||||||
i.p_type = FileType::unknown;
|
i.p_type = file_type::UNKNOWN;
|
||||||
i.p_atime = i.p_ctime = i.p_mtime = 0;
|
i.p_atime = i.p_ctime = i.p_mtime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInfo(string_range path) {
|
file_info(string_range path) {
|
||||||
init_from_str(path);
|
init_from_str(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInfo &operator=(FileInfo const &i) {
|
file_info &operator=(file_info const &i) {
|
||||||
p_slash = i.p_slash;
|
p_slash = i.p_slash;
|
||||||
p_dot = i.p_dot;
|
p_dot = i.p_dot;
|
||||||
p_type = i.p_type;
|
p_type = i.p_type;
|
||||||
|
@ -88,7 +88,7 @@ struct FileInfo {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInfo &operator=(FileInfo &&i) {
|
file_info &operator=(file_info &&i) {
|
||||||
swap(i);
|
swap(i);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ struct FileInfo {
|
||||||
: path().slice(p_dot, p_path.size());
|
: path().slice(p_dot, p_path.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
FileType type() const { return p_type; }
|
file_type type() const { return p_type; }
|
||||||
|
|
||||||
void normalize() {
|
void normalize() {
|
||||||
path_normalize(ostd::iter(p_path));
|
path_normalize(ostd::iter(p_path));
|
||||||
|
@ -125,7 +125,7 @@ struct FileInfo {
|
||||||
time_t mtime() const { return p_mtime; }
|
time_t mtime() const { return p_mtime; }
|
||||||
time_t ctime() const { return p_ctime; }
|
time_t ctime() const { return p_ctime; }
|
||||||
|
|
||||||
void swap(FileInfo &i) {
|
void swap(file_info &i) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(i.p_slash, p_slash);
|
swap(i.p_slash, p_slash);
|
||||||
swap(i.p_dot, p_dot);
|
swap(i.p_dot, p_dot);
|
||||||
|
@ -150,7 +150,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
p_slash = p_dot = std::string::npos;
|
p_slash = p_dot = std::string::npos;
|
||||||
p_type = FileType::unknown;
|
p_type = file_type::UNKNOWN;
|
||||||
p_path.clear();
|
p_path.clear();
|
||||||
p_atime = p_mtime = p_ctime = 0;
|
p_atime = p_mtime = p_ctime = 0;
|
||||||
return;
|
return;
|
||||||
|
@ -173,17 +173,17 @@ private:
|
||||||
|
|
||||||
#ifdef OSTD_PLATFORM_WIN32
|
#ifdef OSTD_PLATFORM_WIN32
|
||||||
if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
p_type = FileType::directory;
|
p_type = file_type::DIRECTORY;
|
||||||
} else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
} else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||||
p_type = FileType::symlink;
|
p_type = file_type::SYMLINK;
|
||||||
} else if (attr.dwFileAttributes & (
|
} else if (attr.dwFileAttributes & (
|
||||||
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED |
|
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED |
|
||||||
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL |
|
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL |
|
||||||
FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_TEMPORARY
|
FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_TEMPORARY
|
||||||
)) {
|
)) {
|
||||||
p_type = FileType::regular;
|
p_type = file_type::REGULAR;
|
||||||
} else {
|
} else {
|
||||||
p_type = FileType::unknown;
|
p_type = file_type::UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_atime = detail::filetime_to_time_t(attr.ftLastAccessTime);
|
p_atime = detail::filetime_to_time_t(attr.ftLastAccessTime);
|
||||||
|
@ -191,21 +191,21 @@ private:
|
||||||
p_ctime = detail::filetime_to_time_t(attr.ftCreationTime);
|
p_ctime = detail::filetime_to_time_t(attr.ftCreationTime);
|
||||||
#else
|
#else
|
||||||
if (S_ISREG(st.st_mode)) {
|
if (S_ISREG(st.st_mode)) {
|
||||||
p_type = FileType::regular;
|
p_type = file_type::REGULAR;
|
||||||
} else if (S_ISDIR(st.st_mode)) {
|
} else if (S_ISDIR(st.st_mode)) {
|
||||||
p_type = FileType::directory;
|
p_type = file_type::DIRECTORY;
|
||||||
} else if (S_ISCHR(st.st_mode)) {
|
} else if (S_ISCHR(st.st_mode)) {
|
||||||
p_type = FileType::character;
|
p_type = file_type::CHARACTER;
|
||||||
} else if (S_ISBLK(st.st_mode)) {
|
} else if (S_ISBLK(st.st_mode)) {
|
||||||
p_type = FileType::block;
|
p_type = file_type::BLOCK;
|
||||||
} else if (S_ISFIFO(st.st_mode)) {
|
} else if (S_ISFIFO(st.st_mode)) {
|
||||||
p_type = FileType::fifo;
|
p_type = file_type::FIFO;
|
||||||
} else if (S_ISLNK(st.st_mode)) {
|
} else if (S_ISLNK(st.st_mode)) {
|
||||||
p_type = FileType::symlink;
|
p_type = file_type::SYMLINK;
|
||||||
} else if (S_ISSOCK(st.st_mode)) {
|
} else if (S_ISSOCK(st.st_mode)) {
|
||||||
p_type = FileType::socket;
|
p_type = file_type::SOCKET;
|
||||||
} else {
|
} else {
|
||||||
p_type = FileType::unknown;
|
p_type = file_type::UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_atime = st.st_atime;
|
p_atime = st.st_atime;
|
||||||
|
@ -215,39 +215,39 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t p_slash = std::string::npos, p_dot = std::string::npos;
|
size_t p_slash = std::string::npos, p_dot = std::string::npos;
|
||||||
FileType p_type = FileType::unknown;
|
file_type p_type = file_type::UNKNOWN;
|
||||||
std::string p_path;
|
std::string p_path;
|
||||||
|
|
||||||
time_t p_atime = 0, p_mtime = 0, p_ctime = 0;
|
time_t p_atime = 0, p_mtime = 0, p_ctime = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void swap(FileInfo &a, FileInfo &b) {
|
inline void swap(file_info &a, file_info &b) {
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct directory_range;
|
struct directory_range;
|
||||||
|
|
||||||
#ifndef OSTD_PLATFORM_WIN32
|
#ifndef OSTD_PLATFORM_WIN32
|
||||||
struct DirectoryStream {
|
struct directory_stream {
|
||||||
friend struct directory_range;
|
friend struct directory_range;
|
||||||
|
|
||||||
DirectoryStream(): p_d(), p_de(), p_path() {}
|
directory_stream(): p_d(), p_de(), p_path() {}
|
||||||
DirectoryStream(DirectoryStream const &) = delete;
|
directory_stream(directory_stream const &) = delete;
|
||||||
DirectoryStream(DirectoryStream &&s):
|
directory_stream(directory_stream &&s):
|
||||||
p_d(s.p_d), p_de(s.p_de), p_path(std::move(s.p_path))
|
p_d(s.p_d), p_de(s.p_de), p_path(std::move(s.p_path))
|
||||||
{
|
{
|
||||||
s.p_d = nullptr;
|
s.p_d = nullptr;
|
||||||
s.p_de = nullptr;
|
s.p_de = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectoryStream(string_range path): DirectoryStream() {
|
directory_stream(string_range path): directory_stream() {
|
||||||
open(path);
|
open(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
~DirectoryStream() { close(); }
|
~directory_stream() { close(); }
|
||||||
|
|
||||||
DirectoryStream &operator=(DirectoryStream const &) = delete;
|
directory_stream &operator=(directory_stream const &) = delete;
|
||||||
DirectoryStream &operator=(DirectoryStream &&s) {
|
directory_stream &operator=(directory_stream &&s) {
|
||||||
close();
|
close();
|
||||||
swap(s);
|
swap(s);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -310,14 +310,14 @@ struct DirectoryStream {
|
||||||
return !p_de;
|
return !p_de;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInfo read() {
|
file_info read() {
|
||||||
if (!pop_front()) {
|
if (!pop_front()) {
|
||||||
return FileInfo();
|
return file_info();
|
||||||
}
|
}
|
||||||
return front();
|
return front();
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(DirectoryStream &s) {
|
void swap(directory_stream &s) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(p_d, s.p_d);
|
swap(p_d, s.p_d);
|
||||||
swap(p_de, s.p_de);
|
swap(p_de, s.p_de);
|
||||||
|
@ -348,14 +348,14 @@ private:
|
||||||
return pop_front(p_d, &p_de);
|
return pop_front(p_d, &p_de);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInfo front() const {
|
file_info front() const {
|
||||||
if (!p_de) {
|
if (!p_de) {
|
||||||
return FileInfo();
|
return file_info();
|
||||||
}
|
}
|
||||||
std::string ap = p_path;
|
std::string ap = p_path;
|
||||||
ap += PathSeparator;
|
ap += PathSeparator;
|
||||||
ap += static_cast<char const *>(p_de->d_name);
|
ap += static_cast<char const *>(p_de->d_name);
|
||||||
return FileInfo(ap);
|
return file_info(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
DIR *p_d;
|
DIR *p_d;
|
||||||
|
@ -365,26 +365,26 @@ private:
|
||||||
|
|
||||||
#else /* OSTD_PLATFORM_WIN32 */
|
#else /* OSTD_PLATFORM_WIN32 */
|
||||||
|
|
||||||
struct DirectoryStream {
|
struct directory_stream {
|
||||||
friend struct directory_range;
|
friend struct directory_range;
|
||||||
|
|
||||||
DirectoryStream(): p_handle(INVALID_HANDLE_VALUE), p_data(), p_path() {}
|
directory_stream(): p_handle(INVALID_HANDLE_VALUE), p_data(), p_path() {}
|
||||||
DirectoryStream(DirectoryStream const &) = delete;
|
directory_stream(directory_stream const &) = delete;
|
||||||
DirectoryStream(DirectoryStream &&s):
|
directory_stream(directory_stream &&s):
|
||||||
p_handle(s.p_handle), p_data(s.p_data), p_path(std::move(s.p_path))
|
p_handle(s.p_handle), p_data(s.p_data), p_path(std::move(s.p_path))
|
||||||
{
|
{
|
||||||
s.p_handle = INVALID_HANDLE_VALUE;
|
s.p_handle = INVALID_HANDLE_VALUE;
|
||||||
memset(&s.p_data, 0, sizeof(s.p_data));
|
memset(&s.p_data, 0, sizeof(s.p_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectoryStream(string_range path): DirectoryStream() {
|
directory_stream(string_range path): directory_stream() {
|
||||||
open(path);
|
open(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
~DirectoryStream() { close(); }
|
~directory_stream() { close(); }
|
||||||
|
|
||||||
DirectoryStream &operator=(DirectoryStream const &) = delete;
|
directory_stream &operator=(directory_stream const &) = delete;
|
||||||
DirectoryStream &operator=(DirectoryStream &&s) {
|
directory_stream &operator=(directory_stream &&s) {
|
||||||
close();
|
close();
|
||||||
swap(s);
|
swap(s);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -481,14 +481,14 @@ struct DirectoryStream {
|
||||||
return p_data.cFileName[0] == '\0';
|
return p_data.cFileName[0] == '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInfo read() {
|
file_info read() {
|
||||||
if (!pop_front()) {
|
if (!pop_front()) {
|
||||||
return FileInfo();
|
return file_info();
|
||||||
}
|
}
|
||||||
return front();
|
return front();
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(DirectoryStream &s) {
|
void swap(directory_stream &s) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(p_handle, s.p_handle);
|
swap(p_handle, s.p_handle);
|
||||||
swap(p_data, s.p_data);
|
swap(p_data, s.p_data);
|
||||||
|
@ -509,14 +509,14 @@ private:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInfo front() const {
|
file_info front() const {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
return FileInfo();
|
return file_info();
|
||||||
}
|
}
|
||||||
std::string ap = p_path;
|
std::string ap = p_path;
|
||||||
ap += PathSeparator;
|
ap += PathSeparator;
|
||||||
ap += static_cast<char const *>(p_data.cFileName);
|
ap += static_cast<char const *>(p_data.cFileName);
|
||||||
return FileInfo(ap);
|
return file_info(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE p_handle;
|
HANDLE p_handle;
|
||||||
|
@ -525,19 +525,19 @@ private:
|
||||||
};
|
};
|
||||||
#endif /* OSTD_PLATFORM_WIN32 */
|
#endif /* OSTD_PLATFORM_WIN32 */
|
||||||
|
|
||||||
inline void swap(DirectoryStream &a, DirectoryStream &b) {
|
inline void swap(directory_stream &a, directory_stream &b) {
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct directory_range: input_range<directory_range> {
|
struct directory_range: input_range<directory_range> {
|
||||||
using range_category = input_range_tag;
|
using range_category = input_range_tag;
|
||||||
using value_type = FileInfo;
|
using value_type = file_info;
|
||||||
using reference = FileInfo;
|
using reference = file_info;
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
using difference_type = long;
|
using difference_type = long;
|
||||||
|
|
||||||
directory_range() = delete;
|
directory_range() = delete;
|
||||||
directory_range(DirectoryStream &s): p_stream(&s) {}
|
directory_range(directory_stream &s): p_stream(&s) {}
|
||||||
directory_range(directory_range const &r): p_stream(r.p_stream) {}
|
directory_range(directory_range const &r): p_stream(r.p_stream) {}
|
||||||
|
|
||||||
directory_range &operator=(directory_range const &r) {
|
directory_range &operator=(directory_range const &r) {
|
||||||
|
@ -553,7 +553,7 @@ struct directory_range: input_range<directory_range> {
|
||||||
return p_stream->pop_front();
|
return p_stream->pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInfo front() const {
|
file_info front() const {
|
||||||
return p_stream->front();
|
return p_stream->front();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,26 +562,26 @@ struct directory_range: input_range<directory_range> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DirectoryStream *p_stream;
|
directory_stream *p_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline directory_range DirectoryStream::iter() {
|
inline directory_range directory_stream::iter() {
|
||||||
return directory_range(*this);
|
return directory_range(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<size_t I>
|
template<size_t I>
|
||||||
struct PathJoin {
|
struct path_join {
|
||||||
template<typename T, typename ...A>
|
template<typename T, typename ...A>
|
||||||
static void join(std::string &s, T const &a, A const &...b) {
|
static void join(std::string &s, T const &a, A const &...b) {
|
||||||
s += a;
|
s += a;
|
||||||
s += PathSeparator;
|
s += PathSeparator;
|
||||||
PathJoin<I - 1>::join(s, b...);
|
path_join<I - 1>::join(s, b...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct PathJoin<1> {
|
struct path_join<1> {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void join(std::string &s, T const &a) {
|
static void join(std::string &s, T const &a) {
|
||||||
s += a;
|
s += a;
|
||||||
|
@ -590,11 +590,11 @@ namespace detail {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ...A>
|
template<typename ...A>
|
||||||
inline FileInfo path_join(A const &...args) {
|
inline file_info path_join(A const &...args) {
|
||||||
std::string path;
|
std::string path;
|
||||||
detail::PathJoin<sizeof...(A)>::join(path, args...);
|
detail::path_join<sizeof...(A)>::join(path, args...);
|
||||||
path_normalize(ostd::iter(path));
|
path_normalize(ostd::iter(path));
|
||||||
return FileInfo(path);
|
return file_info(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool directory_change(string_range path) {
|
inline bool directory_change(string_range path) {
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
#include "ostd/algorithm.hh"
|
#include "ostd/algorithm.hh"
|
||||||
#include "ostd/string.hh"
|
#include "ostd/string.hh"
|
||||||
#include "ostd/utility.hh"
|
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
|
@ -132,13 +131,13 @@ namespace detail {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FormatSpec {
|
struct format_spec {
|
||||||
FormatSpec(): p_nested_escape(false), p_fmt() {}
|
format_spec(): p_nested_escape(false), p_fmt() {}
|
||||||
FormatSpec(string_range fmt, bool escape = false):
|
format_spec(string_range fmt, bool escape = false):
|
||||||
p_nested_escape(escape), p_fmt(fmt)
|
p_nested_escape(escape), p_fmt(fmt)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
FormatSpec(char spec, int width = -1, int prec = -1, int flags = 0):
|
format_spec(char spec, int width = -1, int prec = -1, int flags = 0):
|
||||||
p_flags(flags),
|
p_flags(flags),
|
||||||
p_width((width >= 0) ? width : 0),
|
p_width((width >= 0) ? width : 0),
|
||||||
p_precision((prec >= 0) ? prec : 0),
|
p_precision((prec >= 0) ? prec : 0),
|
||||||
|
@ -437,17 +436,17 @@ protected:
|
||||||
template<
|
template<
|
||||||
typename T, typename R, typename = std::enable_if_t<
|
typename T, typename R, typename = std::enable_if_t<
|
||||||
std::is_same_v<decltype(std::declval<T const &>().to_format(
|
std::is_same_v<decltype(std::declval<T const &>().to_format(
|
||||||
std::declval<R &>(), std::declval<FormatSpec const &>()
|
std::declval<R &>(), std::declval<format_spec const &>()
|
||||||
)), void>
|
)), void>
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
inline void to_format(T const &v, R &writer, FormatSpec const &fs) {
|
inline void to_format(T const &v, R &writer, format_spec const &fs) {
|
||||||
v.to_format(writer, fs);
|
v.to_format(writer, fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename R, typename T>
|
template<typename R, typename T>
|
||||||
inline size_t write_u(R &writer, FormatSpec const *fl, bool neg, T val) {
|
inline size_t write_u(R &writer, format_spec const *fl, bool neg, T val) {
|
||||||
char buf[20];
|
char buf[20];
|
||||||
size_t r = 0, n = 0;
|
size_t r = 0, n = 0;
|
||||||
|
|
||||||
|
@ -564,9 +563,9 @@ namespace detail {
|
||||||
|
|
||||||
template<typename R, typename T>
|
template<typename R, typename T>
|
||||||
inline size_t write_range(
|
inline size_t write_range(
|
||||||
R &writer, FormatSpec const *fl, bool escape, bool expandval,
|
R &writer, format_spec const *fl, bool escape, bool expandval,
|
||||||
string_range sep, T const &val,
|
string_range sep, T const &val,
|
||||||
std::enable_if_t<detail::IterableTest<T>, bool> = true
|
std::enable_if_t<detail::iterable_test<T>, bool> = true
|
||||||
) {
|
) {
|
||||||
/* XXX: maybe handle error cases? */
|
/* XXX: maybe handle error cases? */
|
||||||
auto range = ostd::iter(val);
|
auto range = ostd::iter(val);
|
||||||
|
@ -591,21 +590,21 @@ namespace detail {
|
||||||
|
|
||||||
template<typename R, typename T>
|
template<typename R, typename T>
|
||||||
inline size_t write_range(
|
inline size_t write_range(
|
||||||
R &, FormatSpec const *, bool, bool, string_range,
|
R &, format_spec const *, bool, bool, string_range,
|
||||||
T const &, std::enable_if_t<!detail::IterableTest<T>, bool> = true
|
T const &, std::enable_if_t<!detail::iterable_test<T>, bool> = true
|
||||||
) {
|
) {
|
||||||
throw format_error{"invalid value for ranged format"};
|
throw format_error{"invalid value for ranged format"};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::true_type test_fmt_tostr(
|
static std::true_type test_fmt_tostr(
|
||||||
decltype(ostd::to_string(std::declval<T>())) *
|
decltype(ostd::to_string<T>{}(std::declval<T>())) *
|
||||||
);
|
);
|
||||||
template<typename>
|
template<typename>
|
||||||
static std::false_type test_fmt_tostr(...);
|
static std::false_type test_fmt_tostr(...);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool FmtTostrTest = decltype(test_fmt_tostr<T>(0))::value;
|
constexpr bool fmt_tostr_test = decltype(test_fmt_tostr<T>(0))::value;
|
||||||
|
|
||||||
/* non-printable escapes up to 0x20 (space) */
|
/* non-printable escapes up to 0x20 (space) */
|
||||||
static constexpr char const *fmt_escapes[] = {
|
static constexpr char const *fmt_escapes[] = {
|
||||||
|
@ -648,17 +647,17 @@ namespace detail {
|
||||||
template<typename T, typename R>
|
template<typename T, typename R>
|
||||||
static std::true_type test_tofmt(decltype(to_format(
|
static std::true_type test_tofmt(decltype(to_format(
|
||||||
std::declval<T const &>(), std::declval<R &>(),
|
std::declval<T const &>(), std::declval<R &>(),
|
||||||
std::declval<FormatSpec const &>()
|
std::declval<format_spec const &>()
|
||||||
)) *);
|
)) *);
|
||||||
|
|
||||||
template<typename, typename>
|
template<typename, typename>
|
||||||
static std::false_type test_tofmt(...);
|
static std::false_type test_tofmt(...);
|
||||||
|
|
||||||
template<typename T, typename R>
|
template<typename T, typename R>
|
||||||
constexpr bool FmtTofmtTest = decltype(test_tofmt<T, R>(0))::value;
|
constexpr bool fmt_tofmt_test = decltype(test_tofmt<T, R>(0))::value;
|
||||||
|
|
||||||
struct WriteSpec: FormatSpec {
|
struct write_spec: format_spec {
|
||||||
using FormatSpec::FormatSpec;
|
using format_spec::format_spec;
|
||||||
|
|
||||||
/* string base writer */
|
/* string base writer */
|
||||||
template<typename R>
|
template<typename R>
|
||||||
|
@ -757,7 +756,7 @@ namespace detail {
|
||||||
template<typename R, typename T>
|
template<typename R, typename T>
|
||||||
size_t write_val(R &writer, bool escape, T const &val) const {
|
size_t write_val(R &writer, bool escape, T const &val) const {
|
||||||
/* stuff fhat can be custom-formatted goes first */
|
/* stuff fhat can be custom-formatted goes first */
|
||||||
if constexpr(FmtTofmtTest<T, tostr_range<R>>) {
|
if constexpr(fmt_tofmt_test<T, tostr_range<R>>) {
|
||||||
tostr_range<R> sink(writer);
|
tostr_range<R> sink(writer);
|
||||||
to_format(val, sink, *this);
|
to_format(val, sink, *this);
|
||||||
return sink.get_written();
|
return sink.get_written();
|
||||||
|
@ -788,7 +787,7 @@ namespace detail {
|
||||||
* char pointers are handled by the string case above
|
* char pointers are handled by the string case above
|
||||||
*/
|
*/
|
||||||
if constexpr(std::is_pointer_v<T>) {
|
if constexpr(std::is_pointer_v<T>) {
|
||||||
FormatSpec sp{
|
format_spec sp{
|
||||||
(spec() == 's') ? 'x' : spec(),
|
(spec() == 's') ? 'x' : spec(),
|
||||||
has_width() ? width() : -1,
|
has_width() ? width() : -1,
|
||||||
has_precision() ? precision() : -1,
|
has_precision() ? precision() : -1,
|
||||||
|
@ -815,11 +814,11 @@ namespace detail {
|
||||||
return write_float(writer, escape, val);
|
return write_float(writer, escape, val);
|
||||||
}
|
}
|
||||||
/* stuff that can be to_string'd, worst reliable case, allocates */
|
/* stuff that can be to_string'd, worst reliable case, allocates */
|
||||||
if constexpr(FmtTostrTest<T>) {
|
if constexpr(fmt_tostr_test<T>) {
|
||||||
if (this->spec() != 's') {
|
if (this->spec() != 's') {
|
||||||
throw format_error{"custom objects need the '%s' spec"};
|
throw format_error{"custom objects need the '%s' spec"};
|
||||||
}
|
}
|
||||||
return write_val(writer, false, ostd::to_string(val));
|
return write_val(writer, false, ostd::to_string<T>{}(val));
|
||||||
}
|
}
|
||||||
/* we ran out of options, failure */
|
/* we ran out of options, failure */
|
||||||
throw format_error{"the value cannot be formatted"};
|
throw format_error{"the value cannot be formatted"};
|
||||||
|
@ -866,7 +865,7 @@ namespace detail {
|
||||||
R &writer, bool escape, string_range fmt, A const &...args
|
R &writer, bool escape, string_range fmt, A const &...args
|
||||||
) {
|
) {
|
||||||
size_t argidx = 1, twr = 0, written = 0;
|
size_t argidx = 1, twr = 0, written = 0;
|
||||||
detail::WriteSpec spec(fmt, escape);
|
detail::write_spec spec(fmt, escape);
|
||||||
while (spec.read_until_spec(writer, &twr)) {
|
while (spec.read_until_spec(writer, &twr)) {
|
||||||
written += twr;
|
written += twr;
|
||||||
size_t argpos = spec.index();
|
size_t argpos = spec.index();
|
||||||
|
@ -875,7 +874,7 @@ namespace detail {
|
||||||
argpos = argidx++;
|
argpos = argidx++;
|
||||||
}
|
}
|
||||||
/* FIXME: figure out a better way */
|
/* FIXME: figure out a better way */
|
||||||
detail::WriteSpec nspec(spec.nested(), spec.nested_escape());
|
detail::write_spec nspec(spec.nested(), spec.nested_escape());
|
||||||
written += nspec.write_range(
|
written += nspec.write_range(
|
||||||
writer, argpos - 1, (spec.flags() & FMT_FLAG_HASH),
|
writer, argpos - 1, (spec.flags() & FMT_FLAG_HASH),
|
||||||
spec.nested_sep(), args...
|
spec.nested_sep(), args...
|
||||||
|
@ -916,7 +915,7 @@ namespace detail {
|
||||||
template<typename R>
|
template<typename R>
|
||||||
inline ptrdiff_t format_impl(R &writer, bool, string_range fmt) {
|
inline ptrdiff_t format_impl(R &writer, bool, string_range fmt) {
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
detail::WriteSpec spec(fmt, false);
|
detail::write_spec spec(fmt, false);
|
||||||
if (spec.read_until_spec(writer, &written)) {
|
if (spec.read_until_spec(writer, &written)) {
|
||||||
throw format_error{"format spec without format arguments"};
|
throw format_error{"format spec without format arguments"};
|
||||||
}
|
}
|
||||||
|
@ -930,9 +929,9 @@ inline size_t format(R &&writer, string_range fmt, A const &...args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename R, typename T>
|
template<typename R, typename T>
|
||||||
inline size_t format(R &&writer, FormatSpec const &fmt, T const &val) {
|
inline size_t format(R &&writer, format_spec const &fmt, T const &val) {
|
||||||
/* we can do this as there are no members added... but ugly, FIXME later */
|
/* we can do this as there are no members added... but ugly, FIXME later */
|
||||||
detail::WriteSpec const &wsp = static_cast<detail::WriteSpec const &>(fmt);
|
detail::write_spec const &wsp = static_cast<detail::write_spec const &>(fmt);
|
||||||
return wsp.write_arg(writer, 0, val);
|
return wsp.write_arg(writer, 0, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
50
ostd/io.hh
50
ostd/io.hh
|
@ -17,8 +17,8 @@
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
enum class StreamMode {
|
enum class stream_mode {
|
||||||
read = 0, write, append, read_u, write_u, append_u
|
READ = 0, WRITE, APPEND, READ_U, WRITE_U, APPEND_U
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -27,30 +27,30 @@ namespace detail {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileStream: Stream {
|
struct file_stream: stream {
|
||||||
FileStream(): p_f(), p_owned(false) {}
|
file_stream(): p_f(), p_owned(false) {}
|
||||||
FileStream(FileStream const &) = delete;
|
file_stream(file_stream const &) = delete;
|
||||||
FileStream(FileStream &&s): p_f(s.p_f), p_owned(s.p_owned) {
|
file_stream(file_stream &&s): p_f(s.p_f), p_owned(s.p_owned) {
|
||||||
s.p_f = nullptr;
|
s.p_f = nullptr;
|
||||||
s.p_owned = false;
|
s.p_owned = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileStream(string_range path, StreamMode mode = StreamMode::read): p_f() {
|
file_stream(string_range path, stream_mode mode = stream_mode::READ): p_f() {
|
||||||
open(path, mode);
|
open(path, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileStream(FILE *f): p_f(f), p_owned(false) {}
|
file_stream(FILE *f): p_f(f), p_owned(false) {}
|
||||||
|
|
||||||
~FileStream() { close(); }
|
~file_stream() { close(); }
|
||||||
|
|
||||||
FileStream &operator=(FileStream const &) = delete;
|
file_stream &operator=(file_stream const &) = delete;
|
||||||
FileStream &operator=(FileStream &&s) {
|
file_stream &operator=(file_stream &&s) {
|
||||||
close();
|
close();
|
||||||
swap(s);
|
swap(s);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool open(string_range path, StreamMode mode = StreamMode::read) {
|
bool open(string_range path, stream_mode mode = stream_mode::READ) {
|
||||||
if (p_f || (path.size() > FILENAME_MAX)) {
|
if (p_f || (path.size() > FILENAME_MAX)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ struct FileStream: Stream {
|
||||||
return feof(p_f) != 0;
|
return feof(p_f) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool seek(StreamOffset pos, StreamSeek whence = StreamSeek::set) {
|
bool seek(stream_off_t pos, stream_seek whence = stream_seek::SET) {
|
||||||
#ifndef OSTD_PLATFORM_WIN32
|
#ifndef OSTD_PLATFORM_WIN32
|
||||||
return fseeko(p_f, pos, int(whence)) >= 0;
|
return fseeko(p_f, pos, int(whence)) >= 0;
|
||||||
#else
|
#else
|
||||||
|
@ -101,7 +101,7 @@ struct FileStream: Stream {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamOffset tell() const {
|
stream_off_t tell() const {
|
||||||
#ifndef OSTD_PLATFORM_WIN32
|
#ifndef OSTD_PLATFORM_WIN32
|
||||||
return ftello(p_f);
|
return ftello(p_f);
|
||||||
#else
|
#else
|
||||||
|
@ -127,7 +127,7 @@ struct FileStream: Stream {
|
||||||
return fputc(c, p_f) != EOF;
|
return fputc(c, p_f) != EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(FileStream &s) {
|
void swap(file_stream &s) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(p_f, s.p_f);
|
swap(p_f, s.p_f);
|
||||||
swap(p_owned, s.p_owned);
|
swap(p_owned, s.p_owned);
|
||||||
|
@ -140,38 +140,38 @@ private:
|
||||||
bool p_owned;
|
bool p_owned;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void swap(FileStream &a, FileStream &b) {
|
inline void swap(file_stream &a, file_stream &b) {
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FileStream in(stdin);
|
static file_stream in(stdin);
|
||||||
static FileStream out(stdout);
|
static file_stream out(stdout);
|
||||||
static FileStream err(stderr);
|
static file_stream err(stderr);
|
||||||
|
|
||||||
/* no need to call anything from FileStream, prefer simple calls... */
|
/* no need to call anything from file_stream, prefer simple calls... */
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
/* lightweight output range for direct stdout */
|
/* lightweight output range for direct stdout */
|
||||||
struct StdoutRange: output_range<StdoutRange> {
|
struct stdout_range: output_range<stdout_range> {
|
||||||
using value_type = char;
|
using value_type = char;
|
||||||
using reference = char &;
|
using reference = char &;
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
using difference_type = ptrdiff_t;
|
using difference_type = ptrdiff_t;
|
||||||
|
|
||||||
StdoutRange() {}
|
stdout_range() {}
|
||||||
bool put(char c) {
|
bool put(char c) {
|
||||||
return putchar(c) != EOF;
|
return putchar(c) != EOF;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline size_t range_put_n(StdoutRange &, char const *p, size_t n) {
|
inline size_t range_put_n(stdout_range &, char const *p, size_t n) {
|
||||||
return fwrite(p, 1, n, stdout);
|
return fwrite(p, 1, n, stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void write(T const &v) {
|
inline void write(T const &v) {
|
||||||
format(detail::StdoutRange{}, FormatSpec{'s'}, v);
|
format(detail::stdout_range{}, format_spec{'s'}, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename ...A>
|
template<typename T, typename ...A>
|
||||||
|
@ -200,7 +200,7 @@ inline void writeln(T const &v, A const &...args) {
|
||||||
|
|
||||||
template<typename ...A>
|
template<typename ...A>
|
||||||
inline void writef(string_range fmt, A const &...args) {
|
inline void writef(string_range fmt, A const &...args) {
|
||||||
format(detail::StdoutRange{}, fmt, args...);
|
format(detail::stdout_range{}, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ...A>
|
template<typename ...A>
|
||||||
|
|
|
@ -149,12 +149,10 @@ inline std::uint64_t endian_swap64(std::uint64_t x) noexcept {
|
||||||
/* endian swap */
|
/* endian swap */
|
||||||
|
|
||||||
template<typename T, size_t N = sizeof(T), bool IsNum = std::is_arithmetic_v<T>>
|
template<typename T, size_t N = sizeof(T), bool IsNum = std::is_arithmetic_v<T>>
|
||||||
struct EndianSwap;
|
struct endian_swap;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct EndianSwap<T, 2, true> {
|
struct endian_swap<T, 2, true> {
|
||||||
using Argument = T;
|
|
||||||
using Result = T;
|
|
||||||
T operator()(T v) const {
|
T operator()(T v) const {
|
||||||
union { T iv; std::uint16_t sv; } u;
|
union { T iv; std::uint16_t sv; } u;
|
||||||
u.iv = v;
|
u.iv = v;
|
||||||
|
@ -164,9 +162,7 @@ struct EndianSwap<T, 2, true> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct EndianSwap<T, 4, true> {
|
struct endian_swap<T, 4, true> {
|
||||||
using Argument = T;
|
|
||||||
using Result = T;
|
|
||||||
T operator()(T v) const {
|
T operator()(T v) const {
|
||||||
union { T iv; std::uint32_t sv; } u;
|
union { T iv; std::uint32_t sv; } u;
|
||||||
u.iv = v;
|
u.iv = v;
|
||||||
|
@ -176,9 +172,7 @@ struct EndianSwap<T, 4, true> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct EndianSwap<T, 8, true> {
|
struct endian_swap<T, 8, true> {
|
||||||
using Argument = T;
|
|
||||||
using Result = T;
|
|
||||||
T operator()(T v) const {
|
T operator()(T v) const {
|
||||||
union { T iv; std::uint64_t sv; } u;
|
union { T iv; std::uint64_t sv; } u;
|
||||||
u.iv = v;
|
u.iv = v;
|
||||||
|
@ -187,52 +181,38 @@ struct EndianSwap<T, 8, true> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T endian_swap(T x) { return EndianSwap<T>()(x); }
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
template<
|
||||||
typename T, size_t N = sizeof(T), bool IsNum = std::is_arithmetic_v<T>
|
typename T, size_t N = sizeof(T), bool IsNum = std::is_arithmetic_v<T>
|
||||||
>
|
>
|
||||||
struct EndianSame;
|
struct endian_same;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct EndianSame<T, 2, true> {
|
struct endian_same<T, 2, true> {
|
||||||
using Argument = T;
|
|
||||||
using Result = T;
|
|
||||||
T operator()(T v) const { return v; }
|
T operator()(T v) const { return v; }
|
||||||
};
|
};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct EndianSame<T, 4, true> {
|
struct endian_same<T, 4, true> {
|
||||||
using Argument = T;
|
|
||||||
using Result = T;
|
|
||||||
T operator()(T v) const { return v; }
|
T operator()(T v) const { return v; }
|
||||||
};
|
};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct EndianSame<T, 8, true> {
|
struct endian_same<T, 8, true> {
|
||||||
using Argument = T;
|
|
||||||
using Result = T;
|
|
||||||
T operator()(T v) const { return v; }
|
T operator()(T v) const { return v; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OSTD_BYTE_ORDER == OSTD_ENDIAN_LIL
|
#if OSTD_BYTE_ORDER == OSTD_ENDIAN_LIL
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct FromLilEndian: detail::EndianSame<T> {};
|
struct from_lil_endian: detail::endian_same<T> {};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct FromBigEndian: EndianSwap<T> {};
|
struct from_big_endian: endian_swap<T> {};
|
||||||
#else
|
#else
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct FromLilEndian: EndianSwap<T> {};
|
struct from_lil_endian: endian_swap<T> {};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct FromBigEndian: detail::EndianSame<T> {};
|
struct from_big_endian: detail::endian_same<T> {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T from_lil_endian(T x) { return FromLilEndian<T>()(x); }
|
|
||||||
template<typename T>
|
|
||||||
T from_big_endian(T x) { return FromBigEndian<T>()(x); }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
|
||||||
#include "ostd/types.hh"
|
#include "ostd/types.hh"
|
||||||
#include "ostd/utility.hh"
|
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
|
@ -27,7 +26,7 @@ struct forward_range_tag: input_range_tag {};
|
||||||
struct bidirectional_range_tag: forward_range_tag {};
|
struct bidirectional_range_tag: forward_range_tag {};
|
||||||
struct random_access_range_tag: bidirectional_range_tag {};
|
struct random_access_range_tag: bidirectional_range_tag {};
|
||||||
struct finite_random_access_range_tag: random_access_range_tag {};
|
struct finite_random_access_range_tag: random_access_range_tag {};
|
||||||
struct ContiguousRangeTag: finite_random_access_range_tag {};
|
struct contiguous_range_tag: finite_random_access_range_tag {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct range_half;
|
struct range_half;
|
||||||
|
@ -172,7 +171,7 @@ template<typename T> constexpr bool is_infinite_random_access_range =
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool is_contiguous_range_core =
|
constexpr bool is_contiguous_range_core =
|
||||||
std::is_convertible_v<range_category_t<T>, ContiguousRangeTag>;
|
std::is_convertible_v<range_category_t<T>, contiguous_range_tag>;
|
||||||
|
|
||||||
template<typename T, bool = detail::is_range_test<T>>
|
template<typename T, bool = detail::is_range_test<T>>
|
||||||
constexpr bool is_contiguous_range_base = false;
|
constexpr bool is_contiguous_range_base = false;
|
||||||
|
@ -284,20 +283,20 @@ template<typename T>
|
||||||
struct half_range;
|
struct half_range;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename R, bool = is_bidirectional_range<typename R::Range>>
|
template<typename R, bool = is_bidirectional_range<typename R::range>>
|
||||||
struct RangeAdd;
|
struct range_add;
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
struct RangeAdd<R, true> {
|
struct range_add<R, true> {
|
||||||
using Diff = range_difference_t<typename R::Range>;
|
using diff_t = range_difference_t<typename R::range>;
|
||||||
|
|
||||||
static Diff add_n(R &half, Diff n) {
|
static diff_t add_n(R &half, diff_t n) {
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
return -half.prev_n(n);
|
return -half.prev_n(n);
|
||||||
}
|
}
|
||||||
return half.next_n(n);
|
return half.next_n(n);
|
||||||
}
|
}
|
||||||
static Diff sub_n(R &half, Diff n) {
|
static diff_t sub_n(R &half, diff_t n) {
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
return -half.next_n(n);
|
return -half.next_n(n);
|
||||||
}
|
}
|
||||||
|
@ -306,16 +305,16 @@ namespace detail {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
struct RangeAdd<R, false> {
|
struct range_add<R, false> {
|
||||||
using Diff = range_difference_t<typename R::Range>;
|
using diff_t = range_difference_t<typename R::range>;
|
||||||
|
|
||||||
static Diff add_n(R &half, Diff n) {
|
static diff_t add_n(R &half, diff_t n) {
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return half.next_n(n);
|
return half.next_n(n);
|
||||||
}
|
}
|
||||||
static Diff sub_n(R &half, Diff n) {
|
static diff_t sub_n(R &half, diff_t n) {
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -326,29 +325,29 @@ namespace detail {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename>
|
template<typename>
|
||||||
struct range_iteratorTag {
|
struct range_iterator_tag {
|
||||||
/* better range types all become random access iterators */
|
/* better range types all become random access iterators */
|
||||||
using Type = std::random_access_iterator_tag;
|
using type = std::random_access_iterator_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct range_iteratorTag<input_range_tag> {
|
struct range_iterator_tag<input_range_tag> {
|
||||||
using Type = std::input_iterator_tag;
|
using type = std::input_iterator_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct range_iteratorTag<output_range_tag> {
|
struct range_iterator_tag<output_range_tag> {
|
||||||
using Type = std::output_iterator_tag;
|
using type = std::output_iterator_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct range_iteratorTag<forward_range_tag> {
|
struct range_iterator_tag<forward_range_tag> {
|
||||||
using Type = std::forward_iterator_tag;
|
using type = std::forward_iterator_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct range_iteratorTag<bidirectional_range_tag> {
|
struct range_iterator_tag<bidirectional_range_tag> {
|
||||||
using Type = std::bidirectional_iterator_tag;
|
using type = std::bidirectional_iterator_tag;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,9 +356,9 @@ struct range_half {
|
||||||
private:
|
private:
|
||||||
T p_range;
|
T p_range;
|
||||||
public:
|
public:
|
||||||
using Range = T;
|
using range = T;
|
||||||
|
|
||||||
using iterator_category = typename detail::range_iteratorTag<T>::Type;
|
using iterator_category = typename detail::range_iterator_tag<T>::type;
|
||||||
using value_type = range_value_t<T>;
|
using value_type = range_value_t<T>;
|
||||||
using difference_type = range_difference_t<T>;
|
using difference_type = range_difference_t<T>;
|
||||||
using pointer = range_value_t<T> *;
|
using pointer = range_value_t<T> *;
|
||||||
|
@ -395,10 +394,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
range_difference_t<T> add_n(range_difference_t<T> n) {
|
range_difference_t<T> add_n(range_difference_t<T> n) {
|
||||||
return detail::RangeAdd<range_half<T>>::add_n(*this, n);
|
return detail::range_add<range_half<T>>::add_n(*this, n);
|
||||||
}
|
}
|
||||||
range_difference_t<T> sub_n(range_difference_t<T> n) {
|
range_difference_t<T> sub_n(range_difference_t<T> n) {
|
||||||
return detail::RangeAdd<range_half<T>>::sub_n(*this, n);
|
return detail::range_add<range_half<T>>::sub_n(*this, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
range_reference_t<T> get() const {
|
range_reference_t<T> get() const {
|
||||||
|
@ -859,11 +858,11 @@ inline auto citer(T const &r) -> decltype(ranged_traits<T const>::iter(r)) {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct half_range: input_range<half_range<T>> {
|
struct half_range: input_range<half_range<T>> {
|
||||||
using range_category = range_category_t <typename T::Range>;
|
using range_category = range_category_t <typename T::range>;
|
||||||
using value_type = range_value_t <typename T::Range>;
|
using value_type = range_value_t <typename T::range>;
|
||||||
using reference = range_reference_t <typename T::Range>;
|
using reference = range_reference_t <typename T::range>;
|
||||||
using size_type = range_size_t <typename T::Range>;
|
using size_type = range_size_t <typename T::range>;
|
||||||
using difference_type = range_difference_t<typename T::Range>;
|
using difference_type = range_difference_t<typename T::range>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T p_beg;
|
T p_beg;
|
||||||
|
@ -1553,38 +1552,38 @@ namespace detail {
|
||||||
template<typename>
|
template<typename>
|
||||||
struct iterator_range_tag_base {
|
struct iterator_range_tag_base {
|
||||||
/* fallback, the most basic range */
|
/* fallback, the most basic range */
|
||||||
using Type = input_range_tag;
|
using type = input_range_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct iterator_range_tag_base<std::output_iterator_tag> {
|
struct iterator_range_tag_base<std::output_iterator_tag> {
|
||||||
using Type = output_range_tag;
|
using type = output_range_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct iterator_range_tag_base<std::forward_iterator_tag> {
|
struct iterator_range_tag_base<std::forward_iterator_tag> {
|
||||||
using Type = forward_range_tag;
|
using type = forward_range_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct iterator_range_tag_base<std::bidirectional_iterator_tag> {
|
struct iterator_range_tag_base<std::bidirectional_iterator_tag> {
|
||||||
using Type = bidirectional_range_tag;
|
using type = bidirectional_range_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct iterator_range_tag_base<std::random_access_iterator_tag> {
|
struct iterator_range_tag_base<std::random_access_iterator_tag> {
|
||||||
using Type = finite_random_access_range_tag;
|
using type = finite_random_access_range_tag;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using iterator_range_tag = typename detail::iterator_range_tag_base<T>::Type;
|
using iterator_range_tag = typename detail::iterator_range_tag_base<T>::type;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct iterator_range: input_range<iterator_range<T>> {
|
struct iterator_range: input_range<iterator_range<T>> {
|
||||||
using range_category = std::conditional_t<
|
using range_category = std::conditional_t<
|
||||||
std::is_pointer_v<T>,
|
std::is_pointer_v<T>,
|
||||||
ContiguousRangeTag,
|
contiguous_range_tag,
|
||||||
iterator_range_tag<typename std::iterator_traits<T>::iterator_category>
|
iterator_range_tag<typename std::iterator_traits<T>::iterator_category>
|
||||||
>;
|
>;
|
||||||
using value_type = typename std::iterator_traits<T>::value_type;
|
using value_type = typename std::iterator_traits<T>::value_type;
|
||||||
|
@ -1715,7 +1714,7 @@ struct iterator_range: input_range<iterator_range<T>> {
|
||||||
return range.p_end - p_end;
|
return range.p_end - p_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* satisfy FiniteRandomAccessRange */
|
/* satisfy finite_random_access_range */
|
||||||
size_type size() const { return size_type(p_end - p_beg); }
|
size_type size() const { return size_type(p_end - p_beg); }
|
||||||
|
|
||||||
iterator_range slice(size_type start, size_type end) const {
|
iterator_range slice(size_type start, size_type end) const {
|
||||||
|
|
|
@ -13,49 +13,48 @@
|
||||||
#include "ostd/types.hh"
|
#include "ostd/types.hh"
|
||||||
#include "ostd/range.hh"
|
#include "ostd/range.hh"
|
||||||
#include "ostd/string.hh"
|
#include "ostd/string.hh"
|
||||||
#include "ostd/utility.hh"
|
|
||||||
#include "ostd/format.hh"
|
#include "ostd/format.hh"
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
#ifndef OSTD_PLATFORM_WIN32
|
#ifndef OSTD_PLATFORM_WIN32
|
||||||
using StreamOffset = off_t;
|
using stream_off_t = off_t;
|
||||||
#else
|
#else
|
||||||
using StreamOffset = __int64;
|
using stream_off_t = __int64;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum class StreamSeek {
|
enum class stream_seek {
|
||||||
cur = SEEK_CUR,
|
CUR = SEEK_CUR,
|
||||||
end = SEEK_END,
|
END = SEEK_END,
|
||||||
set = SEEK_SET
|
SET = SEEK_SET
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T = char, bool = std::is_pod_v<T>>
|
template<typename T = char, bool = std::is_pod_v<T>>
|
||||||
struct stream_range;
|
struct stream_range;
|
||||||
|
|
||||||
struct Stream {
|
struct stream {
|
||||||
using Offset = StreamOffset;
|
using offset_type = stream_off_t;
|
||||||
|
|
||||||
virtual ~Stream() {}
|
virtual ~stream() {}
|
||||||
|
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
|
|
||||||
virtual bool end() const = 0;
|
virtual bool end() const = 0;
|
||||||
|
|
||||||
virtual Offset size() {
|
virtual offset_type size() {
|
||||||
Offset p = tell();
|
offset_type p = tell();
|
||||||
if ((p < 0) || !seek(0, StreamSeek::end)) {
|
if ((p < 0) || !seek(0, stream_seek::END)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
Offset e = tell();
|
offset_type e = tell();
|
||||||
return ((p == e) || seek(p, StreamSeek::set)) ? e : -1;
|
return ((p == e) || seek(p, stream_seek::SET)) ? e : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool seek(Offset, StreamSeek = StreamSeek::set) {
|
virtual bool seek(offset_type, stream_seek = stream_seek::SET) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Offset tell() const { return -1; }
|
virtual offset_type tell() const { return -1; }
|
||||||
|
|
||||||
virtual bool flush() { return true; }
|
virtual bool flush() { return true; }
|
||||||
|
|
||||||
|
@ -149,17 +148,17 @@ struct stream_range<T, true>: input_range<stream_range<T>> {
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
using reference = T;
|
using reference = T;
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
using difference_type = StreamOffset;
|
using difference_type = stream_off_t;
|
||||||
|
|
||||||
template<typename TT>
|
template<typename TT>
|
||||||
friend size_t range_put_n(stream_range<TT> &range, TT const *p, size_t n);
|
friend size_t range_put_n(stream_range<TT> &range, TT const *p, size_t n);
|
||||||
|
|
||||||
stream_range() = delete;
|
stream_range() = delete;
|
||||||
stream_range(Stream &s): p_stream(&s), p_size(s.size()) {}
|
stream_range(stream &s): p_stream(&s), p_size(s.size()) {}
|
||||||
stream_range(stream_range const &r): p_stream(r.p_stream), p_size(r.p_size) {}
|
stream_range(stream_range const &r): p_stream(r.p_stream), p_size(r.p_size) {}
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
return (p_size - p_stream->tell()) < StreamOffset(sizeof(T));
|
return (p_size - p_stream->tell()) < stream_off_t(sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pop_front() {
|
bool pop_front() {
|
||||||
|
@ -172,7 +171,7 @@ struct stream_range<T, true>: input_range<stream_range<T>> {
|
||||||
|
|
||||||
T front() const {
|
T front() const {
|
||||||
T val;
|
T val;
|
||||||
p_stream->seek(-p_stream->read_bytes(&val, sizeof(T)), StreamSeek::cur);
|
p_stream->seek(-p_stream->read_bytes(&val, sizeof(T)), stream_seek::CUR);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,8 +193,8 @@ struct stream_range<T, true>: input_range<stream_range<T>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Stream *p_stream;
|
stream *p_stream;
|
||||||
StreamOffset p_size;
|
stream_off_t p_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -204,7 +203,7 @@ inline size_t range_put_n(stream_range<T> &range, T const *p, size_t n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline stream_range<T> Stream::iter() {
|
inline stream_range<T> stream::iter() {
|
||||||
return stream_range<T>(*this);
|
return stream_range<T>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,11 +215,11 @@ namespace detail {
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
using difference_type = ptrdiff_t;
|
using difference_type = ptrdiff_t;
|
||||||
|
|
||||||
fmt_stream_range(Stream &s): p_s(s) {}
|
fmt_stream_range(stream &s): p_s(s) {}
|
||||||
bool put(char c) {
|
bool put(char c) {
|
||||||
return p_s.write_bytes(&c, 1) == 1;
|
return p_s.write_bytes(&c, 1) == 1;
|
||||||
}
|
}
|
||||||
Stream &p_s;
|
stream &p_s;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline size_t range_put_n(fmt_stream_range &range, char const *p, size_t n) {
|
inline size_t range_put_n(fmt_stream_range &range, char const *p, size_t n) {
|
||||||
|
@ -229,12 +228,12 @@ namespace detail {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void Stream::write(T const &v) {
|
inline void stream::write(T const &v) {
|
||||||
format(detail::fmt_stream_range{*this}, FormatSpec{'s'}, v);
|
format(detail::fmt_stream_range{*this}, format_spec{'s'}, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ...A>
|
template<typename ...A>
|
||||||
inline void Stream::writef(string_range fmt, A const &...args) {
|
inline void stream::writef(string_range fmt, A const &...args) {
|
||||||
format(detail::fmt_stream_range{*this}, fmt, args...);
|
format(detail::fmt_stream_range{*this}, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
139
ostd/string.hh
139
ostd/string.hh
|
@ -14,8 +14,8 @@
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "ostd/utility.hh"
|
|
||||||
#include "ostd/range.hh"
|
#include "ostd/range.hh"
|
||||||
#include "ostd/vector.hh"
|
#include "ostd/vector.hh"
|
||||||
#include "ostd/algorithm.hh"
|
#include "ostd/algorithm.hh"
|
||||||
|
@ -24,7 +24,7 @@ namespace ostd {
|
||||||
|
|
||||||
template<typename T, typename TR = std::char_traits<std::remove_const_t<T>>>
|
template<typename T, typename TR = std::char_traits<std::remove_const_t<T>>>
|
||||||
struct basic_char_range: input_range<basic_char_range<T>> {
|
struct basic_char_range: input_range<basic_char_range<T>> {
|
||||||
using range_category = ContiguousRangeTag;
|
using range_category = contiguous_range_tag;
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
using reference = T &;
|
using reference = T &;
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
|
@ -565,11 +565,6 @@ namespace detail {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename R>
|
|
||||||
static auto test_stringify(int) -> std::integral_constant<
|
|
||||||
bool, std::is_same_v<decltype(std::declval<T>().stringify()), std::string>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename T, typename R>
|
template<typename T, typename R>
|
||||||
static std::true_type test_stringify(
|
static std::true_type test_stringify(
|
||||||
decltype(std::declval<T const &>().to_string(std::declval<R &>())) *
|
decltype(std::declval<T const &>().to_string(std::declval<R &>())) *
|
||||||
|
@ -579,7 +574,7 @@ namespace detail {
|
||||||
static std::false_type test_stringify(...);
|
static std::false_type test_stringify(...);
|
||||||
|
|
||||||
template<typename T, typename R>
|
template<typename T, typename R>
|
||||||
constexpr bool StringifyTest = decltype(test_stringify<T, R>(0))::value;
|
constexpr bool stringify_test = decltype(test_stringify<T, R>(0))::value;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::true_type test_iterable(decltype(ostd::iter(std::declval<T>())) *);
|
static std::true_type test_iterable(decltype(ostd::iter(std::declval<T>())) *);
|
||||||
|
@ -587,21 +582,18 @@ namespace detail {
|
||||||
static std::false_type test_iterable(...);
|
static std::false_type test_iterable(...);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool IterableTest = decltype(test_iterable<T>(0))::value;
|
constexpr bool iterable_test = decltype(test_iterable<T>(0))::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename = void>
|
template<typename T, typename = void>
|
||||||
struct ToString;
|
struct to_string;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct ToString<T, std::enable_if_t<detail::IterableTest<T>>> {
|
struct to_string<T, std::enable_if_t<detail::iterable_test<T>>> {
|
||||||
using Argument = std::remove_cv_t<std::remove_reference_t<T>>;
|
|
||||||
using Result = std::string;
|
|
||||||
|
|
||||||
std::string operator()(T const &v) const {
|
std::string operator()(T const &v) const {
|
||||||
std::string ret("{");
|
std::string ret("{");
|
||||||
auto x = appender<std::string>();
|
auto x = appender<std::string>();
|
||||||
if (concat(x, ostd::iter(v), ", ", ToString<
|
if (concat(x, ostd::iter(v), ", ", to_string<
|
||||||
std::remove_const_t<std::remove_reference_t<
|
std::remove_const_t<std::remove_reference_t<
|
||||||
range_reference_t<decltype(ostd::iter(v))>
|
range_reference_t<decltype(ostd::iter(v))>
|
||||||
>>
|
>>
|
||||||
|
@ -614,12 +606,9 @@ struct ToString<T, std::enable_if_t<detail::IterableTest<T>>> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct ToString<T, std::enable_if_t<
|
struct to_string<T, std::enable_if_t<
|
||||||
detail::StringifyTest<T, detail::tostr_range<appender_range<std::string>>>
|
detail::stringify_test<T, detail::tostr_range<appender_range<std::string>>>
|
||||||
>> {
|
>> {
|
||||||
using Argument = std::remove_cv_t<std::remove_reference_t<T>>;
|
|
||||||
using Result = std::string;
|
|
||||||
|
|
||||||
std::string operator()(T const &v) const {
|
std::string operator()(T const &v) const {
|
||||||
auto app = appender<std::string>();
|
auto app = appender<std::string>();
|
||||||
detail::tostr_range<appender_range<std::string>> sink(app);
|
detail::tostr_range<appender_range<std::string>> sink(app);
|
||||||
|
@ -631,18 +620,14 @@ struct ToString<T, std::enable_if_t<
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ToString<bool> {
|
struct to_string<bool> {
|
||||||
using Argument = bool;
|
|
||||||
using Result = std::string;
|
|
||||||
std::string operator()(bool b) {
|
std::string operator()(bool b) {
|
||||||
return b ? "true" : "false";
|
return b ? "true" : "false";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ToString<char> {
|
struct to_string<char> {
|
||||||
using Argument = char;
|
|
||||||
using Result = std::string;
|
|
||||||
std::string operator()(char c) {
|
std::string operator()(char c) {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
ret += c;
|
ret += c;
|
||||||
|
@ -652,9 +637,7 @@ struct ToString<char> {
|
||||||
|
|
||||||
#define OSTD_TOSTR_NUM(T) \
|
#define OSTD_TOSTR_NUM(T) \
|
||||||
template<> \
|
template<> \
|
||||||
struct ToString<T> { \
|
struct to_string<T> { \
|
||||||
using Argument = T; \
|
|
||||||
using Result = std::string; \
|
|
||||||
std::string operator()(T v) { \
|
std::string operator()(T v) { \
|
||||||
return std::to_string(v); \
|
return std::to_string(v); \
|
||||||
} \
|
} \
|
||||||
|
@ -678,10 +661,8 @@ OSTD_TOSTR_NUM(ldouble)
|
||||||
#undef OSTD_TOSTR_NUM
|
#undef OSTD_TOSTR_NUM
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct ToString<T *> {
|
struct to_string<T *> {
|
||||||
using Argument = T *;
|
std::string operator()(T *v) {
|
||||||
using Result = std::string;
|
|
||||||
std::string operator()(Argument v) {
|
|
||||||
char buf[16];
|
char buf[16];
|
||||||
sprintf(buf, "%p", v);
|
sprintf(buf, "%p", v);
|
||||||
return buf;
|
return buf;
|
||||||
|
@ -689,59 +670,47 @@ struct ToString<T *> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ToString<char const *> {
|
struct to_string<char const *> {
|
||||||
using Argument = char const *;
|
|
||||||
using Result = std::string;
|
|
||||||
std::string operator()(char const *s) {
|
std::string operator()(char const *s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ToString<char *> {
|
struct to_string<char *> {
|
||||||
using Argument = char *;
|
|
||||||
using Result = std::string;
|
|
||||||
std::string operator()(char *s) {
|
std::string operator()(char *s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ToString<std::string> {
|
struct to_string<std::string> {
|
||||||
using Argument = std::string;
|
std::string operator()(std::string const &s) {
|
||||||
using Result = std::string;
|
|
||||||
std::string operator()(Argument const &s) {
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ToString<char_range> {
|
struct to_string<char_range> {
|
||||||
using Argument = char_range;
|
std::string operator()(char_range const &s) {
|
||||||
using Result = std::string;
|
|
||||||
std::string operator()(Argument const &s) {
|
|
||||||
return std::string{s};
|
return std::string{s};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ToString<string_range> {
|
struct to_string<string_range> {
|
||||||
using Argument = string_range;
|
std::string operator()(string_range const &s) {
|
||||||
using Result = std::string;
|
|
||||||
std::string operator()(Argument const &s) {
|
|
||||||
return std::string{s};
|
return std::string{s};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
struct ToString<std::pair<T, U>> {
|
struct to_string<std::pair<T, U>> {
|
||||||
using Argument = std::pair<T, U>;
|
std::string operator()(std::pair<T, U> const &v) {
|
||||||
using Result = std::string;
|
|
||||||
std::string operator()(Argument const &v) {
|
|
||||||
std::string ret{"{"};
|
std::string ret{"{"};
|
||||||
ret += ToString<std::remove_cv_t<std::remove_reference_t<T>>>()(v.first);
|
ret += to_string<std::remove_cv_t<std::remove_reference_t<T>>>()(v.first);
|
||||||
ret += ", ";
|
ret += ", ";
|
||||||
ret += ToString<std::remove_cv_t<std::remove_reference_t<U>>>()(v.second);
|
ret += to_string<std::remove_cv_t<std::remove_reference_t<U>>>()(v.second);
|
||||||
ret += "}";
|
ret += "}";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -749,71 +718,59 @@ struct ToString<std::pair<T, U>> {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<size_t I, size_t N>
|
template<size_t I, size_t N>
|
||||||
struct TupleToString {
|
struct tuple_to_str {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void append(std::string &ret, T const &tup) {
|
static void append(std::string &ret, T const &tup) {
|
||||||
ret += ", ";
|
ret += ", ";
|
||||||
ret += ToString<std::remove_cv_t<std::remove_reference_t<
|
ret += to_string<std::remove_cv_t<std::remove_reference_t<
|
||||||
decltype(std::get<I>(tup))
|
decltype(std::get<I>(tup))
|
||||||
>>>()(std::get<I>(tup));
|
>>>()(std::get<I>(tup));
|
||||||
TupleToString<I + 1, N>::append(ret, tup);
|
tuple_to_str<I + 1, N>::append(ret, tup);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
struct TupleToString<N, N> {
|
struct tuple_to_str<N, N> {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void append(std::string &, T const &) {}
|
static void append(std::string &, T const &) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
struct TupleToString<0, N> {
|
struct tuple_to_str<0, N> {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void append(std::string &ret, T const &tup) {
|
static void append(std::string &ret, T const &tup) {
|
||||||
ret += ToString<std::remove_cv_t<std::remove_reference_t<
|
ret += to_string<std::remove_cv_t<std::remove_reference_t<
|
||||||
decltype(std::get<0>(tup))
|
decltype(std::get<0>(tup))
|
||||||
>>>()(std::get<0>(tup));
|
>>>()(std::get<0>(tup));
|
||||||
TupleToString<1, N>::append(ret, tup);
|
tuple_to_str<1, N>::append(ret, tup);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ...T>
|
template<typename ...T>
|
||||||
struct ToString<std::tuple<T...>> {
|
struct to_string<std::tuple<T...>> {
|
||||||
using Argument = std::tuple<T...>;
|
std::string operator()(std::tuple<T...> const &v) {
|
||||||
using Result = std::string;
|
|
||||||
std::string operator()(Argument const &v) {
|
|
||||||
std::string ret("{");
|
std::string ret("{");
|
||||||
detail::TupleToString<0, sizeof...(T)>::append(ret, v);
|
detail::tuple_to_str<0, sizeof...(T)>::append(ret, v);
|
||||||
ret += "}";
|
ret += "}";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename ToString<T>::Result to_string(T const &v) {
|
|
||||||
return ToString<std::remove_cv_t<std::remove_reference_t<T>>>()(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
std::string to_string(std::initializer_list<T> init) {
|
|
||||||
return to_string(iter(init));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
struct TempCString {
|
struct temp_c_string {
|
||||||
private:
|
private:
|
||||||
std::remove_cv_t<range_value_t<R>> *p_buf;
|
std::remove_cv_t<range_value_t<R>> *p_buf;
|
||||||
bool p_allocated;
|
bool p_allocated;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TempCString() = delete;
|
temp_c_string() = delete;
|
||||||
TempCString(TempCString const &) = delete;
|
temp_c_string(temp_c_string const &) = delete;
|
||||||
TempCString(TempCString &&s): p_buf(s.p_buf), p_allocated(s.p_allocated) {
|
temp_c_string(temp_c_string &&s): p_buf(s.p_buf), p_allocated(s.p_allocated) {
|
||||||
s.p_buf = nullptr;
|
s.p_buf = nullptr;
|
||||||
s.p_allocated = false;
|
s.p_allocated = false;
|
||||||
}
|
}
|
||||||
TempCString(R input, std::remove_cv_t<range_value_t<R>> *sbuf, size_t bufsize)
|
temp_c_string(R input, std::remove_cv_t<range_value_t<R>> *sbuf, size_t bufsize)
|
||||||
: p_buf(nullptr), p_allocated(false) {
|
: p_buf(nullptr), p_allocated(false) {
|
||||||
if (input.empty()) {
|
if (input.empty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -826,14 +783,14 @@ public:
|
||||||
}
|
}
|
||||||
p_buf[input.copy(p_buf)] = '\0';
|
p_buf[input.copy(p_buf)] = '\0';
|
||||||
}
|
}
|
||||||
~TempCString() {
|
~temp_c_string() {
|
||||||
if (p_allocated) {
|
if (p_allocated) {
|
||||||
delete[] p_buf;
|
delete[] p_buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TempCString &operator=(TempCString const &) = delete;
|
temp_c_string &operator=(temp_c_string const &) = delete;
|
||||||
TempCString &operator=(TempCString &&s) {
|
temp_c_string &operator=(temp_c_string &&s) {
|
||||||
swap(s);
|
swap(s);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -841,7 +798,7 @@ public:
|
||||||
operator std::remove_cv_t<range_value_t<R>> const *() const { return p_buf; }
|
operator std::remove_cv_t<range_value_t<R>> const *() const { return p_buf; }
|
||||||
std::remove_cv_t<range_value_t<R>> const *get() const { return p_buf; }
|
std::remove_cv_t<range_value_t<R>> const *get() const { return p_buf; }
|
||||||
|
|
||||||
void swap(TempCString &s) {
|
void swap(temp_c_string &s) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(p_buf, s.p_buf);
|
swap(p_buf, s.p_buf);
|
||||||
swap(p_allocated, s.p_allocated);
|
swap(p_allocated, s.p_allocated);
|
||||||
|
@ -849,15 +806,15 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
inline void swap(TempCString<R> &a, TempCString<R> &b) {
|
inline void swap(temp_c_string<R> &a, temp_c_string<R> &b) {
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
inline TempCString<R> to_temp_cstr(
|
inline temp_c_string<R> to_temp_cstr(
|
||||||
R input, std::remove_cv_t<range_value_t<R>> *buf, size_t bufsize
|
R input, std::remove_cv_t<range_value_t<R>> *buf, size_t bufsize
|
||||||
) {
|
) {
|
||||||
return TempCString<R>(input, buf, bufsize);
|
return temp_c_string<R>(input, buf, bufsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace ostd */
|
} /* namespace ostd */
|
||||||
|
|
|
@ -26,7 +26,7 @@ using ldouble = long double;
|
||||||
/* used occasionally for template variables */
|
/* used occasionally for template variables */
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename> struct Undefined;
|
template<typename> struct undef_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
230
ostd/utility.hh
230
ostd/utility.hh
|
@ -1,230 +0,0 @@
|
||||||
/* Utilities for OctaSTD.
|
|
||||||
*
|
|
||||||
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OSTD_UTILITY_HH
|
|
||||||
#define OSTD_UTILITY_HH
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "ostd/types.hh"
|
|
||||||
|
|
||||||
namespace ostd {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template<typename T, typename U,
|
|
||||||
bool = std::is_same_v<std::remove_cv_t<T>, std::remove_cv_t<U>>,
|
|
||||||
bool = std::is_empty_v<T>, bool = std::is_empty_v<U>
|
|
||||||
>
|
|
||||||
constexpr size_t CompressedPairSwitch = detail::Undefined<T>();
|
|
||||||
|
|
||||||
/* neither empty */
|
|
||||||
template<typename T, typename U, bool Same>
|
|
||||||
constexpr size_t CompressedPairSwitch<T, U, Same, false, false> = 0;
|
|
||||||
|
|
||||||
/* first empty */
|
|
||||||
template<typename T, typename U, bool Same>
|
|
||||||
constexpr size_t CompressedPairSwitch<T, U, Same, true, false> = 1;
|
|
||||||
|
|
||||||
/* second empty */
|
|
||||||
template<typename T, typename U, bool Same>
|
|
||||||
constexpr size_t CompressedPairSwitch<T, U, Same, false, true> = 2;
|
|
||||||
|
|
||||||
/* both empty, not the same */
|
|
||||||
template<typename T, typename U>
|
|
||||||
constexpr size_t CompressedPairSwitch<T, U, false, true, true> = 3;
|
|
||||||
|
|
||||||
/* both empty and same */
|
|
||||||
template<typename T, typename U>
|
|
||||||
constexpr size_t CompressedPairSwitch<T, U, true, true, true> = 1;
|
|
||||||
|
|
||||||
template<typename T, typename U, size_t = CompressedPairSwitch<T, U>>
|
|
||||||
struct CompressedPairBase;
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct CompressedPairBase<T, U, 0> {
|
|
||||||
T p_first;
|
|
||||||
U p_second;
|
|
||||||
|
|
||||||
template<typename TT, typename UU>
|
|
||||||
CompressedPairBase(TT &&a, UU &&b):
|
|
||||||
p_first(std::forward<TT>(a)), p_second(std::forward<UU>(b))
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename ...A1, typename ...A2, size_t ...I1, size_t ...I2>
|
|
||||||
CompressedPairBase(
|
|
||||||
std::piecewise_construct_t,
|
|
||||||
std::tuple<A1...> &fa, std::tuple<A2...> &sa,
|
|
||||||
std::index_sequence<I1...>, std::index_sequence<I2...>
|
|
||||||
);
|
|
||||||
|
|
||||||
T &first() { return p_first; }
|
|
||||||
T const &first() const { return p_first; }
|
|
||||||
|
|
||||||
U &second() { return p_second; }
|
|
||||||
U const &second() const { return p_second; }
|
|
||||||
|
|
||||||
void swap(CompressedPairBase &v) {
|
|
||||||
swap_adl(p_first, v.p_first);
|
|
||||||
swap_adl(p_second, v.p_second);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct CompressedPairBase<T, U, 1>: T {
|
|
||||||
U p_second;
|
|
||||||
|
|
||||||
template<typename TT, typename UU>
|
|
||||||
CompressedPairBase(TT &&a, UU &&b):
|
|
||||||
T(std::forward<TT>(a)), p_second(std::forward<UU>(b))
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename ...A1, typename ...A2, size_t ...I1, size_t ...I2>
|
|
||||||
CompressedPairBase(
|
|
||||||
std::piecewise_construct_t,
|
|
||||||
std::tuple<A1...> &fa, std::tuple<A2...> &sa,
|
|
||||||
std::index_sequence<I1...>, std::index_sequence<I2...>
|
|
||||||
);
|
|
||||||
|
|
||||||
T &first() { return *this; }
|
|
||||||
T const &first() const { return *this; }
|
|
||||||
|
|
||||||
U &second() { return p_second; }
|
|
||||||
U const &second() const { return p_second; }
|
|
||||||
|
|
||||||
void swap(CompressedPairBase &v) {
|
|
||||||
swap_adl(p_second, v.p_second);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct CompressedPairBase<T, U, 2>: U {
|
|
||||||
T p_first;
|
|
||||||
|
|
||||||
template<typename TT, typename UU>
|
|
||||||
CompressedPairBase(TT &&a, UU &&b):
|
|
||||||
U(std::forward<UU>(b)), p_first(std::forward<TT>(a))
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename ...A1, typename ...A2, size_t ...I1, size_t ...I2>
|
|
||||||
CompressedPairBase(
|
|
||||||
std::piecewise_construct_t,
|
|
||||||
std::tuple<A1...> &fa, std::tuple<A2...> &sa,
|
|
||||||
std::index_sequence<I1...>, std::index_sequence<I2...>
|
|
||||||
);
|
|
||||||
|
|
||||||
T &first() { return p_first; }
|
|
||||||
T const &first() const { return p_first; }
|
|
||||||
|
|
||||||
U &second() { return *this; }
|
|
||||||
U const &second() const { return *this; }
|
|
||||||
|
|
||||||
void swap(CompressedPairBase &v) {
|
|
||||||
swap_adl(p_first, v.p_first);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct CompressedPairBase<T, U, 3>: T, U {
|
|
||||||
template<typename TT, typename UU>
|
|
||||||
CompressedPairBase(TT &&a, UU &&b):
|
|
||||||
T(std::forward<TT>(a)), U(std::forward<UU>(b))
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename ...A1, typename ...A2, size_t ...I1, size_t ...I2>
|
|
||||||
CompressedPairBase(
|
|
||||||
std::piecewise_construct_t,
|
|
||||||
std::tuple<A1...> &fa, std::tuple<A2...> &sa,
|
|
||||||
std::index_sequence<I1...>, std::index_sequence<I2...>
|
|
||||||
);
|
|
||||||
|
|
||||||
T &first() { return *this; }
|
|
||||||
T const &first() const { return *this; }
|
|
||||||
|
|
||||||
U &second() { return *this; }
|
|
||||||
U const &second() const { return *this; }
|
|
||||||
|
|
||||||
void swap(CompressedPairBase &) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct CompressedPair: CompressedPairBase<T, U> {
|
|
||||||
using Base = CompressedPairBase<T, U>;
|
|
||||||
|
|
||||||
template<typename TT, typename UU>
|
|
||||||
CompressedPair(TT &&a, UU &&b):
|
|
||||||
Base(std::forward<TT>(a), std::forward<UU>(b))
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename ...A1, typename ...A2>
|
|
||||||
CompressedPair(
|
|
||||||
std::piecewise_construct_t pc,
|
|
||||||
std::tuple<A1...> fa, std::tuple<A2...> sa
|
|
||||||
):
|
|
||||||
Base(
|
|
||||||
pc, fa, sa,
|
|
||||||
std::make_index_sequence<sizeof...(A1)>(),
|
|
||||||
std::make_index_sequence<sizeof...(A2)>()
|
|
||||||
)
|
|
||||||
{}
|
|
||||||
|
|
||||||
T &first() { return Base::first(); }
|
|
||||||
T const &first() const { return Base::first(); }
|
|
||||||
|
|
||||||
U &second() { return Base::second(); }
|
|
||||||
U const &second() const { return Base::second(); }
|
|
||||||
|
|
||||||
void swap(CompressedPair &v) {
|
|
||||||
Base::swap(v);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
template<typename ...A1, typename ...A2, size_t ...I1, size_t ...I2>
|
|
||||||
CompressedPairBase<T, U, 0>::CompressedPairBase(
|
|
||||||
std::piecewise_construct_t, std::tuple<A1...> &fa, std::tuple<A2...> &sa,
|
|
||||||
std::index_sequence<I1...>, std::index_sequence<I2...>
|
|
||||||
):
|
|
||||||
p_first(std::forward<A1>(std::get<I1>(fa))...),
|
|
||||||
p_second(std::forward<A2>(std::get<I2>(sa))...)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
template<typename ...A1, typename ...A2, size_t ...I1, size_t ...I2>
|
|
||||||
CompressedPairBase<T, U, 1>::CompressedPairBase(
|
|
||||||
std::piecewise_construct_t, std::tuple<A1...> &fa, std::tuple<A2...> &sa,
|
|
||||||
std::index_sequence<I1...>, std::index_sequence<I2...>
|
|
||||||
):
|
|
||||||
T(std::forward<A1>(std::get<I1>(fa))...),
|
|
||||||
p_second(std::forward<A2>(std::get<I2>(sa))...)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
template<typename ...A1, typename ...A2, size_t ...I1, size_t ...I2>
|
|
||||||
CompressedPairBase<T, U, 2>::CompressedPairBase(
|
|
||||||
std::piecewise_construct_t, std::tuple<A1...> &fa, std::tuple<A2...> &sa,
|
|
||||||
std::index_sequence<I1...>, std::index_sequence<I2...>
|
|
||||||
):
|
|
||||||
U(std::forward<A2>(std::get<I2>(sa))...),
|
|
||||||
p_first(std::forward<A1>(std::get<I1>(fa))...)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
template<typename ...A1, typename ...A2, size_t ...I1, size_t ...I2>
|
|
||||||
CompressedPairBase<T, U, 3>::CompressedPairBase(
|
|
||||||
std::piecewise_construct_t, std::tuple<A1...> &fa, std::tuple<A2...> &sa,
|
|
||||||
std::index_sequence<I1...>, std::index_sequence<I2...>
|
|
||||||
):
|
|
||||||
T(std::forward<A1>(std::get<I1>(fa))...),
|
|
||||||
U(std::forward<A2>(std::get<I2>(sa))...)
|
|
||||||
{}
|
|
||||||
} /* namespace detail */
|
|
||||||
|
|
||||||
} /* namespace ostd */
|
|
||||||
|
|
||||||
#endif
|
|
234
ostd/vecmath.hh
234
ostd/vecmath.hh
|
@ -11,57 +11,57 @@
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Vec2 {
|
struct vec2 {
|
||||||
union {
|
union {
|
||||||
struct { T x, y; };
|
struct { T x, y; };
|
||||||
T value[2];
|
T value[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
Vec2(): x(0), y(0) {}
|
vec2(): x(0), y(0) {}
|
||||||
Vec2(Vec2 const &v): x(v.x), y(v.y) {}
|
vec2(vec2 const &v): x(v.x), y(v.y) {}
|
||||||
Vec2(T v): x(v), y(v) {}
|
vec2(T v): x(v), y(v) {}
|
||||||
Vec2(T x, T y): x(x), y(y) {}
|
vec2(T x, T y): x(x), y(y) {}
|
||||||
|
|
||||||
T &operator[](size_t idx) { return value[idx]; }
|
T &operator[](size_t idx) { return value[idx]; }
|
||||||
T operator[](size_t idx) const { return value[idx]; }
|
T operator[](size_t idx) const { return value[idx]; }
|
||||||
|
|
||||||
Vec2 &add(T v) {
|
vec2 &add(T v) {
|
||||||
x += v; y += v;
|
x += v; y += v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec2 &add(Vec2 const &o) {
|
vec2 &add(vec2 const &o) {
|
||||||
x += o.x; y += o.y;
|
x += o.x; y += o.y;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 &sub(T v) {
|
vec2 &sub(T v) {
|
||||||
x -= v; y -= v;
|
x -= v; y -= v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec2 &sub(Vec2 const &o) {
|
vec2 &sub(vec2 const &o) {
|
||||||
x -= o.x; y -= o.y;
|
x -= o.x; y -= o.y;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 &mul(T v) {
|
vec2 &mul(T v) {
|
||||||
x *= v; y *= v;
|
x *= v; y *= v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec2 &mul(Vec2 const &o) {
|
vec2 &mul(vec2 const &o) {
|
||||||
x *= o.x; y *= o.y;
|
x *= o.x; y *= o.y;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 &div(T v) {
|
vec2 &div(T v) {
|
||||||
x /= v; y /= v;
|
x /= v; y /= v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec2 &div(Vec2 const &o) {
|
vec2 &div(vec2 const &o) {
|
||||||
x /= o.x; y /= o.y;
|
x /= o.x; y /= o.y;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 &neg() {
|
vec2 &neg() {
|
||||||
x = -x; y = -y;
|
x = -x; y = -y;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -70,124 +70,124 @@ struct Vec2 {
|
||||||
return (x == 0) && (y == 0);
|
return (x == 0) && (y == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
T dot(Vec2<T> const &o) const {
|
T dot(vec2<T> const &o) const {
|
||||||
return (x * o.x) + (y * o.y);
|
return (x * o.x) + (y * o.y);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool operator==(Vec2<T> const &a, Vec2<T> const &b) {
|
inline bool operator==(vec2<T> const &a, vec2<T> const &b) {
|
||||||
return (a.x == b.x) && (a.y == b.y);
|
return (a.x == b.x) && (a.y == b.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool operator!=(Vec2<T> const &a, Vec2<T> const &b) {
|
inline bool operator!=(vec2<T> const &a, vec2<T> const &b) {
|
||||||
return (a.x != b.x) || (a.y != b.y);
|
return (a.x != b.x) || (a.y != b.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec2<T> operator+(Vec2<T> const &a, Vec2<T> const &b) {
|
inline vec2<T> operator+(vec2<T> const &a, vec2<T> const &b) {
|
||||||
return Vec2<T>(a).add(b);
|
return vec2<T>(a).add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec2<T> operator+(Vec2<T> const &a, T b) {
|
inline vec2<T> operator+(vec2<T> const &a, T b) {
|
||||||
return Vec2<T>(a).add(b);
|
return vec2<T>(a).add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec2<T> operator-(Vec2<T> const &a, Vec2<T> const &b) {
|
inline vec2<T> operator-(vec2<T> const &a, vec2<T> const &b) {
|
||||||
return Vec2<T>(a).sub(b);
|
return vec2<T>(a).sub(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec2<T> operator-(Vec2<T> const &a, T b) {
|
inline vec2<T> operator-(vec2<T> const &a, T b) {
|
||||||
return Vec2<T>(a).sub(b);
|
return vec2<T>(a).sub(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec2<T> operator*(Vec2<T> const &a, Vec2<T> const &b) {
|
inline vec2<T> operator*(vec2<T> const &a, vec2<T> const &b) {
|
||||||
return Vec2<T>(a).mul(b);
|
return vec2<T>(a).mul(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec2<T> operator*(Vec2<T> const &a, T b) {
|
inline vec2<T> operator*(vec2<T> const &a, T b) {
|
||||||
return Vec2<T>(a).mul(b);
|
return vec2<T>(a).mul(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec2<T> operator/(Vec2<T> const &a, Vec2<T> const &b) {
|
inline vec2<T> operator/(vec2<T> const &a, vec2<T> const &b) {
|
||||||
return Vec2<T>(a).div(b);
|
return vec2<T>(a).div(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec2<T> operator/(Vec2<T> const &a, T b) {
|
inline vec2<T> operator/(vec2<T> const &a, T b) {
|
||||||
return Vec2<T>(a).div(b);
|
return vec2<T>(a).div(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec2<T> operator-(Vec2<T> const &a) {
|
inline vec2<T> operator-(vec2<T> const &a) {
|
||||||
return Vec2<T>(a).neg();
|
return vec2<T>(a).neg();
|
||||||
}
|
}
|
||||||
|
|
||||||
using Vec2f = Vec2<float>;
|
using vec2f = vec2<float>;
|
||||||
using Vec2d = Vec2<double>;
|
using vec2d = vec2<double>;
|
||||||
using Vec2b = Vec2<byte>;
|
using vec2b = vec2<byte>;
|
||||||
using Vec2i = Vec2<int>;
|
using vec2i = vec2<int>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Vec3 {
|
struct vec3 {
|
||||||
union {
|
union {
|
||||||
struct { T x, y, z; };
|
struct { T x, y, z; };
|
||||||
struct { T r, g, b; };
|
struct { T r, g, b; };
|
||||||
T value[3];
|
T value[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
Vec3(): x(0), y(0), z(0) {}
|
vec3(): x(0), y(0), z(0) {}
|
||||||
Vec3(Vec3 const &v): x(v.x), y(v.y), z(v.z) {}
|
vec3(vec3 const &v): x(v.x), y(v.y), z(v.z) {}
|
||||||
Vec3(T v): x(v), y(v), z(v) {}
|
vec3(T v): x(v), y(v), z(v) {}
|
||||||
Vec3(T x, T y, T z): x(x), y(y), z(z) {}
|
vec3(T x, T y, T z): x(x), y(y), z(z) {}
|
||||||
|
|
||||||
T &operator[](size_t idx) { return value[idx]; }
|
T &operator[](size_t idx) { return value[idx]; }
|
||||||
T operator[](size_t idx) const { return value[idx]; }
|
T operator[](size_t idx) const { return value[idx]; }
|
||||||
|
|
||||||
Vec3 &add(T v) {
|
vec3 &add(T v) {
|
||||||
x += v; y += v; z += v;
|
x += v; y += v; z += v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec3 &add(Vec3 const &o) {
|
vec3 &add(vec3 const &o) {
|
||||||
x += o.x; y += o.y; z += o.z;
|
x += o.x; y += o.y; z += o.z;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 &sub(T v) {
|
vec3 &sub(T v) {
|
||||||
x -= v; y -= v; z -= v;
|
x -= v; y -= v; z -= v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec3 &sub(Vec3 const &o) {
|
vec3 &sub(vec3 const &o) {
|
||||||
x -= o.x; y -= o.y; z -= o.z;
|
x -= o.x; y -= o.y; z -= o.z;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 &mul(T v) {
|
vec3 &mul(T v) {
|
||||||
x *= v; y *= v; z *= v;
|
x *= v; y *= v; z *= v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec3 &mul(Vec3 const &o) {
|
vec3 &mul(vec3 const &o) {
|
||||||
x *= o.x; y *= o.y; z *= o.z;
|
x *= o.x; y *= o.y; z *= o.z;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 &div(T v) {
|
vec3 &div(T v) {
|
||||||
x /= v; y /= v; z /= v;
|
x /= v; y /= v; z /= v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec3 &div(Vec3 const &o) {
|
vec3 &div(vec3 const &o) {
|
||||||
x /= o.x; y /= o.y; z /= o.z;
|
x /= o.x; y /= o.y; z /= o.z;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 &neg() {
|
vec3 &neg() {
|
||||||
x = -x; y = -y; z = -z;
|
x = -x; y = -y; z = -z;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -196,124 +196,124 @@ struct Vec3 {
|
||||||
return (x == 0) && (y == 0) && (z == 0);
|
return (x == 0) && (y == 0) && (z == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
T dot(Vec3<T> const &o) const {
|
T dot(vec3<T> const &o) const {
|
||||||
return (x * o.x) + (y * o.y) + (z * o.z);
|
return (x * o.x) + (y * o.y) + (z * o.z);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool operator==(Vec3<T> const &a, Vec3<T> const &b) {
|
inline bool operator==(vec3<T> const &a, vec3<T> const &b) {
|
||||||
return (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
|
return (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool operator!=(Vec3<T> const &a, Vec3<T> const &b) {
|
inline bool operator!=(vec3<T> const &a, vec3<T> const &b) {
|
||||||
return (a.x != b.x) || (a.y != b.y) || (a.z != b.z);
|
return (a.x != b.x) || (a.y != b.y) || (a.z != b.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec3<T> operator+(Vec3<T> const &a, Vec3<T> const &b) {
|
inline vec3<T> operator+(vec3<T> const &a, vec3<T> const &b) {
|
||||||
return Vec3<T>(a).add(b);
|
return vec3<T>(a).add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec3<T> operator+(Vec3<T> const &a, T b) {
|
inline vec3<T> operator+(vec3<T> const &a, T b) {
|
||||||
return Vec3<T>(a).add(b);
|
return vec3<T>(a).add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec3<T> operator-(Vec3<T> const &a, Vec3<T> const &b) {
|
inline vec3<T> operator-(vec3<T> const &a, vec3<T> const &b) {
|
||||||
return Vec3<T>(a).sub(b);
|
return vec3<T>(a).sub(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec3<T> operator-(Vec3<T> const &a, T b) {
|
inline vec3<T> operator-(vec3<T> const &a, T b) {
|
||||||
return Vec3<T>(a).sub(b);
|
return vec3<T>(a).sub(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec3<T> operator*(Vec3<T> const &a, Vec3<T> const &b) {
|
inline vec3<T> operator*(vec3<T> const &a, vec3<T> const &b) {
|
||||||
return Vec3<T>(a).mul(b);
|
return vec3<T>(a).mul(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec3<T> operator*(Vec3<T> const &a, T b) {
|
inline vec3<T> operator*(vec3<T> const &a, T b) {
|
||||||
return Vec3<T>(a).mul(b);
|
return vec3<T>(a).mul(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec3<T> operator/(Vec3<T> const &a, Vec3<T> const &b) {
|
inline vec3<T> operator/(vec3<T> const &a, vec3<T> const &b) {
|
||||||
return Vec3<T>(a).div(b);
|
return vec3<T>(a).div(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec3<T> operator/(Vec3<T> const &a, T b) {
|
inline vec3<T> operator/(vec3<T> const &a, T b) {
|
||||||
return Vec3<T>(a).div(b);
|
return vec3<T>(a).div(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec3<T> operator-(Vec3<T> const &a) {
|
inline vec3<T> operator-(vec3<T> const &a) {
|
||||||
return Vec3<T>(a).neg();
|
return vec3<T>(a).neg();
|
||||||
}
|
}
|
||||||
|
|
||||||
using Vec3f = Vec3<float>;
|
using vec3f = vec3<float>;
|
||||||
using Vec3d = Vec3<double>;
|
using vec3d = vec3<double>;
|
||||||
using Vec3b = Vec3<byte>;
|
using vec3b = vec3<byte>;
|
||||||
using Vec3i = Vec3<int>;
|
using vec3i = vec3<int>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Vec4 {
|
struct vec4 {
|
||||||
union {
|
union {
|
||||||
struct { T x, y, z, w; };
|
struct { T x, y, z, w; };
|
||||||
struct { T r, g, b, a; };
|
struct { T r, g, b, a; };
|
||||||
T value[4];
|
T value[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
Vec4(): x(0), y(0), z(0), w(0) {}
|
vec4(): x(0), y(0), z(0), w(0) {}
|
||||||
Vec4(Vec4 const &v): x(v.x), y(v.y), z(v.z), w(v.w) {}
|
vec4(vec4 const &v): x(v.x), y(v.y), z(v.z), w(v.w) {}
|
||||||
Vec4(T v): x(v), y(v), z(v), w(v) {}
|
vec4(T v): x(v), y(v), z(v), w(v) {}
|
||||||
Vec4(T x, T y, T z, T w): x(x), y(y), z(z), w(w) {}
|
vec4(T x, T y, T z, T w): x(x), y(y), z(z), w(w) {}
|
||||||
|
|
||||||
T &operator[](size_t idx) { return value[idx]; }
|
T &operator[](size_t idx) { return value[idx]; }
|
||||||
T operator[](size_t idx) const { return value[idx]; }
|
T operator[](size_t idx) const { return value[idx]; }
|
||||||
|
|
||||||
Vec4 &add(T v) {
|
vec4 &add(T v) {
|
||||||
x += v; y += v; z += v; w += v;
|
x += v; y += v; z += v; w += v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec4 &add(Vec4 const &o) {
|
vec4 &add(vec4 const &o) {
|
||||||
x += o.x; y += o.y; z += o.z; w += o.w;
|
x += o.x; y += o.y; z += o.z; w += o.w;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 &sub(T v) {
|
vec4 &sub(T v) {
|
||||||
x -= v; y -= v; z -= v; w -= v;
|
x -= v; y -= v; z -= v; w -= v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec4 &sub(Vec4 const &o) {
|
vec4 &sub(vec4 const &o) {
|
||||||
x -= o.x; y -= o.y; z -= o.z; w -= o.w;
|
x -= o.x; y -= o.y; z -= o.z; w -= o.w;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 &mul(T v) {
|
vec4 &mul(T v) {
|
||||||
x *= v; y *= v; z *= v; w *= v;
|
x *= v; y *= v; z *= v; w *= v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec4 &mul(Vec4 const &o) {
|
vec4 &mul(vec4 const &o) {
|
||||||
x *= o.x; y *= o.y; z *= o.z; w *= o.w;
|
x *= o.x; y *= o.y; z *= o.z; w *= o.w;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 &div(T v) {
|
vec4 &div(T v) {
|
||||||
x /= v; y /= v; z /= v; w /= v;
|
x /= v; y /= v; z /= v; w /= v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Vec4 &div(Vec4 const &o) {
|
vec4 &div(vec4 const &o) {
|
||||||
x /= o.x; y /= o.y; z /= o.z; w /= o.w;
|
x /= o.x; y /= o.y; z /= o.z; w /= o.w;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 &neg() {
|
vec4 &neg() {
|
||||||
x = -x; y = -y; z = -z; w = -w;
|
x = -x; y = -y; z = -z; w = -w;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -322,70 +322,70 @@ struct Vec4 {
|
||||||
return (x == 0) && (y == 0) && (z == 0) && (w == 0);
|
return (x == 0) && (y == 0) && (z == 0) && (w == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
T dot(Vec4<T> const &o) const {
|
T dot(vec4<T> const &o) const {
|
||||||
return (x * o.x) + (y * o.y) + (z * o.z) + (w * o.w);
|
return (x * o.x) + (y * o.y) + (z * o.z) + (w * o.w);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool operator==(Vec4<T> const &a, Vec4<T> const &b) {
|
inline bool operator==(vec4<T> const &a, vec4<T> const &b) {
|
||||||
return (a.x == b.x) && (a.y == b.y) && (a.z == b.z) && (a.w == b.w);
|
return (a.x == b.x) && (a.y == b.y) && (a.z == b.z) && (a.w == b.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool operator!=(Vec4<T> const &a, Vec4<T> const &b) {
|
inline bool operator!=(vec4<T> const &a, vec4<T> const &b) {
|
||||||
return (a.x != b.x) || (a.y != b.y) || (a.z != b.z) || (a.w != b.w);
|
return (a.x != b.x) || (a.y != b.y) || (a.z != b.z) || (a.w != b.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec4<T> operator+(Vec4<T> const &a, Vec4<T> const &b) {
|
inline vec4<T> operator+(vec4<T> const &a, vec4<T> const &b) {
|
||||||
return Vec4<T>(a).add(b);
|
return vec4<T>(a).add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec4<T> operator+(Vec4<T> const &a, T b) {
|
inline vec4<T> operator+(vec4<T> const &a, T b) {
|
||||||
return Vec4<T>(a).add(b);
|
return vec4<T>(a).add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec4<T> operator-(Vec4<T> const &a, Vec4<T> const &b) {
|
inline vec4<T> operator-(vec4<T> const &a, vec4<T> const &b) {
|
||||||
return Vec4<T>(a).sub(b);
|
return vec4<T>(a).sub(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec4<T> operator-(Vec4<T> const &a, T b) {
|
inline vec4<T> operator-(vec4<T> const &a, T b) {
|
||||||
return Vec4<T>(a).sub(b);
|
return vec4<T>(a).sub(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec4<T> operator*(Vec4<T> const &a, Vec4<T> const &b) {
|
inline vec4<T> operator*(vec4<T> const &a, vec4<T> const &b) {
|
||||||
return Vec4<T>(a).mul(b);
|
return vec4<T>(a).mul(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec4<T> operator*(Vec4<T> const &a, T b) {
|
inline vec4<T> operator*(vec4<T> const &a, T b) {
|
||||||
return Vec4<T>(a).mul(b);
|
return vec4<T>(a).mul(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec4<T> operator/(Vec4<T> const &a, Vec4<T> const &b) {
|
inline vec4<T> operator/(vec4<T> const &a, vec4<T> const &b) {
|
||||||
return Vec4<T>(a).div(b);
|
return vec4<T>(a).div(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec4<T> operator/(Vec4<T> const &a, T b) {
|
inline vec4<T> operator/(vec4<T> const &a, T b) {
|
||||||
return Vec4<T>(a).div(b);
|
return vec4<T>(a).div(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Vec4<T> operator-(Vec4<T> const &a) {
|
inline vec4<T> operator-(vec4<T> const &a) {
|
||||||
return Vec4<T>(a).neg();
|
return vec4<T>(a).neg();
|
||||||
}
|
}
|
||||||
|
|
||||||
using Vec4f = Vec4<float>;
|
using vec4f = vec4<float>;
|
||||||
using Vec4d = Vec4<double>;
|
using vec4d = vec4<double>;
|
||||||
using Vec4b = Vec4<byte>;
|
using vec4b = vec4<byte>;
|
||||||
using Vec4i = Vec4<int>;
|
using vec4i = vec4<int>;
|
||||||
|
|
||||||
} /* namespace ostd */
|
} /* namespace ostd */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue