vmap/libs/property.h

174 lines
4.4 KiB
C
Raw Normal View History

2020-11-17 11:16:16 +00:00
#ifndef INCLUDED_IMPORTEXPORT_H
#define INCLUDED_IMPORTEXPORT_H
#include "generic/callback.h"
#include "string/string.h"
template<class T>
struct Property {
2021-08-04 20:23:18 +00:00
// todo: just return T, don't use continuation passing style
Callback<void(const Callback<void(T)> &returnz)> get;
Callback<void(T value)> set;
2020-11-17 11:16:16 +00:00
};
// implementation
template<class Self, class T = Self>
struct PropertyImpl {
2021-08-04 20:23:18 +00:00
static void Export(const Self &self, const Callback<void(T)> &returnz) {
returnz(self);
}
2020-11-17 11:16:16 +00:00
2021-08-04 20:23:18 +00:00
static void Import(Self &self, T value) {
self = value;
}
2020-11-17 11:16:16 +00:00
};
namespace detail {
2021-08-04 20:23:18 +00:00
template<class I>
using propertyimpl_self = typename std::remove_reference<get_argument<decltype(&I::Import), 0> >::type;
2020-11-17 11:16:16 +00:00
2021-08-04 20:23:18 +00:00
template<class I>
using propertyimpl_other = get_argument<decltype(&I::Import), 1>;
2020-11-17 11:16:16 +00:00
2021-08-04 20:23:18 +00:00
template<class I>
using propertyimpl_other_free = get_argument<decltype(&I::Import), 0>;
2020-11-17 11:16:16 +00:00
}
// adaptor
template<
2021-08-04 20:23:18 +00:00
class Self,
class T = Self,
class I = PropertyImpl<Self, T>
>
2020-11-17 11:16:16 +00:00
struct PropertyAdaptor {
2021-08-04 20:23:18 +00:00
using Type = Self;
using Other = T;
2020-11-17 11:16:16 +00:00
2021-08-04 20:23:18 +00:00
using Get = ConstReferenceCaller<Self, void (const Callback<void (T)> &), I::Export>;
using Set = ReferenceCaller<Self, void (T), I::Import>;
2020-11-17 11:16:16 +00:00
};
template<
2021-08-04 20:23:18 +00:00
class T,
class I
>
2020-11-17 11:16:16 +00:00
struct PropertyAdaptorFree {
2021-08-04 20:23:18 +00:00
using Other = T;
2020-11-17 11:16:16 +00:00
2021-08-04 20:23:18 +00:00
using Get = FreeCaller<void (const Callback<void (T)> &), I::Export>;
using Set = FreeCaller<void (T), I::Import>;
2020-11-17 11:16:16 +00:00
};
// explicit full
template<class A>
Property<typename A::Other> make_property(typename A::Type &self) {
2021-08-04 20:23:18 +00:00
return {typename A::Get(self), typename A::Set(self)};
2020-11-17 11:16:16 +00:00
}
template<class A>
Property<typename A::Other> make_property() {
2021-08-04 20:23:18 +00:00
return {typename A::Get(), typename A::Set()};
2020-11-17 11:16:16 +00:00
}
// explicit impl
2021-08-04 20:23:18 +00:00
template<class I, class Self = detail::propertyimpl_self<I>, class T = detail::propertyimpl_other<I> >
2020-11-17 11:16:16 +00:00
using property_impl = PropertyAdaptor<Self, T, I>;
2021-08-04 20:23:18 +00:00
template<class I, class Self, class T = detail::propertyimpl_other<I> >
2020-11-17 11:16:16 +00:00
Property<T> make_property(Self &self) {
2021-08-04 20:23:18 +00:00
return make_property<property_impl<I> >(self);
2020-11-17 11:16:16 +00:00
}
2021-08-04 20:23:18 +00:00
template<class I, class T = detail::propertyimpl_other_free<I> >
2020-11-17 11:16:16 +00:00
using property_impl_free = PropertyAdaptorFree<T, I>;
2021-08-04 20:23:18 +00:00
template<class I, class T = detail::propertyimpl_other_free<I> >
2020-11-17 11:16:16 +00:00
Property<T> make_property() {
2021-08-04 20:23:18 +00:00
return make_property<property_impl_free<I> >();
2020-11-17 11:16:16 +00:00
}
// implicit
template<class Self, class T = Self>
Property<T> make_property(Self &self) {
2021-08-04 20:23:18 +00:00
return make_property<PropertyAdaptor<Self, T> >(self);
2020-11-17 11:16:16 +00:00
}
// chain
2021-01-16 15:46:35 +00:00
template<typename DST, typename SRC, typename X, typename A>
struct make_property_chain_I_1 {
2021-08-04 20:23:18 +00:00
static void ExportThunk(const Callback<void(DST)> &self, SRC value) {
PropertyImpl<SRC, DST>::Export(value, self);
}
static void Export(const X &self, const Callback<void(DST)> &returnz) {
A::Get::thunk_(self, ConstReferenceCaller<Callback<void(DST)>, void(SRC), ExportThunk>(returnz));
}
static void Import(X &self, DST value) {
SRC out;
PropertyImpl<SRC, DST>::Import(out, value);
A::Set::thunk_(self, out);
}
2021-01-16 15:46:35 +00:00
};
2020-11-17 11:16:16 +00:00
template<class I_Outer, class I_Inner>
2021-08-04 20:23:18 +00:00
Property<detail::propertyimpl_other<I_Outer> > make_property_chain(detail::propertyimpl_self<I_Inner> &it) {
using DST = detail::propertyimpl_other<I_Outer>;
using SRC = detail::propertyimpl_self<I_Outer>;
using X = detail::propertyimpl_self<I_Inner>;
using A = property_impl<I_Inner>;
using I = make_property_chain_I_1<DST, SRC, X, A>;
return make_property<PropertyAdaptor<X, DST, I> >(it);
2020-11-17 11:16:16 +00:00
}
2021-01-16 15:46:35 +00:00
template<typename DST, typename SRC, typename A>
struct make_property_chain_I_2 {
2021-08-04 20:23:18 +00:00
static void ExportThunk(const Callback<void(DST)> &self, SRC value) {
PropertyImpl<SRC, DST>::Export(value, self);
}
static void Export(const Callback<void(DST)> &returnz) {
A::Get::thunk_(nullptr, ConstReferenceCaller<Callback<void(DST)>, void(SRC), ExportThunk>(returnz));
}
static void Import(DST value) {
SRC out;
PropertyImpl<SRC, DST>::Import(out, value);
A::Set::thunk_(nullptr, out);
}
2021-01-16 15:46:35 +00:00
};
2020-11-17 11:16:16 +00:00
template<class I_Outer, class I_Inner>
2021-08-04 20:23:18 +00:00
Property<detail::propertyimpl_other<I_Outer> > make_property_chain() {
using DST = detail::propertyimpl_other<I_Outer>;
using SRC = detail::propertyimpl_self<I_Outer>;
2020-11-17 11:16:16 +00:00
2021-08-04 20:23:18 +00:00
using A = property_impl_free<I_Inner>;
using I = make_property_chain_I_2<DST, SRC, A>;
return make_property<PropertyAdaptorFree<DST, I> >();
2020-11-17 11:16:16 +00:00
}
// specializations
template<>
struct PropertyImpl<CopiedString, const char *> {
2021-08-04 20:23:18 +00:00
static void Export(const CopiedString &self, const Callback<void(const char *)> &returnz) {
returnz(self.c_str());
}
2020-11-17 11:16:16 +00:00
2021-08-04 20:23:18 +00:00
static void Import(CopiedString &self, const char *value) {
self = value;
}
2020-11-17 11:16:16 +00:00
};
#endif