#include <cstdint>
#include <array>
#include <iostream>
#include <tuple>
#include <type_traits>
/////////////////////////
#if 1 // multiple dispatch
// sequence of size_t // not in C++11
template <std::size_t ...> struct index_sequence {};
// Create index_sequence<0, >
template <std::size_t N, std::size_t ...Is>
struct make_index_sequence : make_index_sequence <N - 1, N - 1, Is... > {};
template <std::size_t ... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
// Generic IVisitor
// Do: using MyIVisitor = IVisitorTs<Child1, Child2, ...>
template <typename ... Ts> class IVisitorTs;
template <typename T, typename ... Ts>
class IVisitorTs<T, Ts...> : public IVisitorTs<Ts...>
{
public:
using tuple_type = std::tuple<T, Ts...>;
using IVisitorTs<Ts...>::visit;
virtual void visit(const T& t) = 0;
};
template <typename T> class IVisitorTs<T>
{
public:
using tuple_type = std::tuple<T>;
virtual void visit(const T& t) = 0;
};
namespace detail {
// retrieve the index of T in Ts...
template <typename T, typename ... Ts> struct get_index;
template <typename T, typename ... Ts>
struct get_index<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
template <typename T, typename Tail, typename ... Ts>
struct get_index<T, Tail, Ts...> :
std::integral_constant < std::size_t, 1 + get_index<T, Ts...>::value > {};
// retrieve the index of T in Tuple<Ts...>
template <typename T, typename Tuple> struct get_index_in_tuple;
template <typename T, template <typename...> class C, typename ... Ts>
struct get_index_in_tuple<T, C<Ts...>> : get_index<T, Ts...> {};
// get element of a multiarray
template <std::size_t I>
struct multi_array_getter
{
template <typename T, std::size_t N>
static constexpr auto get(const T& a, const std::array<std::size_t, N>& index)
-> decltype(multi_array_getter<I - 1>::get(a[index[N - I]], index))
{
return multi_array_getter<I - 1>::get(a[index[N - I]], index);
}
};
template <>
struct multi_array_getter<0>
{
template <typename T, std::size_t N>
static constexpr auto get(const T& a, const std::array<std::size_t, N>& index)
-> decltype(a)
{
return a;
}
};
// Provide an implementation of visitor
// by forwarding to C implementation (which may be non virtual)
template <typename IVisitor, typename C, typename...Ts> struct IVisitorImpl;
template <typename IVisitor, typename C, typename T, typename...Ts>
struct IVisitorImpl<IVisitor, C, T, Ts...> : IVisitorImpl<IVisitor, C, Ts...>
{
virtual void visit(const T& t) override { C::visit(t); }
};
template <typename IVisitor, typename C, typename T>
struct IVisitorImpl<IVisitor, C, T> : IVisitor, C
{
virtual void visit(const T& t) override { C::visit(t); }
};
// helper to expand child type to IVisitorImpl
template <typename IVisitor, typename C>
struct IVisitorImplType;
template <typename ... Ts, typename C>
struct IVisitorImplType<IVisitorTs<Ts...>, C>
{
using type = IVisitorImpl<IVisitorTs<Ts...>, C, Ts...>;
};
// Create an multi array of pointer of function
// (with all combinaisons of overload).
template <typename Ret, typename F, typename Arg>
class GetAllOverload
{
private:
template <typename...Ts>
struct Functor
{
// function which will be in array.
static Ret call(F&f, const Arg& arg)
{
return call_helper(f, arg, make_index_sequence<sizeof...(Ts)>());
}
private:
// The final dispatched function
template <std::size_t ... Is>
static Ret call_helper(F&f, const Arg& arg, index_sequence<Is...>)
{
using RetTuple = std::tuple<Ts&...>;
// static cast is suffisant if arg is the abstract type
// when given arg is concrete type, reinterpret_cast is required.
// TODO: build a smaller table with only possible value to avoid that
return f(reinterpret_cast<typename std::tuple_element<Is, RetTuple>::type>(std::get<Is>(arg))...);
}
};
// helper class to create the multi array of function pointer
template <std::size_t N, typename Tuple, typename...Ts>
struct Builder;
template <typename...Ts, typename...Ts2>
struct Builder<1, std::tuple<Ts...>, Ts2...>
{
using RetType = std::array<Ret (*)(F&, const Arg&), sizeof...(Ts)>;
static constexpr RetType build()
{
return RetType{ &Functor<Ts2..., Ts>::call... };
}
};
template <std::size_t N, typename ...Ts, typename...Ts2>
struct Builder<N, std::tuple<Ts...>, Ts2...>
{
template <typename T>
using RecType = Builder<N - 1, std::tuple<Ts...>, Ts2..., T>;
using T0 = typename std::tuple_element<0, std::tuple<Ts...>>::type;
using RetType = std::array<decltype(RecType<T0>::build()), sizeof...(Ts)>;
static constexpr RetType build() {
return RetType{ RecType<Ts>::build()... };
}
};
public:
template <std::size_t N, typename VisitorTuple>
static constexpr auto get()
-> decltype(Builder<N, VisitorTuple>::build())
{
return Builder<N, VisitorTuple>::build();
}
};
template <typename Ret, typename IVisitor, typename F, std::size_t N>
class dispatcher
{
private:
std::array<std::size_t, N> index;
struct visitorCallImpl
{
template <typename T>
void visit(const T&) const
{
*index = get_index_in_tuple<T, IVisitor>::value;
}
void setIndexPtr(std::size_t& index) { this->index = &index; }
private:
std::size_t* index = nullptr;
};
template <std::size_t I, typename Tuple>
void set_index(const Tuple&t)
{
using VisitorType = typename IVisitorImplType<IVisitor, visitorCallImpl>::type;
VisitorType visitor;
visitor.setIndexPtr(index[I]);
std::get<I>(t).accept(visitor);
}
public:
template <typename Tuple, std::size_t ... Is>
Ret operator () (F&& f, const Tuple&t, index_sequence<Is...>)
{
const int dummy[] = {(set_index<Is>(t), 0)...};
static_cast<void>(dummy); // silent the warning unused varaible
constexpr auto a = GetAllOverload<Ret, F&&, Tuple>::
template get<sizeof...(Is), typename IVisitor::tuple_type>();
auto func = multi_array_getter<N>::get(a, index);
return (*func)(f, t);
}
};
} // namespace detail
template <typename Ret, typename Visitor, typename F, typename ... Ts>
Ret dispatch(F&& f, Ts&...args)
{
constexpr std::size_t size = sizeof...(Ts);
detail::dispatcher<Ret, Visitor, F&&, size> d;
return d(std::forward<F>(f), std::tie(args...), make_index_sequence<size>());
}
#endif // multiple dispatch
#if 1 // multiple dispatch usage
struct A;
struct B;
struct C;
struct D;
using IAVisitor = IVisitorTs<A, B, C, D>;
struct A {
virtual ~A() = default;
virtual void accept(IAVisitor& v) const { v.visit(*this); }
};
struct B : A {
virtual void accept(IAVisitor& v) const override { v.visit(*this); }
};
struct C : A {
virtual void accept(IAVisitor& v) const override { v.visit(*this); }
};
struct D : A {
virtual void accept(IAVisitor& v) const override { v.visit(*this); }
};
class Object {
public:
virtual double foo (A*, A*) { std::cout << "Object::foo A,A\n"; return 3.14; }
virtual double foo (B*, B*) { std::cout << "Object::foo B,B\n"; return 3.14; }
virtual double foo (B*, C*) { std::cout << "Object::foo B,C\n"; return 3.14; }
virtual double foo (C*, B*) { std::cout << "Object::foo C,B\n"; return 3.14; }
virtual double foo (C*, C*) { std::cout << "Object::foo C,C\n"; return 3.14; }
virtual char foo (A*, A*, A*) const { std::cout << "Object::foo A,A,A\n"; return '&'; }
virtual char foo (C*, B*, D*) const { std::cout << "Object::foo C,B,D\n"; return '!'; } // Overload of foo with three arguments.
virtual void bar (A*, A*, A*) const { std::cout << "Object::bar A,A,A\n"; }
virtual void bar (B*, B*, B*) const { std::cout << "Object::bar B,B,B\n"; }
virtual void bar (B*, C*, B*) const { std::cout << "Object::bar B,C,B\n"; }
virtual void bar (B*, C*, C*) const { std::cout << "Object::bar B,C,C\n"; }
virtual void bar (B*, C*, D*) const { std::cout << "Object::bar B,C,D\n"; }
virtual void bar (C*, B*, D*) const { std::cout << "Object::bar C,B,D\n"; }
virtual void bar (C*, C*, C*) const { std::cout << "Object::bar C,C,C\n"; }
virtual void bar (D*, B*, C*) const { std::cout << "Object::bar D,B,C\n"; }
double fooMultipleDispatch (A*, A*);
char fooMultipleDispatch (A*, A*, A*);
};
class FooDispatcher
{
public:
explicit FooDispatcher(Object& object) : object(object) {}
template <typename T1, typename T2>
double operator() (T1& a1, T2& a2) const
{
return object.foo(&a1, &a2);
}
template <typename T1, typename T2, typename T3>
char operator() (T1& a1, T2& a2, T3& a3) const
{
return object.foo(&a1, &a2, &a3);
}
private:
Object& object;
};
double Object::fooMultipleDispatch (A* a1, A* a2)
{
return dispatch<double, IAVisitor>(FooDispatcher(*this), *a1, *a2);
}
char Object::fooMultipleDispatch (A* a1, A* a2, A* a3)
{
return dispatch<char, IAVisitor>(FooDispatcher(*this), *a1, *a2, *a3);
}
int main() {
A a_a;
B a_b;
C a_c;
D a_d;
A* a[] = {&a_b, &a_c, &a_d, &a_a};
Object object;
double d = object.foo (a[0], a[1]); // Object::foo A,A (no multiple dispatch)
d = object.fooMultipleDispatch (a[0], a[1]); // Object::foo B,C
std::cout << "d = " << d << std::endl; // 3.14
object.fooMultipleDispatch (a[0], a[3]); // B,A -> so best match is Object::foo A,A
const char k = object.fooMultipleDispatch (a[1], a[0], a[2]); // Object::foo C,B,D
std::cout << "k = " << k << std::endl; // !
}
#endif // multiple dispatch usage
I2luY2x1ZGUgPGNzdGRpbnQ+CiNpbmNsdWRlIDxhcnJheT4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDx0eXBlX3RyYWl0cz4KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCiNpZiAxIC8vIG11bHRpcGxlIGRpc3BhdGNoCgovLyBzZXF1ZW5jZSBvZiBzaXplX3QgLy8gbm90IGluIEMrKzExCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCAuLi4+IHN0cnVjdCBpbmRleF9zZXF1ZW5jZSB7fTsKCi8vIENyZWF0ZSBpbmRleF9zZXF1ZW5jZTwwLCA+CnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBOLCBzdGQ6OnNpemVfdCAuLi5Jcz4Kc3RydWN0IG1ha2VfaW5kZXhfc2VxdWVuY2UgOiBtYWtlX2luZGV4X3NlcXVlbmNlIDxOIC0gMSwgTiAtIDEsIElzLi4uID4ge307Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgLi4uIElzPgpzdHJ1Y3QgbWFrZV9pbmRleF9zZXF1ZW5jZTwwLCBJcy4uLj4gOiBpbmRleF9zZXF1ZW5jZTxJcy4uLj4ge307CgovLyBHZW5lcmljIElWaXNpdG9yCi8vIERvOiB1c2luZyBNeUlWaXNpdG9yID0gSVZpc2l0b3JUczxDaGlsZDEsIENoaWxkMiwgLi4uPgp0ZW1wbGF0ZSA8dHlwZW5hbWUgLi4uIFRzPiBjbGFzcyBJVmlzaXRvclRzOwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIC4uLiBUcz4KY2xhc3MgSVZpc2l0b3JUczxULCBUcy4uLj4gOiBwdWJsaWMgSVZpc2l0b3JUczxUcy4uLj4KewpwdWJsaWM6CiAgICB1c2luZyB0dXBsZV90eXBlID0gc3RkOjp0dXBsZTxULCBUcy4uLj47CiAgICB1c2luZyBJVmlzaXRvclRzPFRzLi4uPjo6dmlzaXQ7CgogICAgdmlydHVhbCB2b2lkIHZpc2l0KGNvbnN0IFQmIHQpID0gMDsKfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPiBjbGFzcyBJVmlzaXRvclRzPFQ+CnsKcHVibGljOgogICAgdXNpbmcgdHVwbGVfdHlwZSA9IHN0ZDo6dHVwbGU8VD47CgogICAgdmlydHVhbCB2b2lkIHZpc2l0KGNvbnN0IFQmIHQpID0gMDsKfTsKCm5hbWVzcGFjZSBkZXRhaWwgewoKLy8gcmV0cmlldmUgdGhlIGluZGV4IG9mIFQgaW4gVHMuLi4KdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIC4uLiBUcz4gc3RydWN0IGdldF9pbmRleDsKCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSAuLi4gVHM+CnN0cnVjdCBnZXRfaW5kZXg8VCwgVCwgVHMuLi4+IDogc3RkOjppbnRlZ3JhbF9jb25zdGFudDxzdGQ6OnNpemVfdCwgMD4ge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVGFpbCwgIHR5cGVuYW1lIC4uLiBUcz4Kc3RydWN0IGdldF9pbmRleDxULCBUYWlsLCBUcy4uLj4gOgogICAgICAgIHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQgPCBzdGQ6OnNpemVfdCwgMSArIGdldF9pbmRleDxULCBUcy4uLj46OnZhbHVlID4ge307CgovLyByZXRyaWV2ZSB0aGUgaW5kZXggb2YgVCBpbiBUdXBsZTxUcy4uLj4KdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFR1cGxlPiBzdHJ1Y3QgZ2V0X2luZGV4X2luX3R1cGxlOwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgQywgdHlwZW5hbWUgLi4uIFRzPgpzdHJ1Y3QgZ2V0X2luZGV4X2luX3R1cGxlPFQsIEM8VHMuLi4+PiA6IGdldF9pbmRleDxULCBUcy4uLj4ge307CgovLyBnZXQgZWxlbWVudCBvZiBhIG11bHRpYXJyYXkKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IEk+CnN0cnVjdCBtdWx0aV9hcnJheV9nZXR0ZXIKewogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHN0ZDo6c2l6ZV90IE4+CiAgICBzdGF0aWMgY29uc3RleHByIGF1dG8gZ2V0KGNvbnN0IFQmIGEsIGNvbnN0IHN0ZDo6YXJyYXk8c3RkOjpzaXplX3QsIE4+JiBpbmRleCkKICAgIC0+IGRlY2x0eXBlKG11bHRpX2FycmF5X2dldHRlcjxJIC0gMT46OmdldChhW2luZGV4W04gLSBJXV0sIGluZGV4KSkKICAgIHsKICAgICAgICByZXR1cm4gbXVsdGlfYXJyYXlfZ2V0dGVyPEkgLSAxPjo6Z2V0KGFbaW5kZXhbTiAtIEldXSwgaW5kZXgpOwogICAgfQp9OwoKdGVtcGxhdGUgPD4Kc3RydWN0IG11bHRpX2FycmF5X2dldHRlcjwwPgp7CiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgc3RkOjpzaXplX3QgTj4KICAgIHN0YXRpYyBjb25zdGV4cHIgYXV0byBnZXQoY29uc3QgVCYgYSwgY29uc3Qgc3RkOjphcnJheTxzdGQ6OnNpemVfdCwgTj4mIGluZGV4KQogICAgLT4gZGVjbHR5cGUoYSkKICAgIHsKICAgICAgICByZXR1cm4gYTsKICAgIH0KfTsKCi8vIFByb3ZpZGUgYW4gaW1wbGVtZW50YXRpb24gb2YgdmlzaXRvcgovLyBieSBmb3J3YXJkaW5nIHRvIEMgaW1wbGVtZW50YXRpb24gKHdoaWNoIG1heSBiZSBub24gdmlydHVhbCkKdGVtcGxhdGUgPHR5cGVuYW1lIElWaXNpdG9yLCB0eXBlbmFtZSBDLCB0eXBlbmFtZS4uLlRzPiBzdHJ1Y3QgSVZpc2l0b3JJbXBsOwoKdGVtcGxhdGUgPHR5cGVuYW1lIElWaXNpdG9yLCB0eXBlbmFtZSBDLCB0eXBlbmFtZSBULCB0eXBlbmFtZS4uLlRzPgpzdHJ1Y3QgSVZpc2l0b3JJbXBsPElWaXNpdG9yLCBDLCBULCBUcy4uLj4gOiBJVmlzaXRvckltcGw8SVZpc2l0b3IsIEMsIFRzLi4uPgp7CiAgICB2aXJ0dWFsIHZvaWQgdmlzaXQoY29uc3QgVCYgdCkgb3ZlcnJpZGUgeyBDOjp2aXNpdCh0KTsgfQp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIElWaXNpdG9yLCB0eXBlbmFtZSBDLCB0eXBlbmFtZSBUPgpzdHJ1Y3QgSVZpc2l0b3JJbXBsPElWaXNpdG9yLCBDLCBUPiA6IElWaXNpdG9yLCBDCnsKICAgIHZpcnR1YWwgdm9pZCB2aXNpdChjb25zdCBUJiB0KSBvdmVycmlkZSB7IEM6OnZpc2l0KHQpOyB9Cn07CgovLyBoZWxwZXIgdG8gZXhwYW5kIGNoaWxkIHR5cGUgdG8gSVZpc2l0b3JJbXBsCnRlbXBsYXRlIDx0eXBlbmFtZSBJVmlzaXRvciwgdHlwZW5hbWUgQz4Kc3RydWN0IElWaXNpdG9ySW1wbFR5cGU7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgLi4uIFRzLCB0eXBlbmFtZSBDPgpzdHJ1Y3QgSVZpc2l0b3JJbXBsVHlwZTxJVmlzaXRvclRzPFRzLi4uPiwgQz4KewogICAgdXNpbmcgdHlwZSA9IElWaXNpdG9ySW1wbDxJVmlzaXRvclRzPFRzLi4uPiwgQywgVHMuLi4+Owp9OwoKLy8gQ3JlYXRlIGFuIG11bHRpIGFycmF5IG9mIHBvaW50ZXIgb2YgZnVuY3Rpb24KLy8gKHdpdGggYWxsIGNvbWJpbmFpc29ucyBvZiBvdmVybG9hZCkuCnRlbXBsYXRlIDx0eXBlbmFtZSBSZXQsIHR5cGVuYW1lIEYsIHR5cGVuYW1lIEFyZz4KY2xhc3MgR2V0QWxsT3ZlcmxvYWQKewpwcml2YXRlOgogICAgdGVtcGxhdGUgPHR5cGVuYW1lLi4uVHM+CiAgICBzdHJ1Y3QgRnVuY3RvcgogICAgewogICAgICAgIC8vIGZ1bmN0aW9uIHdoaWNoIHdpbGwgYmUgaW4gYXJyYXkuCiAgICAgICAgc3RhdGljIFJldCBjYWxsKEYmZiwgY29uc3QgQXJnJiBhcmcpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gY2FsbF9oZWxwZXIoZiwgYXJnLCBtYWtlX2luZGV4X3NlcXVlbmNlPHNpemVvZi4uLihUcyk+KCkpOwogICAgICAgIH0KICAgIHByaXZhdGU6CiAgICAgICAgLy8gVGhlIGZpbmFsIGRpc3BhdGNoZWQgZnVuY3Rpb24KICAgICAgICB0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgLi4uIElzPgogICAgICAgIHN0YXRpYyBSZXQgY2FsbF9oZWxwZXIoRiZmLCBjb25zdCBBcmcmIGFyZywgaW5kZXhfc2VxdWVuY2U8SXMuLi4+KQogICAgICAgIHsKICAgICAgICAgICAgdXNpbmcgUmV0VHVwbGUgPSBzdGQ6OnR1cGxlPFRzJi4uLj47CiAgICAgICAgICAgIC8vIHN0YXRpYyBjYXN0IGlzIHN1ZmZpc2FudCBpZiBhcmcgaXMgdGhlIGFic3RyYWN0IHR5cGUKICAgICAgICAgICAgLy8gd2hlbiBnaXZlbiBhcmcgaXMgY29uY3JldGUgdHlwZSwgcmVpbnRlcnByZXRfY2FzdCBpcyByZXF1aXJlZC4KICAgICAgICAgICAgLy8gVE9ETzogYnVpbGQgYSBzbWFsbGVyIHRhYmxlIHdpdGggb25seSBwb3NzaWJsZSB2YWx1ZSB0byBhdm9pZCB0aGF0CiAgICAgICAgICAgIHJldHVybiBmKHJlaW50ZXJwcmV0X2Nhc3Q8dHlwZW5hbWUgc3RkOjp0dXBsZV9lbGVtZW50PElzLCBSZXRUdXBsZT46OnR5cGU+KHN0ZDo6Z2V0PElzPihhcmcpKS4uLik7CiAgICAgICAgfQogICAgfTsKCiAgICAvLyBoZWxwZXIgY2xhc3MgdG8gY3JlYXRlIHRoZSBtdWx0aSBhcnJheSBvZiBmdW5jdGlvbiBwb2ludGVyCiAgICB0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgTiwgdHlwZW5hbWUgVHVwbGUsIHR5cGVuYW1lLi4uVHM+CiAgICBzdHJ1Y3QgQnVpbGRlcjsKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUuLi5UcywgdHlwZW5hbWUuLi5UczI+CiAgICBzdHJ1Y3QgQnVpbGRlcjwxLCBzdGQ6OnR1cGxlPFRzLi4uPiwgVHMyLi4uPgogICAgewogICAgICAgIHVzaW5nIFJldFR5cGUgPSBzdGQ6OmFycmF5PFJldCAoKikoRiYsIGNvbnN0IEFyZyYpLCBzaXplb2YuLi4oVHMpPjsKCiAgICAgICAgc3RhdGljIGNvbnN0ZXhwciBSZXRUeXBlIGJ1aWxkKCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBSZXRUeXBleyAmRnVuY3RvcjxUczIuLi4sIFRzPjo6Y2FsbC4uLiB9OwogICAgICAgIH0KICAgIH07CgogICAgdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IE4sIHR5cGVuYW1lIC4uLlRzLCB0eXBlbmFtZS4uLlRzMj4KICAgIHN0cnVjdCBCdWlsZGVyPE4sIHN0ZDo6dHVwbGU8VHMuLi4+LCBUczIuLi4+CiAgICB7CiAgICAgICAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CiAgICAgICAgdXNpbmcgUmVjVHlwZSA9IEJ1aWxkZXI8TiAtIDEsIHN0ZDo6dHVwbGU8VHMuLi4+LCBUczIuLi4sIFQ+OwogICAgICAgIHVzaW5nIFQwID0gdHlwZW5hbWUgc3RkOjp0dXBsZV9lbGVtZW50PDAsIHN0ZDo6dHVwbGU8VHMuLi4+Pjo6dHlwZTsKICAgICAgICB1c2luZyBSZXRUeXBlID0gc3RkOjphcnJheTxkZWNsdHlwZShSZWNUeXBlPFQwPjo6YnVpbGQoKSksIHNpemVvZi4uLihUcyk+OwoKICAgICAgICBzdGF0aWMgY29uc3RleHByIFJldFR5cGUgYnVpbGQoKSB7CiAgICAgICAgICAgIHJldHVybiBSZXRUeXBleyBSZWNUeXBlPFRzPjo6YnVpbGQoKS4uLiB9OwogICAgICAgIH0KICAgIH07CgpwdWJsaWM6CiAgICB0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgTiwgdHlwZW5hbWUgVmlzaXRvclR1cGxlPgogICAgc3RhdGljIGNvbnN0ZXhwciBhdXRvIGdldCgpCiAgICAtPiBkZWNsdHlwZShCdWlsZGVyPE4sIFZpc2l0b3JUdXBsZT46OmJ1aWxkKCkpCiAgICB7CiAgICAgICAgcmV0dXJuIEJ1aWxkZXI8TiwgVmlzaXRvclR1cGxlPjo6YnVpbGQoKTsKICAgIH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBSZXQsIHR5cGVuYW1lIElWaXNpdG9yLCB0eXBlbmFtZSBGLCBzdGQ6OnNpemVfdCBOPgpjbGFzcyBkaXNwYXRjaGVyCnsKcHJpdmF0ZToKICAgIHN0ZDo6YXJyYXk8c3RkOjpzaXplX3QsIE4+IGluZGV4OwoKICAgIHN0cnVjdCB2aXNpdG9yQ2FsbEltcGwKICAgIHsKICAgICAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KICAgICAgICB2b2lkIHZpc2l0KGNvbnN0IFQmKSBjb25zdAogICAgICAgIHsKICAgICAgICAgICAgKmluZGV4ID0gZ2V0X2luZGV4X2luX3R1cGxlPFQsIElWaXNpdG9yPjo6dmFsdWU7CiAgICAgICAgfQoKICAgICAgICB2b2lkIHNldEluZGV4UHRyKHN0ZDo6c2l6ZV90JiBpbmRleCkgeyB0aGlzLT5pbmRleCA9ICZpbmRleDsgfQogICAgcHJpdmF0ZToKICAgICAgICBzdGQ6OnNpemVfdCogaW5kZXggPSBudWxscHRyOwogICAgfTsKCiAgICB0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgSSwgdHlwZW5hbWUgVHVwbGU+CiAgICB2b2lkIHNldF9pbmRleChjb25zdCBUdXBsZSZ0KQogICAgewogICAgICAgIHVzaW5nIFZpc2l0b3JUeXBlID0gdHlwZW5hbWUgSVZpc2l0b3JJbXBsVHlwZTxJVmlzaXRvciwgdmlzaXRvckNhbGxJbXBsPjo6dHlwZTsKICAgICAgICBWaXNpdG9yVHlwZSB2aXNpdG9yOwogICAgICAgIHZpc2l0b3Iuc2V0SW5kZXhQdHIoaW5kZXhbSV0pOwoKICAgICAgICBzdGQ6OmdldDxJPih0KS5hY2NlcHQodmlzaXRvcik7CiAgICB9CnB1YmxpYzoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUdXBsZSwgc3RkOjpzaXplX3QgLi4uIElzPgogICAgUmV0IG9wZXJhdG9yICgpIChGJiYgZiwgY29uc3QgVHVwbGUmdCwgaW5kZXhfc2VxdWVuY2U8SXMuLi4+KQogICAgewogICAgICAgIGNvbnN0IGludCBkdW1teVtdID0geyhzZXRfaW5kZXg8SXM+KHQpLCAwKS4uLn07CiAgICAgICAgc3RhdGljX2Nhc3Q8dm9pZD4oZHVtbXkpOyAvLyBzaWxlbnQgdGhlIHdhcm5pbmcgdW51c2VkIHZhcmFpYmxlCiAgICAgICAgY29uc3RleHByIGF1dG8gYSA9IEdldEFsbE92ZXJsb2FkPFJldCwgRiYmLCBUdXBsZT46OgogICAgICAgICAgICB0ZW1wbGF0ZSBnZXQ8c2l6ZW9mLi4uKElzKSwgdHlwZW5hbWUgSVZpc2l0b3I6OnR1cGxlX3R5cGU+KCk7CiAgICAgICAgYXV0byBmdW5jID0gbXVsdGlfYXJyYXlfZ2V0dGVyPE4+OjpnZXQoYSwgaW5kZXgpOwogICAgICAgIHJldHVybiAoKmZ1bmMpKGYsIHQpOwogICAgfQp9OwoKfSAvLyBuYW1lc3BhY2UgZGV0YWlsCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgUmV0LCB0eXBlbmFtZSBWaXNpdG9yLCB0eXBlbmFtZSBGLCB0eXBlbmFtZSAuLi4gVHM+ClJldCBkaXNwYXRjaChGJiYgZiwgVHMmLi4uYXJncykKewogICAgY29uc3RleHByIHN0ZDo6c2l6ZV90IHNpemUgPSBzaXplb2YuLi4oVHMpOwogICAgZGV0YWlsOjpkaXNwYXRjaGVyPFJldCwgVmlzaXRvciwgRiYmLCBzaXplPiBkOwogICAgcmV0dXJuIGQoc3RkOjpmb3J3YXJkPEY+KGYpLCBzdGQ6OnRpZShhcmdzLi4uKSwgbWFrZV9pbmRleF9zZXF1ZW5jZTxzaXplPigpKTsKfQoKI2VuZGlmIC8vIG11bHRpcGxlIGRpc3BhdGNoCgojaWYgMSAvLyBtdWx0aXBsZSBkaXNwYXRjaCB1c2FnZQpzdHJ1Y3QgQTsKc3RydWN0IEI7CnN0cnVjdCBDOwpzdHJ1Y3QgRDsKCgp1c2luZyBJQVZpc2l0b3IgPSBJVmlzaXRvclRzPEEsIEIsIEMsIEQ+OwoKc3RydWN0IEEgewogICAgdmlydHVhbCB+QSgpID0gZGVmYXVsdDsKICAgIHZpcnR1YWwgdm9pZCBhY2NlcHQoSUFWaXNpdG9yJiB2KSBjb25zdCB7IHYudmlzaXQoKnRoaXMpOyB9Cn07CnN0cnVjdCBCIDogQSB7CiAgICB2aXJ0dWFsIHZvaWQgYWNjZXB0KElBVmlzaXRvciYgdikgY29uc3Qgb3ZlcnJpZGUgeyB2LnZpc2l0KCp0aGlzKTsgfQp9OwoKc3RydWN0IEMgOiBBIHsKICAgIHZpcnR1YWwgdm9pZCBhY2NlcHQoSUFWaXNpdG9yJiB2KSBjb25zdCBvdmVycmlkZSB7IHYudmlzaXQoKnRoaXMpOyB9Cn07CnN0cnVjdCBEIDogQSB7CiAgICB2aXJ0dWFsIHZvaWQgYWNjZXB0KElBVmlzaXRvciYgdikgY29uc3Qgb3ZlcnJpZGUgeyB2LnZpc2l0KCp0aGlzKTsgfQp9OwoKY2xhc3MgT2JqZWN0IHsKICAgIHB1YmxpYzoKICAgICAgICB2aXJ0dWFsIGRvdWJsZSBmb28gKEEqLCBBKikgeyBzdGQ6OmNvdXQgPDwgIk9iamVjdDo6Zm9vIEEsQVxuIjsgIHJldHVybiAzLjE0OyB9CiAgICAgICAgdmlydHVhbCBkb3VibGUgZm9vIChCKiwgQiopIHsgc3RkOjpjb3V0IDw8ICJPYmplY3Q6OmZvbyBCLEJcbiI7ICByZXR1cm4gMy4xNDsgfQogICAgICAgIHZpcnR1YWwgZG91YmxlIGZvbyAoQiosIEMqKSB7IHN0ZDo6Y291dCA8PCAiT2JqZWN0Ojpmb28gQixDXG4iOyAgcmV0dXJuIDMuMTQ7IH0KICAgICAgICB2aXJ0dWFsIGRvdWJsZSBmb28gKEMqLCBCKikgeyBzdGQ6OmNvdXQgPDwgIk9iamVjdDo6Zm9vIEMsQlxuIjsgIHJldHVybiAzLjE0OyB9CiAgICAgICAgdmlydHVhbCBkb3VibGUgZm9vIChDKiwgQyopIHsgc3RkOjpjb3V0IDw8ICJPYmplY3Q6OmZvbyBDLENcbiI7ICByZXR1cm4gMy4xNDsgfQogICAgICAgIHZpcnR1YWwgY2hhciBmb28gKEEqLCBBKiwgQSopIGNvbnN0IHsgc3RkOjpjb3V0IDw8ICJPYmplY3Q6OmZvbyBBLEEsQVxuIjsgIHJldHVybiAnJic7IH0KICAgICAgICB2aXJ0dWFsIGNoYXIgZm9vIChDKiwgQiosIEQqKSBjb25zdCB7IHN0ZDo6Y291dCA8PCAiT2JqZWN0Ojpmb28gQyxCLERcbiI7ICByZXR1cm4gJyEnOyB9ICAvLyBPdmVybG9hZCBvZiBmb28gd2l0aCB0aHJlZSBhcmd1bWVudHMuCiAgICAgICAgdmlydHVhbCB2b2lkIGJhciAoQSosIEEqLCBBKikgY29uc3QgeyBzdGQ6OmNvdXQgPDwgIk9iamVjdDo6YmFyIEEsQSxBXG4iOyB9CiAgICAgICAgdmlydHVhbCB2b2lkIGJhciAoQiosIEIqLCBCKikgY29uc3QgeyBzdGQ6OmNvdXQgPDwgIk9iamVjdDo6YmFyIEIsQixCXG4iOyB9CiAgICAgICAgdmlydHVhbCB2b2lkIGJhciAoQiosIEMqLCBCKikgY29uc3QgeyBzdGQ6OmNvdXQgPDwgIk9iamVjdDo6YmFyIEIsQyxCXG4iOyB9CiAgICAgICAgdmlydHVhbCB2b2lkIGJhciAoQiosIEMqLCBDKikgY29uc3QgeyBzdGQ6OmNvdXQgPDwgIk9iamVjdDo6YmFyIEIsQyxDXG4iOyB9CiAgICAgICAgdmlydHVhbCB2b2lkIGJhciAoQiosIEMqLCBEKikgY29uc3QgeyBzdGQ6OmNvdXQgPDwgIk9iamVjdDo6YmFyIEIsQyxEXG4iOyB9CiAgICAgICAgdmlydHVhbCB2b2lkIGJhciAoQyosIEIqLCBEKikgY29uc3QgeyBzdGQ6OmNvdXQgPDwgIk9iamVjdDo6YmFyIEMsQixEXG4iOyB9CiAgICAgICAgdmlydHVhbCB2b2lkIGJhciAoQyosIEMqLCBDKikgY29uc3QgeyBzdGQ6OmNvdXQgPDwgIk9iamVjdDo6YmFyIEMsQyxDXG4iOyB9CiAgICAgICAgdmlydHVhbCB2b2lkIGJhciAoRCosIEIqLCBDKikgY29uc3QgeyBzdGQ6OmNvdXQgPDwgIk9iamVjdDo6YmFyIEQsQixDXG4iOyB9CiAgICAgICAgZG91YmxlIGZvb011bHRpcGxlRGlzcGF0Y2ggKEEqLCBBKik7CiAgICAgICAgY2hhciBmb29NdWx0aXBsZURpc3BhdGNoIChBKiwgQSosIEEqKTsKfTsKCmNsYXNzIEZvb0Rpc3BhdGNoZXIKewpwdWJsaWM6CglleHBsaWNpdCBGb29EaXNwYXRjaGVyKE9iamVjdCYgb2JqZWN0KSA6IG9iamVjdChvYmplY3QpIHt9CgkKCXRlbXBsYXRlIDx0eXBlbmFtZSBUMSwgdHlwZW5hbWUgVDI+CiAgICBkb3VibGUgb3BlcmF0b3IoKSAoVDEmIGExLCBUMiYgYTIpIGNvbnN0CiAgICB7CiAgICAJcmV0dXJuIG9iamVjdC5mb28oJmExLCAmYTIpOwogICAgfQoKCXRlbXBsYXRlIDx0eXBlbmFtZSBUMSwgdHlwZW5hbWUgVDIsIHR5cGVuYW1lIFQzPgogICAgY2hhciBvcGVyYXRvcigpIChUMSYgYTEsIFQyJiBhMiwgVDMmIGEzKSBjb25zdAogICAgewogICAgCXJldHVybiBvYmplY3QuZm9vKCZhMSwgJmEyLCAmYTMpOwogICAgfQpwcml2YXRlOgogICAgT2JqZWN0JiBvYmplY3Q7Cn07Cgpkb3VibGUgT2JqZWN0Ojpmb29NdWx0aXBsZURpc3BhdGNoIChBKiBhMSwgQSogYTIpCnsKCXJldHVybiBkaXNwYXRjaDxkb3VibGUsIElBVmlzaXRvcj4oRm9vRGlzcGF0Y2hlcigqdGhpcyksICphMSwgKmEyKTsKfQpjaGFyIE9iamVjdDo6Zm9vTXVsdGlwbGVEaXNwYXRjaCAoQSogYTEsIEEqIGEyLCBBKiBhMykKewoJcmV0dXJuIGRpc3BhdGNoPGNoYXIsIElBVmlzaXRvcj4oRm9vRGlzcGF0Y2hlcigqdGhpcyksICphMSwgKmEyLCAqYTMpOwp9CgoKaW50IG1haW4oKSB7CglBIGFfYTsKCUIgYV9iOwoJQyBhX2M7CglEIGFfZDsKICAgIEEqIGFbXSA9IHsmYV9iLCAmYV9jLCAmYV9kLCAmYV9hfTsKICAgIE9iamVjdCBvYmplY3Q7CgogICAgZG91YmxlIGQgPSBvYmplY3QuZm9vIChhWzBdLCBhWzFdKTsgIC8vIE9iamVjdDo6Zm9vIEEsQSAgKG5vIG11bHRpcGxlIGRpc3BhdGNoKQogICAgZCA9IG9iamVjdC5mb29NdWx0aXBsZURpc3BhdGNoIChhWzBdLCBhWzFdKTsgIC8vIE9iamVjdDo6Zm9vIEIsQwogICAgc3RkOjpjb3V0IDw8ICJkID0gIiA8PCBkIDw8IHN0ZDo6ZW5kbDsgIC8vIDMuMTQKCiAgICBvYmplY3QuZm9vTXVsdGlwbGVEaXNwYXRjaCAoYVswXSwgYVszXSk7ICAvLyBCLEEgLT4gc28gYmVzdCBtYXRjaCBpcyBPYmplY3Q6OmZvbyBBLEEKCiAgICBjb25zdCBjaGFyIGsgPSBvYmplY3QuZm9vTXVsdGlwbGVEaXNwYXRjaCAoYVsxXSwgYVswXSwgYVsyXSk7ICAvLyBPYmplY3Q6OmZvbyBDLEIsRAogICAgc3RkOjpjb3V0IDw8ICJrID0gIiA8PCBrIDw8IHN0ZDo6ZW5kbDsgIC8vICEKfQoKI2VuZGlmIC8vIG11bHRpcGxlIGRpc3BhdGNoIHVzYWdlCg==