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