// TODO: Replace `cout, printf` with sprintf&fputs and custom buffers #ifndef _TABLE_H #define _TABLE_H #include "types.h" #include "vector_type.hpp" #include template class vector_type; template <> class vector_type; #ifdef _MSC_VER namespace types { enum Type_t; template struct Types; template struct Coercion; } #endif template class ColView; template class ColRef : public vector_type<_Ty> { public: const char* name; types::Type_t ty = types::ERROR; ColRef(const uint32_t& size, const char* name = "") : vector_type<_Ty>(size), name(name) {} ColRef(const char* name) : name(name) {} void init() { ty = types::Types<_Ty>::getType(); this->size = this->capacity = 0; this->container = 0; } ColRef(const char* name, types::Type_t ty) : name(name), ty(ty) {} using vector_type<_Ty>::operator[]; using vector_type<_Ty>::operator=; ColView<_Ty> operator [](const vector_type&idxs) const { return ColView<_Ty>(*this, idxs); } template ColRef scast(); }; template class ColView { public: const vector_type& idxs; const ColRef<_Ty>& orig; const uint32_t& size; ColView(const ColRef<_Ty>& orig, const vector_type& idxs) : orig(orig), idxs(idxs), size(idxs.size) {} ColView(const ColView<_Ty>& orig, const vector_type& idxs) : orig(orig.orig), idxs(idxs), size(idxs.size) { for (uint32_t i = 0; i < size; ++i) idxs[i] = orig.idxs[idxs[i]]; } _Ty& operator [](const uint32_t& i) const { return orig[idxs[i]]; } struct Iterator_t { const uint32_t* val; const ColRef<_Ty>& orig; constexpr Iterator_t(const uint32_t* val, const ColRef<_Ty>& orig) noexcept : val(val), orig(orig) {} _Ty& operator*() { return orig[*val]; } bool operator != (const Iterator_t& rhs) { return rhs.val != val; } Iterator_t& operator++ () { ++val; return *this; } Iterator_t operator++ (int) { Iterator_t tmp = *this; ++val; return tmp; } }; Iterator_t begin() const { return Iterator_t(idxs.begin(), orig); } Iterator_t end() const { return Iterator_t(idxs.end(), orig); } }; template template inline ColRef ColRef<_Ty>::scast() { this->ty = types::Types::getType(); return *(ColRef *)this; } using uColRef = ColRef; template struct TableInfo; template struct TableView; template constexpr inline auto& get(const TableInfo<_Types...>& table) noexcept { if constexpr (order) return *(ColRef>> *) & (table.colrefs[_Index]); else return *(ColRef>> *) & (table.colrefs[-1-_Index]); } template constexpr inline ColRef>>& get(const TableView<_Types...>& table) noexcept { return *(ColRef>> *) & (table.info.colrefs[_Index]); } template struct TableView; template struct TableInfo { const char* name; ColRef* colrefs; uint32_t n_cols; typedef std::tuple tuple_type; void print(const char* __restrict sep, const char* __restrict end) const; template typename std::enable_if::type print_impl(const uint32_t& i, const char* __restrict sep = " ") const; template typename std::enable_if::type print_impl(const uint32_t& i, const char* __restrict sep = " ") const; template struct GetTypes { typedef typename std::tuple::type ...> type; }; template using getRecordType = typename GetTypes::type; TableInfo(const char* name, uint32_t n_cols); template inline void materialize(const vector_type& idxs, TableInfo* tbl = nullptr) { // inplace materialize if constexpr(prog == 0) tbl = 0 ? this : tbl; if constexpr (prog == sizeof...(Types)) return; else { auto& col = get(*this); auto new_col = decays{idxs.size}; for(uint32_t i = 0; i < idxs.size; ++i) new_col[i] = col[idxs[i]]; get(*tbl) = new_col; materialize(); } } inline TableInfo* materialize_copy(const vector_type& idxs) { auto tbl = new TableInfo(this->name, sizeof...(Types)); materialize<0>(idxs, tbl); return tbl; } template inline vector_type* order_by() { vector_type* ord = new vector_type(colrefs[0].size); for (uint32_t i = 0; i < colrefs[0].size; ++i) (*ord)[i] = i; std::sort(ord->begin(), ord->end(), [this](const uint32_t& lhs, const uint32_t& rhs) { return std::forward_as_tuple((cols >= 0 ? get= 0)>(*this)[lhs] : -get= 0)>(*this)[lhs]) ...) < std::forward_as_tuple((cols >= 0 ? get= 0)>(*this)[rhs] : -get= 0)>(*this)[rhs]) ...); }); return ord; } template auto order_by_view () { return TableView(order_by(), *this); } }; template struct TableView { const vector_type* idxs; const TableInfo& info; constexpr TableView(const vector_type* idxs, const TableInfo& info) noexcept : idxs(idxs), info(info) {} void print(const char* __restrict sep, const char* __restrict end) const; template typename std::enable_if::type print_impl(const uint32_t& i, const char* __restrict sep = " ") const; template typename std::enable_if < j < sizeof...(Types) - 1, void>::type print_impl(const uint32_t& i, const char* __restrict sep = " ") const; ~TableView() { delete idxs; } }; template constexpr static inline bool is_vector(const ColRef&) { return true; } template constexpr static inline bool is_vector(const vector_type&) { return true; } template constexpr static inline bool is_vector(const T&) { return false; } template TableInfo::TableInfo(const char* name, uint32_t n_cols) : name(name), n_cols(n_cols) { this->colrefs = (ColRef*)malloc(sizeof(ColRef) * n_cols); } template template inline typename std::enable_if::type TableView::print_impl(const uint32_t& i, const char* __restrict sep) const { std::cout << (get(*this))[(*idxs)[i]]; } template template inline typename std::enable_if < j < sizeof...(Types) - 1, void>::type TableView::print_impl(const uint32_t& i, const char* __restrict sep) const { std::cout << (get(*this))[(*idxs)[i]] << sep; print_impl(i, sep); } template inline void TableView::print(const char* __restrict sep, const char* __restrict end) const { int n_rows = 0; if (info.colrefs[0].size > 0) n_rows = info.colrefs[0].size; for (int i = 0; i < n_rows; ++i) { print_impl(i); std::cout << end; } } template template inline typename std::enable_if::type TableInfo::print_impl(const uint32_t& i, const char* __restrict sep) const { std::cout << (get(*this))[i]; } template template inline typename std::enable_if::type TableInfo::print_impl(const uint32_t& i, const char* __restrict sep) const { std::cout << (get(*this))[i] << sep; print_impl(i, sep); } template inline void TableInfo::print(const char* __restrict sep, const char* __restrict end) const { int n_rows = 0; if (n_cols > 0 && colrefs[0].size > 0) n_rows = colrefs[0].size; for (int i = 0; i < n_rows; ++i) { print_impl(i); std::cout << end; } } template class VT> VT::type> operator -(const VT& lhs, const VT& rhs) { auto ret = VT::type>(lhs.size, ""); for (int i = 0; i < lhs.size; ++i) ret.container[i] = lhs.container[i] - rhs.container[i]; return ret; } template class VT> VT::type> operator -(const VT& lhs, const T2& rhs) { auto ret = VT::type>(lhs.size, ""); for (int i = 0; i < lhs.size; ++i) ret.container[i] = lhs.container[i] - rhs; return ret; } template class VT> VT::type> operator +(const VT& lhs, const VT& rhs) { auto ret = VT::type>(lhs.size, ""); for (int i = 0; i < lhs.size; ++i) ret.container[i] = lhs.container[i] + rhs.container[i]; return ret; } template class VT> VT::type> operator +(const VT& lhs, const T2& rhs) { auto ret = VT::type>(lhs.size, ""); for (int i = 0; i < lhs.size; ++i) ret.container[i] = lhs.container[i] + rhs; return ret; } template class VT> VT::type> operator *(const VT& lhs, const VT& rhs) { auto ret = VT::type>(lhs.size, ""); for (int i = 0; i < lhs.size; ++i) ret.container[i] = lhs.container[i] * rhs.container[i]; return ret; } template class VT> VT::type> operator *(const VT& lhs, const T2& rhs) { auto ret = VT::type>(lhs.size, ""); for (int i = 0; i < lhs.size; ++i) ret.container[i] = lhs.container[i] * rhs; return ret; } template class VT> VT::type> operator /(const VT& lhs, const VT& rhs) { auto ret = VT::type>(lhs.size, ""); for (int i = 0; i < lhs.size; ++i) ret.container[i] = lhs.container[i] / rhs.container[i]; return ret; } template class VT> VT::type> operator /(const VT& lhs, const T2& rhs) { auto ret = VT::type>(lhs.size, ""); for (int i = 0; i < lhs.size; ++i) ret.container[i] = lhs.container[i] / rhs; return ret; } template void print(const TableInfo& v, const char* delimiter = " ", const char* endline = "\n") { v.print(delimiter, endline); } template void print(const TableView& v, const char* delimiter = " ", const char* endline = "\n") { v.print(delimiter, endline); } template void print(const T& v, const char* delimiter = " ") { std::cout<< v; // printf(types::printf_str[types::Types::getType()], v); } template void inline print_impl(const T& v, const char* delimiter, const char* endline) { for (const auto& vi : v) { print(vi); std::cout << delimiter; // printf("%s", delimiter); } std::cout << endline; //printf("%s", endline); } template class VT> typename std::enable_if, TableInfo>::value>::type print(const VT& v, const char* delimiter = " ", const char* endline = "\n") { print_impl(v, delimiter, endline); } #endif