#ifndef _C4_STD_TUPLE_HPP_ #define _C4_STD_TUPLE_HPP_ /** @file tuple.hpp */ #ifndef C4CORE_SINGLE_HEADER #include "c4/format.hpp" #endif #include /** this is a work in progress */ #undef C4_TUPLE_TO_CHARS namespace c4 { #ifdef C4_TUPLE_TO_CHARS namespace detail { template< size_t Curr, class... Types > struct tuple_helper { static size_t do_cat(substr buf, std::tuple< Types... > const& tp) { size_t num = to_chars(buf, std::get(tp)); buf = buf.len >= num ? buf.sub(num) : substr{}; num += tuple_helper< Curr+1, Types... >::do_cat(buf, tp); return num; } static size_t do_uncat(csubstr buf, std::tuple< Types... > & tp) { size_t num = from_str_trim(buf, &std::get(tp)); if(num == csubstr::npos) return csubstr::npos; buf = buf.len >= num ? buf.sub(num) : substr{}; num += tuple_helper< Curr+1, Types... >::do_uncat(buf, tp); return num; } template< class Sep > static size_t do_catsep_more(substr buf, Sep const& sep, std::tuple< Types... > const& tp) { size_t ret = to_chars(buf, sep), num = ret; buf = buf.len >= ret ? buf.sub(ret) : substr{}; ret = to_chars(buf, std::get(tp)); num += ret; buf = buf.len >= ret ? buf.sub(ret) : substr{}; ret = tuple_helper< Curr+1, Types... >::do_catsep_more(buf, sep, tp); num += ret; return num; } template< class Sep > static size_t do_uncatsep_more(csubstr buf, Sep & sep, std::tuple< Types... > & tp) { size_t ret = from_str_trim(buf, &sep), num = ret; if(ret == csubstr::npos) return csubstr::npos; buf = buf.len >= ret ? buf.sub(ret) : substr{}; ret = from_str_trim(buf, &std::get(tp)); if(ret == csubstr::npos) return csubstr::npos; num += ret; buf = buf.len >= ret ? buf.sub(ret) : substr{}; ret = tuple_helper< Curr+1, Types... >::do_uncatsep_more(buf, sep, tp); if(ret == csubstr::npos) return csubstr::npos; num += ret; return num; } static size_t do_format(substr buf, csubstr fmt, std::tuple< Types... > const& tp) { auto pos = fmt.find("{}"); if(pos != csubstr::npos) { size_t num = to_chars(buf, fmt.sub(0, pos)); size_t out = num; buf = buf.len >= num ? buf.sub(num) : substr{}; num = to_chars(buf, std::get(tp)); out += num; buf = buf.len >= num ? buf.sub(num) : substr{}; num = tuple_helper< Curr+1, Types... >::do_format(buf, fmt.sub(pos + 2), tp); out += num; return out; } else { return format(buf, fmt); } } static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple< Types... > & tp) { auto pos = fmt.find("{}"); if(pos != csubstr::npos) { size_t num = pos; size_t out = num; buf = buf.len >= num ? buf.sub(num) : substr{}; num = from_str_trim(buf, &std::get(tp)); out += num; buf = buf.len >= num ? buf.sub(num) : substr{}; num = tuple_helper< Curr+1, Types... >::do_unformat(buf, fmt.sub(pos + 2), tp); out += num; return out; } else { return tuple_helper< sizeof...(Types), Types... >::do_unformat(buf, fmt, tp); } } }; /** @todo VS compilation fails for this class */ template< class... Types > struct tuple_helper< sizeof...(Types), Types... > { static size_t do_cat(substr /*buf*/, std::tuple const& /*tp*/) { return 0; } static size_t do_uncat(csubstr /*buf*/, std::tuple & /*tp*/) { return 0; } template< class Sep > static size_t do_catsep_more(substr /*buf*/, Sep const& /*sep*/, std::tuple const& /*tp*/) { return 0; } template< class Sep > static size_t do_uncatsep_more(csubstr /*buf*/, Sep & /*sep*/, std::tuple & /*tp*/) { return 0; } static size_t do_format(substr buf, csubstr fmt, std::tuple const& /*tp*/) { return to_chars(buf, fmt); } static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple const& /*tp*/) { return 0; } }; } // namespace detail template< class... Types > inline size_t cat(substr buf, std::tuple< Types... > const& tp) { return detail::tuple_helper< 0, Types... >::do_cat(buf, tp); } template< class... Types > inline size_t uncat(csubstr buf, std::tuple< Types... > & tp) { return detail::tuple_helper< 0, Types... >::do_uncat(buf, tp); } template< class Sep, class... Types > inline size_t catsep(substr buf, Sep const& sep, std::tuple< Types... > const& tp) { size_t num = to_chars(buf, std::cref(std::get<0>(tp))); buf = buf.len >= num ? buf.sub(num) : substr{}; num += detail::tuple_helper< 1, Types... >::do_catsep_more(buf, sep, tp); return num; } template< class Sep, class... Types > inline size_t uncatsep(csubstr buf, Sep & sep, std::tuple< Types... > & tp) { size_t ret = from_str_trim(buf, &std::get<0>(tp)), num = ret; if(ret == csubstr::npos) return csubstr::npos; buf = buf.len >= ret ? buf.sub(ret) : substr{}; ret = detail::tuple_helper< 1, Types... >::do_uncatsep_more(buf, sep, tp); if(ret == csubstr::npos) return csubstr::npos; num += ret; return num; } template< class... Types > inline size_t format(substr buf, csubstr fmt, std::tuple< Types... > const& tp) { return detail::tuple_helper< 0, Types... >::do_format(buf, fmt, tp); } template< class... Types > inline size_t unformat(csubstr buf, csubstr fmt, std::tuple< Types... > & tp) { return detail::tuple_helper< 0, Types... >::do_unformat(buf, fmt, tp); } #endif // C4_TUPLE_TO_CHARS } // namespace c4 #endif /* _C4_STD_TUPLE_HPP_ */