mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 14:25:37 +00:00
185 lines
5.8 KiB
C++
185 lines
5.8 KiB
C++
#ifndef _C4_STD_TUPLE_HPP_
|
|
#define _C4_STD_TUPLE_HPP_
|
|
|
|
/** @file tuple.hpp */
|
|
|
|
#ifndef C4CORE_SINGLE_HEADER
|
|
#include "c4/format.hpp"
|
|
#endif
|
|
|
|
#include <tuple>
|
|
|
|
/** 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<Curr>(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<Curr>(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<Curr>(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<Curr>(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<Curr>(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<Curr>(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<Types...> const& /*tp*/) { return 0; }
|
|
static size_t do_uncat(csubstr /*buf*/, std::tuple<Types...> & /*tp*/) { return 0; }
|
|
|
|
template< class Sep > static size_t do_catsep_more(substr /*buf*/, Sep const& /*sep*/, std::tuple<Types...> const& /*tp*/) { return 0; }
|
|
template< class Sep > static size_t do_uncatsep_more(csubstr /*buf*/, Sep & /*sep*/, std::tuple<Types...> & /*tp*/) { return 0; }
|
|
|
|
static size_t do_format(substr buf, csubstr fmt, std::tuple<Types...> const& /*tp*/)
|
|
{
|
|
return to_chars(buf, fmt);
|
|
}
|
|
|
|
static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple<Types...> 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_ */
|