#include <ostream>
#include <dirent.h>
#include <assert.h>
#include <sstream>
#include <string>
#include <memory>
#include <vector>
#include <iostream>
#include <algorithm>
typedef bool bool_t;
typedef unsigned char short_t;
typedef unsigned short smallint_t;
typedef unsigned int int_t;
typedef unsigned long long_t;
namespace variadic
{
template<bool D, typename Head, typename... Tail>
struct accumulate_stream
{
static void call(std::ostringstream& stream, const Head& head, const Tail&... tail)
{
stream << head;
accumulate_stream<sizeof...(Tail) == 1, Tail...>::call(stream, tail...);
}
};
template<class Head>
struct accumulate_stream<true, Head>
{
static void call(std::ostringstream& stream, const Head& head)
{
stream << head;
}
};
template<bool D, typename Head, typename... Tail>
struct accumulate_stream_separated
{
static void call(std::ostringstream& stream, const char separator, const Head& head, const Tail&... tail)
{
stream << separator << head;
accumulate_stream_separated<sizeof...(Tail) == 1, Tail...>::call(stream, separator, tail...);
}
};
template<class Head>
struct accumulate_stream_separated<true, Head>
{
static void call(std::ostringstream& stream, const char separator, const Head& head)
{
stream << separator << head;
}
};
template<typename Head, typename... Tail>
static const std::string accumulate(const Head& head, const Tail&... tail)
{
std::ostringstream oss;
variadic::accumulate_stream<sizeof...(Tail) == 0, Head, Tail...>::call(oss, head, tail...);
return oss.str();
}
template<typename Head, typename... Tail>
static const std::string accumulate_separator(const char separator, const Head& head, const Tail&... tail)
{
std::ostringstream oss;
variadic::accumulate_stream_separated<sizeof...(Tail) == 0, Head, Tail...>::call(oss, separator, head, tail...);
return oss.str();
}
}
////
namespace fs
{
class any;
typedef long_t size_t;
typedef int_t inner_int_t;
extern const fs::size_t not_fetched = -1;
extern const fs::size_t unknown = -2;
extern const fs::size_t empty = 0;
static any* no_parent = nullptr;
extern const char separator = '/';
extern const char dot = '.';
typedef inner_int_t file_type;
typedef std::string directory_name;
typedef std::string file_name;
typedef std::string path;
typedef std::string ext;
class variadic_constructor {};
class unknown_ext
{
public:
unknown_ext(const fs::ext& E) : m_e(E) {}
virtual ~unknown_ext() throw() {}
const fs::ext& what() const throw() { return m_e; }
private:
const fs::ext m_e;
};
class any
{
public:
typedef std::shared_ptr<any> ptr;
typedef const std::shared_ptr<any> const_ptr;
any() : m_parent(fs::no_parent), m_name(), m_size(fs::unknown), m_offset(fs::unknown), m_childs() {std::cout<<"any::no arg"<<std::endl;}
any(const std::string& n) : m_parent(fs::no_parent), m_name(n), m_size(fs::not_fetched), m_offset(fs::not_fetched), m_childs() {std::cout<<"any::string"<<std::endl;}
any(ptr p, const std::string& n) : m_parent(p), m_name(n), m_size(fs::not_fetched), m_offset(fs::not_fetched), m_childs() {std::cout<<"any::parent string"<<std::endl;}
template<typename Head, typename... Tail>
any(const Head& head, const Tail&... tail) : m_parent(fs::no_parent), m_name(variadic::accumulate_separator(fs::separator, head, tail...)), m_size(fs::unknown), m_offset(fs::unknown), m_childs() {std::cout<<"any::variadic"<<std::endl;}
virtual ~any() { m_childs.clear(); }
virtual inline bool is_file() const = 0;
virtual inline bool is_directory() const = 0;
const std::string& name() const { return m_name; }
inline fs::size_t size() const { return m_size; }
inline fs::size_t offset() const { return m_offset; }
std::vector<ptr>::iterator begin() { return std::begin(m_childs); }
std::vector<ptr>::iterator end() { return std::end(m_childs); }
const std::string path(const std::string& Pf) const
{
auto str(variadic::accumulate(Pf, fs::separator, m_name));
return m_parent ? path(str) : str;
}
protected:
const_ptr m_parent;
std::string m_name;
fs::size_t m_size;
fs::size_t m_offset; /// Only used if you're using fs::write
std::vector<ptr> m_childs;
void update_size()
{
m_size = std::accumulate(begin(), end(), 0,
[](fs::size_t a, ptr b)
{
assert(b->size() != fs::unknown);
return a+b->size();
});
if(m_parent) m_parent->update_size();
}
private:
//virtual const std::string str() const = 0;
};
class directory: public any
{
public:
typedef std::shared_ptr<directory> ptr;
typedef const std::shared_ptr<directory> const_ptr;
class could_not_open
{
public:
could_not_open(const fs::directory_name& P) : m_p(P) {}
virtual ~could_not_open() throw() {}
const fs::directory_name& what() const throw() { return m_p; }
private:
const fs::directory_name m_p;
};
enum child_type: unsigned short
{
Unknown,
OnlyFiles,
OnlyDirectories,
Mixed
};
directory() : any(){ std::cout << "dir::no arg" << std::endl; }
directory(const fs::directory_name& n, bool recursive) : any(n){ std::cout << "dir::string/bool"<<std::endl;}
directory(ptr p, const fs::directory_name& n, bool recursive) : any(p, n) { std::cout << "dir::parent/string/bool"<<std::endl;}
template<typename Head, typename... Tail>
directory(const Head& head, const Tail&... tail) : any(head, tail...) {std::cout<<"dir::variadic"<<std::endl;}
virtual ~directory() { }
inline bool is_file() const { return false; }
inline bool is_directory() const { return true; }
};
}
int main()
{
fs::directory::ptr A(new fs::directory());
fs::directory::ptr B(new fs::directory("ABC", true));
fs::directory::ptr C(new fs::directory(B, "DEF", true));
fs::directory::ptr D(new fs::directory("A", "B", "C"));
}