tuple.hpp (5948B)
1 #ifndef _C4_STD_TUPLE_HPP_ 2 #define _C4_STD_TUPLE_HPP_ 3 4 /** @file tuple.hpp */ 5 6 #ifndef C4CORE_SINGLE_HEADER 7 #include "c4/format.hpp" 8 #endif 9 10 #include <tuple> 11 12 /** this is a work in progress */ 13 #undef C4_TUPLE_TO_CHARS 14 15 namespace c4 { 16 17 #ifdef C4_TUPLE_TO_CHARS 18 namespace detail { 19 20 template< size_t Curr, class... Types > 21 struct tuple_helper 22 { 23 static size_t do_cat(substr buf, std::tuple< Types... > const& tp) 24 { 25 size_t num = to_chars(buf, std::get<Curr>(tp)); 26 buf = buf.len >= num ? buf.sub(num) : substr{}; 27 num += tuple_helper< Curr+1, Types... >::do_cat(buf, tp); 28 return num; 29 } 30 31 static size_t do_uncat(csubstr buf, std::tuple< Types... > & tp) 32 { 33 size_t num = from_str_trim(buf, &std::get<Curr>(tp)); 34 if(num == csubstr::npos) return csubstr::npos; 35 buf = buf.len >= num ? buf.sub(num) : substr{}; 36 num += tuple_helper< Curr+1, Types... >::do_uncat(buf, tp); 37 return num; 38 } 39 40 template< class Sep > 41 static size_t do_catsep_more(substr buf, Sep const& sep, std::tuple< Types... > const& tp) 42 { 43 size_t ret = to_chars(buf, sep), num = ret; 44 buf = buf.len >= ret ? buf.sub(ret) : substr{}; 45 ret = to_chars(buf, std::get<Curr>(tp)); 46 num += ret; 47 buf = buf.len >= ret ? buf.sub(ret) : substr{}; 48 ret = tuple_helper< Curr+1, Types... >::do_catsep_more(buf, sep, tp); 49 num += ret; 50 return num; 51 } 52 53 template< class Sep > 54 static size_t do_uncatsep_more(csubstr buf, Sep & sep, std::tuple< Types... > & tp) 55 { 56 size_t ret = from_str_trim(buf, &sep), num = ret; 57 if(ret == csubstr::npos) return csubstr::npos; 58 buf = buf.len >= ret ? buf.sub(ret) : substr{}; 59 ret = from_str_trim(buf, &std::get<Curr>(tp)); 60 if(ret == csubstr::npos) return csubstr::npos; 61 num += ret; 62 buf = buf.len >= ret ? buf.sub(ret) : substr{}; 63 ret = tuple_helper< Curr+1, Types... >::do_uncatsep_more(buf, sep, tp); 64 if(ret == csubstr::npos) return csubstr::npos; 65 num += ret; 66 return num; 67 } 68 69 static size_t do_format(substr buf, csubstr fmt, std::tuple< Types... > const& tp) 70 { 71 auto pos = fmt.find("{}"); 72 if(pos != csubstr::npos) 73 { 74 size_t num = to_chars(buf, fmt.sub(0, pos)); 75 size_t out = num; 76 buf = buf.len >= num ? buf.sub(num) : substr{}; 77 num = to_chars(buf, std::get<Curr>(tp)); 78 out += num; 79 buf = buf.len >= num ? buf.sub(num) : substr{}; 80 num = tuple_helper< Curr+1, Types... >::do_format(buf, fmt.sub(pos + 2), tp); 81 out += num; 82 return out; 83 } 84 else 85 { 86 return format(buf, fmt); 87 } 88 } 89 90 static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple< Types... > & tp) 91 { 92 auto pos = fmt.find("{}"); 93 if(pos != csubstr::npos) 94 { 95 size_t num = pos; 96 size_t out = num; 97 buf = buf.len >= num ? buf.sub(num) : substr{}; 98 num = from_str_trim(buf, &std::get<Curr>(tp)); 99 out += num; 100 buf = buf.len >= num ? buf.sub(num) : substr{}; 101 num = tuple_helper< Curr+1, Types... >::do_unformat(buf, fmt.sub(pos + 2), tp); 102 out += num; 103 return out; 104 } 105 else 106 { 107 return tuple_helper< sizeof...(Types), Types... >::do_unformat(buf, fmt, tp); 108 } 109 } 110 111 }; 112 113 /** @todo VS compilation fails for this class */ 114 template< class... Types > 115 struct tuple_helper< sizeof...(Types), Types... > 116 { 117 static size_t do_cat(substr /*buf*/, std::tuple<Types...> const& /*tp*/) { return 0; } 118 static size_t do_uncat(csubstr /*buf*/, std::tuple<Types...> & /*tp*/) { return 0; } 119 120 template< class Sep > static size_t do_catsep_more(substr /*buf*/, Sep const& /*sep*/, std::tuple<Types...> const& /*tp*/) { return 0; } 121 template< class Sep > static size_t do_uncatsep_more(csubstr /*buf*/, Sep & /*sep*/, std::tuple<Types...> & /*tp*/) { return 0; } 122 123 static size_t do_format(substr buf, csubstr fmt, std::tuple<Types...> const& /*tp*/) 124 { 125 return to_chars(buf, fmt); 126 } 127 128 static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple<Types...> const& /*tp*/) 129 { 130 return 0; 131 } 132 }; 133 134 } // namespace detail 135 136 template< class... Types > 137 inline size_t cat(substr buf, std::tuple< Types... > const& tp) 138 { 139 return detail::tuple_helper< 0, Types... >::do_cat(buf, tp); 140 } 141 142 template< class... Types > 143 inline size_t uncat(csubstr buf, std::tuple< Types... > & tp) 144 { 145 return detail::tuple_helper< 0, Types... >::do_uncat(buf, tp); 146 } 147 148 template< class Sep, class... Types > 149 inline size_t catsep(substr buf, Sep const& sep, std::tuple< Types... > const& tp) 150 { 151 size_t num = to_chars(buf, std::cref(std::get<0>(tp))); 152 buf = buf.len >= num ? buf.sub(num) : substr{}; 153 num += detail::tuple_helper< 1, Types... >::do_catsep_more(buf, sep, tp); 154 return num; 155 } 156 157 template< class Sep, class... Types > 158 inline size_t uncatsep(csubstr buf, Sep & sep, std::tuple< Types... > & tp) 159 { 160 size_t ret = from_str_trim(buf, &std::get<0>(tp)), num = ret; 161 if(ret == csubstr::npos) return csubstr::npos; 162 buf = buf.len >= ret ? buf.sub(ret) : substr{}; 163 ret = detail::tuple_helper< 1, Types... >::do_uncatsep_more(buf, sep, tp); 164 if(ret == csubstr::npos) return csubstr::npos; 165 num += ret; 166 return num; 167 } 168 169 template< class... Types > 170 inline size_t format(substr buf, csubstr fmt, std::tuple< Types... > const& tp) 171 { 172 return detail::tuple_helper< 0, Types... >::do_format(buf, fmt, tp); 173 } 174 175 template< class... Types > 176 inline size_t unformat(csubstr buf, csubstr fmt, std::tuple< Types... > & tp) 177 { 178 return detail::tuple_helper< 0, Types... >::do_unformat(buf, fmt, tp); 179 } 180 #endif // C4_TUPLE_TO_CHARS 181 182 } // namespace c4 183 184 #endif /* _C4_STD_TUPLE_HPP_ */