forked from OctaForge/libostd
formatting of associative arrays
This commit is contained in:
parent
d883af001f
commit
48a6e1e59d
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "octa/algorithm.hh"
|
||||
#include "octa/string.hh"
|
||||
#include "octa/utility.hh"
|
||||
|
||||
namespace octa {
|
||||
|
||||
|
@ -383,6 +384,20 @@ namespace detail {
|
|||
template<typename T>
|
||||
using FmtRangeTest = decltype(test_fmt_range<T>(0));
|
||||
|
||||
template<typename R, typename ...A>
|
||||
static inline octa::Ptrdiff format_ritem(R &writer, octa::Size &fmtn,
|
||||
const char *fmt,
|
||||
const A &...args) {
|
||||
return format_impl(writer, fmtn, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename R, typename T, typename U>
|
||||
static inline octa::Ptrdiff format_ritem(R &writer, octa::Size &fmtn,
|
||||
const char *fmt,
|
||||
const octa::Pair<T, U> &pair) {
|
||||
return format_impl(writer, fmtn, fmt, pair.first, pair.second);
|
||||
}
|
||||
|
||||
template<typename R, typename T>
|
||||
static inline octa::Ptrdiff write_range(R &writer,
|
||||
const FormatSpec *fl,
|
||||
|
@ -398,7 +413,7 @@ namespace detail {
|
|||
octa::Ptrdiff ret = 0;
|
||||
octa::Size fmtn = 0;
|
||||
/* test first item */
|
||||
octa::Ptrdiff fret = format_impl(writer, fmtn, fl->rest(),
|
||||
octa::Ptrdiff fret = format_ritem(writer, fmtn, fl->rest(),
|
||||
range.front());
|
||||
if (fret < 0) return fret;
|
||||
ret += fret;
|
||||
|
@ -409,7 +424,7 @@ namespace detail {
|
|||
if (v != seplen)
|
||||
return -1;
|
||||
ret += seplen;
|
||||
fret = format_impl(writer, fmtn, fl->rest(), range.front());
|
||||
fret = format_ritem(writer, fmtn, fl->rest(), range.front());
|
||||
if (fret < 0) return fret;
|
||||
ret += fret;
|
||||
}
|
||||
|
@ -428,6 +443,14 @@ namespace detail {
|
|||
return -1;
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
typename = decltype(octa::to_string(octa::declval<T>()))
|
||||
> static octa::True test_fmt_tostr(int);
|
||||
template<typename> static octa::False test_fmt_tostr(...);
|
||||
|
||||
template<typename T>
|
||||
using FmtTostrTest = decltype(test_fmt_tostr<T>(0));
|
||||
|
||||
struct WriteSpec: octa::FormatSpec {
|
||||
WriteSpec(): octa::FormatSpec() {}
|
||||
WriteSpec(const char *fmt): octa::FormatSpec(fmt) {}
|
||||
|
@ -545,7 +568,7 @@ namespace detail {
|
|||
/* generic value */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write(R &writer, const T &val, octa::EnableIf<
|
||||
!octa::IsArithmetic<T>::value, bool
|
||||
!octa::IsArithmetic<T>::value && FmtTostrTest<T>::value, bool
|
||||
> = true) {
|
||||
if (this->spec != 's') {
|
||||
assert(false && "custom objects need '%s' format");
|
||||
|
@ -554,6 +577,15 @@ namespace detail {
|
|||
return write(writer, octa::to_string(val));
|
||||
}
|
||||
|
||||
/* generic failure case */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write(R &, const T &, octa::EnableIf<
|
||||
!octa::IsArithmetic<T>::value && !FmtTostrTest<T>::value, bool
|
||||
> = true) {
|
||||
assert(false && "value cannot be formatted");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* actual writer */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write_arg(R &writer, octa::Size idx, const T &val) {
|
||||
|
@ -693,7 +725,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R, typename ...A>
|
||||
static inline octa::Ptrdiff format(R &writer, octa::Size &fmtn,
|
||||
static inline octa::Ptrdiff format_impl(R &writer, octa::Size &fmtn,
|
||||
const char *fmt) {
|
||||
octa::Size written = 0;
|
||||
octa::detail::WriteSpec spec(fmt);
|
||||
|
|
|
@ -452,9 +452,13 @@ template<typename T> struct ToString {
|
|||
!octa::IsScalar<U>::value, bool> = true
|
||||
) {
|
||||
String ret("{");
|
||||
ret += concat(octa::iter(v), ", ", ToString<octa::RangeReference<
|
||||
decltype(octa::iter(v))
|
||||
>>());
|
||||
ret += concat(octa::iter(v), ", ", ToString<
|
||||
octa::RemoveCv<
|
||||
octa::RemoveReference<
|
||||
octa::RangeReference<decltype(octa::iter(v))>
|
||||
>
|
||||
>
|
||||
>());
|
||||
ret += "}";
|
||||
return ret;
|
||||
}
|
||||
|
@ -468,9 +472,7 @@ template<typename T> struct ToString {
|
|||
}
|
||||
|
||||
String operator()(const T &v) const {
|
||||
return to_str<octa::RemoveCv<
|
||||
octa::RemoveReference<T>
|
||||
>>(v);
|
||||
return to_str(v);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -569,20 +571,17 @@ template<typename T, typename U> struct ToString<octa::Pair<T, U>> {
|
|||
using Result = String;
|
||||
String operator()(const Argument &v) {
|
||||
String ret("{");
|
||||
ret += ToString<octa::RemoveCv<octa::RemoveReference<T>>>()
|
||||
(v.first);
|
||||
ret += ToString<T>()(v.first);
|
||||
ret += ", ";
|
||||
ret += ToString<octa::RemoveCv<octa::RemoveReference<U>>>()
|
||||
(v.second);
|
||||
ret += ToString<U>()(v.second);
|
||||
ret += "}";
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename T, typename = decltype(ToString<T>()(octa::declval<T>()))>
|
||||
String to_string(const T &v) {
|
||||
return ToString<octa::RemoveCv<octa::RemoveReference<T>>>
|
||||
()(v);
|
||||
return ToString<T>()(v);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
Loading…
Reference in a new issue