#include <functional> //for std::is_placeholder<T>
/*#include <boost/bind/arg.hpp>
// ************************************************************************************************
namespace std {
template <> struct is_placeholder<boost::arg<1>> : integral_constant<int, 1> {};
template <> struct is_placeholder<boost::arg<2>> : integral_constant<int, 2> {};
template <> struct is_placeholder<boost::arg<3>> : integral_constant<int, 3> {};
template <> struct is_placeholder<boost::arg<4>> : integral_constant<int, 4> {};
template <> struct is_placeholder<boost::arg<5>> : integral_constant<int, 5> {};
template <> struct is_placeholder<boost::arg<6>> : integral_constant<int, 6> {};
template <> struct is_placeholder<boost::arg<7>> : integral_constant<int, 7> {};
template <> struct is_placeholder<boost::arg<8>> : integral_constant<int, 8> {};
template <> struct is_placeholder<boost::arg<9>> : integral_constant<int, 9> {};
}*/
namespace my {
struct ILL { ILL(int) {} typedef ILL first_type; };
//************************************************************************************************
//placeholderなら実引数に変換
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
struct alt_type {
typedef typename std::remove_cv<typename std::remove_reference<P>::type>::type naked_param_type;
static const int N = std::is_placeholder<naked_param_type>::value;
typedef typename std::conditional<N == 0, P,
typename std::conditional<N == 1, A1,
typename std::conditional<N == 2, A2,
typename std::conditional<N == 3, A3,
typename std::conditional<N == 4, A4,
typename std::conditional<N == 5, A5,
ILL>::type
>::type>::type>::type>::type>::type
type;
};
//************************************************************************************************
//引数型と戻値型
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5, int N>
struct func_signature_base;
//フリー関数/メンバ関数の区別と戻値型
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base0 {
typedef F func_type;
typedef P1 param1_type; typedef P2 param2_type; typedef P3 param3_type; typedef P4 param4_type; typedef P5 param5_type;
static F getF();
static P1 get1(); static P2 get2(); static P3 get3(); static P4 get4(); static P5 get5();
//フリー関数は char, Obj.*mFは short, pObj->*mFはint (int********** の'*'の数は引数の数)
template <typename V> static char
test(V v, int*****, decltype( v (get1(), get2(), get3(), get4(), get5()), (int)0) = 0);
template <typename V> static short
test(V v, int*****, decltype( (get1().*v)(get2(), get3(), get4(), get5()), (int)0) = 0);
template <typename V> static int
test(V v, int*****, decltype((get1()->*v)(get2(), get3(), get4(), get5()), (int)0) = 0);
template <typename V> static char
test(V v, int****, decltype( v (get2(), get3(), get4(), get5()), (int)0) = 0);
template <typename V> static short
test(V v, int****, decltype( (get2().*v)(get3(), get4(), get5()), (int)0) = 0);
template <typename V> static int
test(V v, int****, decltype((get2()->*v)(get3(), get4(), get5()), (int)0) = 0);
template <typename V> static char
test(V v, int***, decltype( v (get3(), get4(), get5()), (int)0) = 0);
template <typename V> static short
test(V v, int***, decltype( (get3().*v)(get4(), get5()), (int)0) = 0);
template <typename V> static int
test(V v, int***, decltype((get3()->*v)(get4(), get5()), (int)0) = 0);
template <typename V> static char
test(V v, int**, decltype( v (get4(), get5()), (int)0) = 0);
template <typename V> static short
test(V v, int**, decltype( (get4().*v)(get5()), (int)0) = 0);
template <typename V> static int
test(V v, int**, decltype((get4()->*v)(get5()), (int)0) = 0);
template <typename V> static char
test(V v, int*, decltype( v (get5()), (int)0) = 0);
template <typename V> static short
test(V v, int*, decltype( (get5().*v)(), (int)0) = 0);
template <typename V> static int
test(V v, int*, decltype((get5()->*v)(), (int)0) = 0);
template <typename V> static char
test(V v, int, decltype(v(), (int)0) = 0);
static long test(...);
//フリー関数かメンバ関数かに応じた戻値型 (int********** の'*'の数は引数の数)
template <typename V, typename FM> static auto // FMはフリー関数orメンバ関数の印
return_t(V v, int*****, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
->decltype(v(get1(), get2(), get3(), get4(), get5()));
template <typename V, typename FM> static auto
return_t(V v, int*****, FM, typename std::enable_if<std::is_same<FM, short>::value, V>::type* = 0)
->decltype(((get1()).*v)(get2(), get3(), get4(), get5()));
template <typename V, typename FM> static auto
return_t(V v, int*****, FM, typename std::enable_if<std::is_same<FM, int>::value, V>::type* = 0)
->decltype(((get1())->*v)(get2(), get3(), get4(), get5()));
template <typename V, typename FM> static auto
return_t(V v, int****, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
->decltype( v(get2(), get3(), get4(), get5()));
template <typename V, typename FM> static auto
return_t(V v, int****, FM, typename std::enable_if<std::is_same<FM, short>::value, V>::type* = 0)
->decltype((( get2()).*v)(get3(), get4(), get5()));
template <typename V, typename FM> static auto
return_t(V v, int****, FM, typename std::enable_if<std::is_same<FM, int>::value, V>::type* = 0)
->decltype(((get2())->*v)(get3(), get4(), get5()));
template <typename V, typename FM> static auto
return_t(V v, int***, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
->decltype( v(get3(), get4(), get5()));
template <typename V, typename FM> static auto
return_t(V v, int***, FM, typename std::enable_if<std::is_same<FM, short>::value, V>::type* = 0)
->decltype((( get3()).*v)(get4(), get5()));
template <typename V, typename FM> static auto
return_t(V v, int***, FM, typename std::enable_if<std::is_same<FM, int>::value, V>::type* = 0)
->decltype(((get3())->*v)(get4(), get5()));
template <typename V, typename FM> static auto
return_t(V v, int**, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
->decltype( v(get4(), get5()));
template <typename V, typename FM> static auto
return_t(V v, int**, FM, typename std::enable_if<std::is_same<FM, short>::value, V>::type* = 0)
->decltype((( get4()).*v)(get5()));
template <typename V, typename FM> static auto
return_t(V v, int**, FM, typename std::enable_if<std::is_same<FM, int>::value, V>::type* = 0)
->decltype(((get4())->*v)(get5()));
template <typename V, typename FM> static auto
return_t(V v, int*, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
->decltype( v(get5()));
template <typename V, typename FM> static auto
return_t(V v, int*, FM, typename std::enable_if<std::is_same<FM, short>::value, V>::type* = 0)
->decltype((( get5()).*v)());
template <typename V, typename FM> static auto
return_t(V v, int*, FM, typename std::enable_if<std::is_same<FM, int>::value, V>::type* = 0)
->decltype(((get5())->*v)());
template <typename V, typename FM> static auto
return_t(V v, int, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
->decltype(v());
static ILL return_t(...);
};
// 5 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 5> : func_signature_base0<F, P1, P2, P3, P4, P5> {
typedef func_signature_base0<F, P1, P2, P3, P4, P5> B;
typedef decltype(B::test(B::getF(),(int*****)0)) fm_type;
typedef decltype(B::return_t(B::getF(), (int*****)0, (fm_type)0)) return_type;
};
// 4 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 4> : func_signature_base0<F, P1, P2, P3, P4, P5> {
typedef func_signature_base0<F, P1, P2, P3, P4, P5> B;
typedef decltype(B::test(B::getF(),(int****)0)) fm_type;
typedef decltype(B::return_t(B::getF(), (int****)0, (fm_type)0)) return_type;
};
// 3 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 3> : func_signature_base0<F, P1, P2, P3, P4, P5> {
typedef func_signature_base0<F, P1, P2, P3, P4, P5> B;
typedef decltype(B::test(B::getF(),(int***)0)) fm_type;
typedef decltype(B::return_t(B::getF(), (int***)0, (fm_type)0)) return_type;
};
// 2 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 2> : func_signature_base0<F, P1, P2, P3, P4, P5> {
typedef func_signature_base0<F, P1, P2, P3, P4, P5> B;
typedef decltype(B::test(B::getF(),(int**)0)) fm_type;
typedef decltype(B::return_t(B::getF(), (int**)0, (fm_type)0)) return_type;
};
// 1 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 1> : func_signature_base0<F, P1, P2, P3, P4, P5> {
typedef func_signature_base0<F, P1, P2, P3, P4, P5> B;
typedef decltype(B::test(B::getF(),(int*)0)) fm_type;
typedef decltype(B::return_t(B::getF(), (int*)0, (fm_type)0)) return_type;
};
// 0 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 0> : func_signature_base0<F, P1, P2, P3, P4, P5> {
typedef func_signature_base0<F, P1, P2, P3, P4, P5> B;
typedef decltype(B::test(B::getF(),(int)0)) fm_type;
typedef decltype(B::return_t(B::getF(), (int)0, (fm_type)0)) return_type;
};
//------------------------------------------------------------------------------------------------
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5,
typename A1, typename A2, typename A3, typename A4, typename A5, int N>
struct func_signature : func_signature_base<typename alt_type<F , A1, A2, A3, A4, A5>::type ,
typename alt_type<P1, A1, A2, A3, A4, A5>::type ,
typename alt_type<P2, A1, A2, A3, A4, A5>::type ,
typename alt_type<P3, A1, A2, A3, A4, A5>::type ,
typename alt_type<P4, A1, A2, A3, A4, A5>::type ,
typename alt_type<P5, A1, A2, A3, A4, A5>::type ,
N >
{ };
//************************************************************************************************
template <typename P>
struct ParamOf {
typedef P param_type;
typedef typename std::remove_cv<typename std::remove_reference<P>::type>::type naked_param_type;
static const size_t placeholder = std::is_placeholder<naked_param_type>::value;
mutable P param;
ParamOf(P p) : param(p) { }
ParamOf(const ParamOf<P>& p) : param(p.param) { }
};
//------------------------------------------------------------------------------------------------
//placeholderだったら実引数に変換する SFINAE
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
typename P::param_type
pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==0>::type* = 0)
{ return p->param; }
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
A1&& pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==1>::type* = 0)
{ return std::forward<A1>(a1); }
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
A2&& pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==2>::type* = 0)
{ return std::forward<A2>(a2); }
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
A3&& pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==3>::type* = 0)
{ return std::forward<A3>(a3); }
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
A4&& pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==4>::type* = 0)
{ return std::forward<A4>(a4); }
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
A5&& pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==5>::type* = 0)
{ return std::forward<A5>(a5); }
//************************************************************************************************
template <int N, typename S, typename T = char> struct executer;
//************************************************************************************************
template <typename P, typename T = ILL, typename F = P, int N = 0>
struct BindOf : ParamOf<P> {
T target;
static const int depth = N;
typedef T target_type;
typedef F func_type;
typedef BindOf<P, T, F, N> MyT;
typedef typename ParamOf<P>::param_type param_type;
typedef typename std::conditional<N == 0, MyT, T>::type back_type;
typedef typename std::conditional<N == 0, MyT, typename T::first_type>::type first_type;
BindOf(const P& p) : ParamOf<P>(p), target(0) { } // bindOfで来る
BindOf(const P p, T& t) : ParamOf<P>(p), target(t) { } // << で来る
BindOf(P p, T&& t) : ParamOf<P>(p), target((T&&)t) { } // << で来る
BindOf(MyT&& t) : ParamOf<P>(t), target((T&&)(t.target)) { }
back_type* getTarget() const { return (depth == 0)? (back_type*)this: (back_type*)⌖ }
first_type* get0() const { return (depth == 0)? (first_type*)this: getTarget()->get0(); }
//
template <typename A1, typename A2, typename A3, typename A4, typename A5>
struct mySignature {
typedef typename my::func_signature<func_type,
typename back_type::back_type::back_type::back_type::param_type,
typename back_type::back_type::back_type::param_type,
typename back_type::back_type::param_type,
typename back_type::param_type,
param_type,
A1, A2, A3, A4, A5, depth>
type;
};
//bindする変数を追加していく operator <<
template <typename PN> BindOf<PN, MyT, func_type, depth + 1>
operator <<(PN&& p)
{ return BindOf<PN, MyT, func_type, depth + 1>(std::forward<PN>(p), (MyT&&)*this); }
// ファンクタとしての operator(a,b,c,d,e)
template <typename A1, typename A2, typename A3, typename A4, typename A5>
auto operator ()(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5) const
->typename mySignature<A1, A2, A3, A4, A5>::type::return_type
{
typedef typename mySignature<A1, A2, A3, A4, A5>::type signature;
executer<depth, signature, typename signature::fm_type>
theExecuter(pass(get0(), a1, a2, a3, a4, a5));
return theExecuter
(
pass(getTarget()->getTarget()->getTarget()->getTarget(), a1, a2, a3, a4, a5),
pass(getTarget()->getTarget()->getTarget(), a1, a2, a3, a4, a5),
pass(getTarget()->getTarget(), a1, a2, a3, a4, a5),
pass(getTarget(), a1, a2, a3, a4, a5),
pass(this, a1, a2, a3, a4, a5)
);
}
// ファンクタとしての operator(a,b,c,d)
template <typename A1, typename A2, typename A3, typename A4>
auto operator ()(A1&& a1, A2&& a2, A3&& a3, A4&& a4) const
->typename mySignature<A1, A2, A3, A4, ILL>::type::return_type
{ return (*this)((A1&&)a1, (A2&&)a2, (A3&&)a3, (A4&&)a4, ILL(0)); }
// ファンクタとしての operator(a,b,c)
template <typename A1, typename A2, typename A3>
auto operator ()(A1&& a1, A2&& a2, A3&& a3) const
->typename mySignature<A1, A2, A3, ILL, ILL>::type::return_type
{ return (*this)((A1&&)a1, (A2&&)a2, (A3&&)a3, ILL(0), ILL(0)); }
// ファンクタとしての operator(a,b)
template <typename A1, typename A2>
auto operator ()(A1&& a1, A2&& a2) const
->typename mySignature<A1, A2, ILL, ILL, ILL>::type::return_type
{ return (*this)((A1&&)a1, (A2&&)a2, ILL(0), ILL(0), ILL(0)); }
// ファンクタとしての operator(a)
template <typename A1>
auto operator ()(A1&& a1) const
->typename mySignature<A1, ILL, ILL, ILL, ILL>::type::return_type
{ return (*this)((A1&&)a1, ILL(0), ILL(0), ILL(0), ILL(0)); }
// ファンクタとしての operator(void)
auto operator ()() const
->typename mySignature<ILL, ILL, ILL, ILL, ILL>::type::return_type
{ return (*this)(ILL(0), ILL(0), ILL(0), ILL(0), ILL(0)); }
};
//************************************************************************************************
// execute with 5 parameters
template <typename S>
struct executer<5, S> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return org_function(p1, p2, p3, p4, p5); }
};
template <typename S>
struct executer<5, S, short> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type Obj,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return (Obj.*org_function)(p2, p3, p4, p5); }
};
template <typename S>
struct executer<5, S, int> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type pObj,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return (pObj->*org_function)(p2, p3, p4, p5); }
};
// execute with 4 parameters
template <typename S>
struct executer<4, S> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return org_function(p2, p3, p4, p5); }
};
template <typename S>
struct executer<4, S, short> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type Obj,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return (Obj.*org_function)(p3, p4, p5); }
};
template <typename S>
struct executer<4, S, int> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type pObj,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return (pObj->*org_function)(p3, p4, p5); }
};
// execute with 3 parameters
template <typename S>
struct executer<3, S> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return org_function(p3, p4, p5); }
};
template <typename S>
struct executer<3, S, short> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type Obj,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return (Obj.*org_function)(p4, p5); }
};
template <typename S>
struct executer<3, S, int> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type pObj,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return (pObj->*org_function)(p4, p5); }
};
// execute with 2 parameters
template <typename S>
struct executer<2, S> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return org_function(p4, p5); }
};
template <typename S>
struct executer<2, S, short> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type Obj,
typename S::param5_type p5) const
{ return (Obj.*org_function)(p5); }
};
template <typename S>
struct executer<2, S, int> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type pObj,
typename S::param5_type p5) const
{ return (pObj->*org_function)(p5); }
};
// execute with 1 parameters
template <typename S>
struct executer<1, S> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return org_function(p5); }
};
template <typename S>
struct executer<1, S, short> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type Obj) const
{ return (Obj.*org_function)(); }
};
template <typename S>
struct executer<1, S, int> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type pObj) const
{ return (pObj->*org_function)(); }
};
// execute with 0 parameters
template <typename S>
struct executer<0, S> {
typedef typename S::func_type func_type;
func_type org_function;
executer(const func_type& f) : org_function(f) { }
typename S::return_type operator ()(typename S::param1_type p1,
typename S::param2_type p2,
typename S::param3_type p3,
typename S::param4_type p4,
typename S::param5_type p5) const
{ return org_function(); }
};
//************************************************************************************************
//関数ポインタ以外のオブジェクト
template <typename F>
BindOf<typename std::remove_reference<F>::type>
bindOf(F&& f)
{ return BindOf<typename std::remove_reference<F>::type>(std::forward<F>(f)); }
//関数ポインタ
template <typename F>
BindOf<F*>
bindOf(F* f)
{ return BindOf<F*>(f); }
//************************************************************************************************
//ユーザが使う bind関数
template <typename F, typename P1>
auto bind(F&& f, P1&& p1)->decltype(bindOf(std::forward<F>(f)) << std::forward<P1>(p1))
{ return bindOf(std::forward<F>(f)) << std::forward<P1>(p1); }
template <typename F, typename P1, typename P2>
auto bind(F&& f, P1&& p1, P2&& p2)->decltype(bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2))
{ return bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2); }
template <typename F, typename P1, typename P2, typename P3>
auto bind(F&& f, P1&& p1, P2&& p2, P3&& p3)->decltype(bindOf(std::forward<F>(f)) << std::forward<P1>(p1)
<< std::forward<P2>(p2) << std::forward<P3>(p3))
{ return bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2) << std::forward<P3>(p3); }
template <typename F, typename P1, typename P2, typename P3, typename P4>
auto bind(F&& f, P1&& p1, P2&& p2, P3&& p3, P4&& p4)
->decltype(bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2) << std::forward<P3>(p3) << std::forward<P4>(p4))
{ return bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2) << std::forward<P3>(p3) << std::forward<P4>(p4); }
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
auto bind(F&& f, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5)
->decltype(bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2) << std::forward<P3>(p3)
<< std::forward<P4>(p4) << std::forward<P5>(p5))
{ return bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2) << std::forward<P3>(p3)
<< std::forward<P4>(p4) << std::forward<P5>(p5); }
} //namespace my
//************************************************************************************************
//
//************************************************************************************************
int f1(int a) { return 1 + a; }
int f2(int a, int& b) { return a + (b *= 10); }
int f3(int a, int& b, int c) { return a + (b *= 20) + c; }
int f4(int a, int& b, int c, int& d) { return a + (b *= 30) + c + (d += 30); }
int f5(int a, int& b, int c, int& d, int e) { return a + (b *= 40) + c + (d += 40) + e; }
struct Func {
int operator ()() const { return 1000; }
int operator ()(int a) const { return 1000 + a; }
int operator ()(int a, int& b) const { return a + (b *= 1000); }
int operator ()(int a, int& b, int c) const { return a + (b *= 2000) + c; }
int operator ()(int a, int& b, int c, int& d) const { return a + (b *= 3000) + c + (d += 3000); }
int func0() const { return (*this)(); }
int func1(int a) const { return (*this)(a); }
int func2(int a, int& b) const { return (*this)(a, b); }
int func3(int a, int& b, int c) const { return (*this)(a, b, c); }
int func4(int a, int& b, int c, int& d) const { return (*this)(a, b, c, d); }
};
#include <iostream>
int main() {
using namespace std::placeholders;
int b = 1;
int d = 1;
int result = 0;
std::cout << "フリー関数 1変数バインド" << std::endl;
auto bf11 = my::bind(f1, 1);
result = bf11();
std::cout << " f1(1) = " << result << '\n';
std::cout << "フリー関数 1変数バインドせず" << std::endl;
auto bf12 = my::bind(f1, _1);
result = bf12(2);
std::cout << " f1(2) = " << result << '\n';
std::cout << "フリー関数 5変数" << std::endl;
std::cout << " b = " << b << ", d = " << d << " ";
auto bf51 = my::bind(f5, 1, _1, 8, d, _2);
result = bf51(b, 3);
std::cout << "f5(1, b, 8, d, 3) = " << result << " b = " << b << ", d = " << d << std::endl;
std::cout << "ファンクタ 4変数" << std::endl;
b = d = 1;
Func fn;
std::cout << " b = " << b << ", d = " << d << " ";
auto bfn4 = my::bind(fn, 1, _1, 2, _2);
result = bfn4(b, d);
std::cout << "fn(1, b, 2, d) = " << result << " b = " << b << ", d = " << d << std::endl;
std::cout << "ファンクタ メンバポインタ" << std::endl;
b = d = 1;
std::cout << " b = " << b << ", d = " << d << " ";
auto bfn4m = my::bind(&Func::func4, fn, 1, _1, 2, _2);
result = bfn4m(b, d);
std::cout << "fn.*mF(1, b, 2, d) = " << result << " b = " << b << ", d = " << d << std::endl;
b = d = 1;
std::cout << " b = " << b << ", d = " << d << " ";
auto bfn4mp = my::bind(&Func::func4, &fn, 1, _1, 2, _2);
result = bfn4mp(b, d);
std::cout << "fn->*mF(1, b, 2, d) = " << result << " b = " << b << ", d = " << d << std::endl;
b = d = 1;
std::cout << "第一引数もプレースホルダにできる" << std::endl;
std::cout << " b = " << b << ", d = " << d << " ";
auto bfn4b1 = my::bind(_1, &fn, 101, _2, 202, _3);
result = bfn4b1(&Func::func4, b, d);
std::cout << "fn->*mF(101, b, 202, d) = " << result << " b = " << b << ", d = " << d << std::endl;
b = d = 2;
std::cout << "どこにでも置ける" << std::endl;
std::cout << " b = " << b << ", d = " << d << " ";
auto bfn5bF = my::bind(_3, fn, 81, _1, 92, _2);
result = bfn5bF(b, d, &Func::func4);
std::cout << "fn.*mF(81, b, 92, d) = " << result << " b = " << b << ", d = " << d << std::endl;
return 0;
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CS8vZm9yIHN0ZDo6aXNfcGxhY2Vob2xkZXI8VD4KCi8qI2luY2x1ZGUgPGJvb3N0L2JpbmQvYXJnLmhwcD4KLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCm5hbWVzcGFjZSBzdGQgewoJdGVtcGxhdGUgPD4gc3RydWN0IGlzX3BsYWNlaG9sZGVyPGJvb3N0Ojphcmc8MT4+IDogaW50ZWdyYWxfY29uc3RhbnQ8aW50LCAxPiB7fTsKCXRlbXBsYXRlIDw+IHN0cnVjdCBpc19wbGFjZWhvbGRlcjxib29zdDo6YXJnPDI+PiA6IGludGVncmFsX2NvbnN0YW50PGludCwgMj4ge307Cgl0ZW1wbGF0ZSA8PiBzdHJ1Y3QgaXNfcGxhY2Vob2xkZXI8Ym9vc3Q6OmFyZzwzPj4gOiBpbnRlZ3JhbF9jb25zdGFudDxpbnQsIDM+IHt9OwoJdGVtcGxhdGUgPD4gc3RydWN0IGlzX3BsYWNlaG9sZGVyPGJvb3N0Ojphcmc8ND4+IDogaW50ZWdyYWxfY29uc3RhbnQ8aW50LCA0PiB7fTsKCXRlbXBsYXRlIDw+IHN0cnVjdCBpc19wbGFjZWhvbGRlcjxib29zdDo6YXJnPDU+PiA6IGludGVncmFsX2NvbnN0YW50PGludCwgNT4ge307Cgl0ZW1wbGF0ZSA8PiBzdHJ1Y3QgaXNfcGxhY2Vob2xkZXI8Ym9vc3Q6OmFyZzw2Pj4gOiBpbnRlZ3JhbF9jb25zdGFudDxpbnQsIDY+IHt9OwoJdGVtcGxhdGUgPD4gc3RydWN0IGlzX3BsYWNlaG9sZGVyPGJvb3N0Ojphcmc8Nz4+IDogaW50ZWdyYWxfY29uc3RhbnQ8aW50LCA3PiB7fTsKCXRlbXBsYXRlIDw+IHN0cnVjdCBpc19wbGFjZWhvbGRlcjxib29zdDo6YXJnPDg+PiA6IGludGVncmFsX2NvbnN0YW50PGludCwgOD4ge307Cgl0ZW1wbGF0ZSA8PiBzdHJ1Y3QgaXNfcGxhY2Vob2xkZXI8Ym9vc3Q6OmFyZzw5Pj4gOiBpbnRlZ3JhbF9jb25zdGFudDxpbnQsIDk+IHt9Owp9Ki8KCm5hbWVzcGFjZSBteQl7CgpzdHJ1Y3QgSUxMIHsgSUxMKGludCkge30gIHR5cGVkZWYgSUxMIGZpcnN0X3R5cGU7IH07CgovLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovL3BsYWNlaG9sZGVy44Gq44KJ5a6f5byV5pWw44Gr5aSJ5o+bCnRlbXBsYXRlIDx0eXBlbmFtZSBQLCB0eXBlbmFtZSBBMSwgdHlwZW5hbWUgQTIsIHR5cGVuYW1lIEEzLCB0eXBlbmFtZSBBNCwgdHlwZW5hbWUgQTU+CnN0cnVjdCBhbHRfdHlwZQl7Cgl0eXBlZGVmIHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX2N2PHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX3JlZmVyZW5jZTxQPjo6dHlwZT46OnR5cGUgbmFrZWRfcGFyYW1fdHlwZTsKCXN0YXRpYyBjb25zdCBpbnQgTiA9IHN0ZDo6aXNfcGxhY2Vob2xkZXI8bmFrZWRfcGFyYW1fdHlwZT46OnZhbHVlOwoJdHlwZWRlZiB0eXBlbmFtZSBzdGQ6OmNvbmRpdGlvbmFsPE4gPT0gMCwgUCwKCQkJCQkJdHlwZW5hbWUgc3RkOjpjb25kaXRpb25hbDxOID09IDEsIEExLAoJCQkJCQkJdHlwZW5hbWUgc3RkOjpjb25kaXRpb25hbDxOID09IDIsIEEyLAoJCQkJCQkJCXR5cGVuYW1lIHN0ZDo6Y29uZGl0aW9uYWw8TiA9PSAzLCBBMywKCQkJCQkJCQkJdHlwZW5hbWUgc3RkOjpjb25kaXRpb25hbDxOID09IDQsIEE0LAoJCQkJCQkJCQkJdHlwZW5hbWUgc3RkOjpjb25kaXRpb25hbDxOID09IDUsIEE1LAoJCQkJCQkJCQkJCUlMTD46OnR5cGUKCQkJCQkJPjo6dHlwZT46OnR5cGU+Ojp0eXBlPjo6dHlwZT46OnR5cGUKCQkJdHlwZTsKfTsKLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy/lvJXmlbDlnovjgajmiLvlgKTlnosKdGVtcGxhdGUgPHR5cGVuYW1lIEYsIHR5cGVuYW1lIFAxLCB0eXBlbmFtZSBQMiwgdHlwZW5hbWUgUDMsIHR5cGVuYW1lIFA0LCB0eXBlbmFtZSBQNSwgaW50IE4+CnN0cnVjdCBmdW5jX3NpZ25hdHVyZV9iYXNlOwovL+ODleODquODvOmWouaVsO+8j+ODoeODs+ODkOmWouaVsOOBruWMuuWIpeOBqOaIu+WApOWeiwp0ZW1wbGF0ZSA8dHlwZW5hbWUgRiwgdHlwZW5hbWUgUDEsIHR5cGVuYW1lIFAyLCB0eXBlbmFtZSBQMywgdHlwZW5hbWUgUDQsIHR5cGVuYW1lIFA1PgpzdHJ1Y3QgZnVuY19zaWduYXR1cmVfYmFzZTAJewoJdHlwZWRlZiBGIGZ1bmNfdHlwZTsKCXR5cGVkZWYgUDEgcGFyYW0xX3R5cGU7IHR5cGVkZWYgUDIgcGFyYW0yX3R5cGU7IHR5cGVkZWYgUDMgcGFyYW0zX3R5cGU7IHR5cGVkZWYgUDQgcGFyYW00X3R5cGU7IHR5cGVkZWYgUDUgcGFyYW01X3R5cGU7CglzdGF0aWMgRiAgZ2V0RigpOwoJc3RhdGljIFAxIGdldDEoKTsgc3RhdGljIFAyIGdldDIoKTsgc3RhdGljIFAzIGdldDMoKTsgc3RhdGljIFA0IGdldDQoKTsgc3RhdGljIFA1IGdldDUoKTsKCS8v44OV44Oq44O86Zai5pWw44GvIGNoYXIsICAgT2JqLiptRuOBryBzaG9ydCwgICBwT2JqLT4qbUbjga9pbnQgIO+8iGludCoqKioqKioqKiog44GuJyon44Gu5pWw44Gv5byV5pWw44Gu5pWw77yJCgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVj4gc3RhdGljIGNoYXIKCQl0ZXN0KFYgdiwgaW50KioqKiosIGRlY2x0eXBlKCB2ICAoZ2V0MSgpLCBnZXQyKCksIGdldDMoKSwgZ2V0NCgpLCBnZXQ1KCkpLCAoaW50KTApID0gMCk7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVj4gc3RhdGljIHNob3J0CgkJdGVzdChWIHYsIGludCoqKioqLCBkZWNsdHlwZSggKGdldDEoKS4qdikoZ2V0MigpLCBnZXQzKCksIGdldDQoKSwgZ2V0NSgpKSwgKGludCkwKSA9IDApOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFY+IHN0YXRpYyBpbnQKCQl0ZXN0KFYgdiwgaW50KioqKiosIGRlY2x0eXBlKChnZXQxKCktPip2KShnZXQyKCksIGdldDMoKSwgZ2V0NCgpLCBnZXQ1KCkpLCAoaW50KTApID0gMCk7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVj4gc3RhdGljIGNoYXIKCQl0ZXN0KFYgdiwgaW50KioqKiwgZGVjbHR5cGUoIHYgIChnZXQyKCksIGdldDMoKSwgZ2V0NCgpLCBnZXQ1KCkpLCAoaW50KTApID0gMCk7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVj4gc3RhdGljIHNob3J0CgkJdGVzdChWIHYsIGludCoqKiosIGRlY2x0eXBlKCAoZ2V0MigpLip2KShnZXQzKCksIGdldDQoKSwgZ2V0NSgpKSwgKGludCkwKSA9IDApOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFY+IHN0YXRpYyBpbnQKCQl0ZXN0KFYgdiwgaW50KioqKiwgZGVjbHR5cGUoKGdldDIoKS0+KnYpKGdldDMoKSwgZ2V0NCgpLCBnZXQ1KCkpLCAoaW50KTApID0gMCk7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVj4gc3RhdGljIGNoYXIKCQl0ZXN0KFYgdiwgaW50KioqLCBkZWNsdHlwZSggdiAgKGdldDMoKSwgZ2V0NCgpLCBnZXQ1KCkpLCAoaW50KTApID0gMCk7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVj4gc3RhdGljIHNob3J0CgkJdGVzdChWIHYsIGludCoqKiwgZGVjbHR5cGUoIChnZXQzKCkuKnYpKGdldDQoKSwgZ2V0NSgpKSwgKGludCkwKSA9IDApOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFY+IHN0YXRpYyBpbnQKCQl0ZXN0KFYgdiwgaW50KioqLCBkZWNsdHlwZSgoZ2V0MygpLT4qdikoZ2V0NCgpLCBnZXQ1KCkpLCAoaW50KTApID0gMCk7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVj4gc3RhdGljIGNoYXIKCQl0ZXN0KFYgdiwgaW50KiosIGRlY2x0eXBlKCB2ICAoZ2V0NCgpLCBnZXQ1KCkpLCAoaW50KTApID0gMCk7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVj4gc3RhdGljIHNob3J0CgkJdGVzdChWIHYsIGludCoqLCBkZWNsdHlwZSggKGdldDQoKS4qdikoZ2V0NSgpKSwgKGludCkwKSA9IDApOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFY+IHN0YXRpYyBpbnQKCQl0ZXN0KFYgdiwgaW50KiosIGRlY2x0eXBlKChnZXQ0KCktPip2KShnZXQ1KCkpLCAoaW50KTApID0gMCk7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVj4gc3RhdGljIGNoYXIKCQl0ZXN0KFYgdiwgaW50KiwgZGVjbHR5cGUoICAgdiAgKGdldDUoKSksIChpbnQpMCkgPSAwKTsKCXRlbXBsYXRlIDx0eXBlbmFtZSBWPiBzdGF0aWMgc2hvcnQKCQl0ZXN0KFYgdiwgaW50KiwgZGVjbHR5cGUoIChnZXQ1KCkuKnYpKCksIChpbnQpMCkgPSAwKTsKCXRlbXBsYXRlIDx0eXBlbmFtZSBWPiBzdGF0aWMgaW50CgkJdGVzdChWIHYsIGludCosIGRlY2x0eXBlKChnZXQ1KCktPip2KSgpLCAoaW50KTApID0gMCk7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVj4gc3RhdGljIGNoYXIKCQl0ZXN0KFYgdiwgaW50LCBkZWNsdHlwZSh2KCksIChpbnQpMCkgPSAwKTsKCXN0YXRpYyBsb25nIHRlc3QoLi4uKTsKCS8v44OV44Oq44O86Zai5pWw44GL44Oh44Oz44OQ6Zai5pWw44GL44Gr5b+c44GY44Gf5oi75YCk5Z6LICDvvIhpbnQqKioqKioqKioqIOOBricqJ+OBruaVsOOBr+W8leaVsOOBruaVsO+8iQoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0byAgICAgICAgLy8gRk3jga/jg5Xjg6rjg7zplqLmlbBvcuODoeODs+ODkOmWouaVsOOBruWNsAoJCXJldHVybl90KFYgdiwgaW50KioqKiosIEZNLCB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX3NhbWU8Rk0sIGNoYXI+Ojp2YWx1ZSwgVj46OnR5cGUqID0gMCkKCQkJLT5kZWNsdHlwZSh2KGdldDEoKSwgZ2V0MigpLCBnZXQzKCksIGdldDQoKSwgZ2V0NSgpKSk7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgViwgdHlwZW5hbWUgRk0+IHN0YXRpYyBhdXRvCgkJcmV0dXJuX3QoViB2LCBpbnQqKioqKiwgRk0sIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPHN0ZDo6aXNfc2FtZTxGTSwgc2hvcnQ+Ojp2YWx1ZSwgVj46OnR5cGUqID0gMCkKCQkJLT5kZWNsdHlwZSgoKGdldDEoKSkuKnYpKGdldDIoKSwgZ2V0MygpLCBnZXQ0KCksIGdldDUoKSkpOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0bwoJCXJldHVybl90KFYgdiwgaW50KioqKiosIEZNLCB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX3NhbWU8Rk0sIGludD46OnZhbHVlLCBWPjo6dHlwZSogPSAwKQoJCQktPmRlY2x0eXBlKCgoZ2V0MSgpKS0+KnYpKGdldDIoKSwgZ2V0MygpLCBnZXQ0KCksIGdldDUoKSkpOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0bwoJCXJldHVybl90KFYgdiwgaW50KioqKiwgRk0sIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPHN0ZDo6aXNfc2FtZTxGTSwgY2hhcj46OnZhbHVlLCBWPjo6dHlwZSogPSAwKQoJCQktPmRlY2x0eXBlKCAgICAgdihnZXQyKCksIGdldDMoKSwgZ2V0NCgpLCBnZXQ1KCkpKTsKCXRlbXBsYXRlIDx0eXBlbmFtZSBWLCB0eXBlbmFtZSBGTT4gc3RhdGljIGF1dG8KCQlyZXR1cm5fdChWIHYsIGludCoqKiosIEZNLCB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX3NhbWU8Rk0sIHNob3J0Pjo6dmFsdWUsIFY+Ojp0eXBlKiA9IDApCgkJCS0+ZGVjbHR5cGUoKCggZ2V0MigpKS4qdikoZ2V0MygpLCBnZXQ0KCksIGdldDUoKSkpOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0bwoJCXJldHVybl90KFYgdiwgaW50KioqKiwgRk0sIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPHN0ZDo6aXNfc2FtZTxGTSwgaW50Pjo6dmFsdWUsIFY+Ojp0eXBlKiA9IDApCgkJCS0+ZGVjbHR5cGUoKChnZXQyKCkpLT4qdikoZ2V0MygpLCBnZXQ0KCksIGdldDUoKSkpOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0bwoJCXJldHVybl90KFYgdiwgaW50KioqLCBGTSwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8c3RkOjppc19zYW1lPEZNLCBjaGFyPjo6dmFsdWUsIFY+Ojp0eXBlKiA9IDApCgkJCS0+ZGVjbHR5cGUoICAgICB2KGdldDMoKSwgZ2V0NCgpLCBnZXQ1KCkpKTsKCXRlbXBsYXRlIDx0eXBlbmFtZSBWLCB0eXBlbmFtZSBGTT4gc3RhdGljIGF1dG8KCQlyZXR1cm5fdChWIHYsIGludCoqKiwgRk0sIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPHN0ZDo6aXNfc2FtZTxGTSwgc2hvcnQ+Ojp2YWx1ZSwgVj46OnR5cGUqID0gMCkKCQkJLT5kZWNsdHlwZSgoKCBnZXQzKCkpLip2KShnZXQ0KCksIGdldDUoKSkpOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0bwoJCXJldHVybl90KFYgdiwgaW50KioqLCBGTSwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8c3RkOjppc19zYW1lPEZNLCBpbnQ+Ojp2YWx1ZSwgVj46OnR5cGUqID0gMCkKCQkJLT5kZWNsdHlwZSgoKGdldDMoKSktPip2KShnZXQ0KCksIGdldDUoKSkpOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0bwoJCXJldHVybl90KFYgdiwgaW50KiosIEZNLCB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX3NhbWU8Rk0sIGNoYXI+Ojp2YWx1ZSwgVj46OnR5cGUqID0gMCkKCQkJLT5kZWNsdHlwZSggICAgIHYoZ2V0NCgpLCBnZXQ1KCkpKTsKCXRlbXBsYXRlIDx0eXBlbmFtZSBWLCB0eXBlbmFtZSBGTT4gc3RhdGljIGF1dG8KCQlyZXR1cm5fdChWIHYsIGludCoqLCBGTSwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8c3RkOjppc19zYW1lPEZNLCBzaG9ydD46OnZhbHVlLCBWPjo6dHlwZSogPSAwKQoJCQktPmRlY2x0eXBlKCgoIGdldDQoKSkuKnYpKGdldDUoKSkpOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0bwoJCXJldHVybl90KFYgdiwgaW50KiosIEZNLCB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX3NhbWU8Rk0sIGludD46OnZhbHVlLCBWPjo6dHlwZSogPSAwKQoJCQktPmRlY2x0eXBlKCgoZ2V0NCgpKS0+KnYpKGdldDUoKSkpOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0bwoJCXJldHVybl90KFYgdiwgaW50KiwgRk0sIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPHN0ZDo6aXNfc2FtZTxGTSwgY2hhcj46OnZhbHVlLCBWPjo6dHlwZSogPSAwKQoJCQktPmRlY2x0eXBlKCAgICAgICB2KGdldDUoKSkpOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0bwoJCXJldHVybl90KFYgdiwgaW50KiwgRk0sIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPHN0ZDo6aXNfc2FtZTxGTSwgc2hvcnQ+Ojp2YWx1ZSwgVj46OnR5cGUqID0gMCkKCQkJLT5kZWNsdHlwZSgoKCBnZXQ1KCkpLip2KSgpKTsKCXRlbXBsYXRlIDx0eXBlbmFtZSBWLCB0eXBlbmFtZSBGTT4gc3RhdGljIGF1dG8KCQlyZXR1cm5fdChWIHYsIGludCosIEZNLCB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX3NhbWU8Rk0sIGludD46OnZhbHVlLCBWPjo6dHlwZSogPSAwKQoJCQktPmRlY2x0eXBlKCgoZ2V0NSgpKS0+KnYpKCkpOwoJdGVtcGxhdGUgPHR5cGVuYW1lIFYsIHR5cGVuYW1lIEZNPiBzdGF0aWMgYXV0bwoJCXJldHVybl90KFYgdiwgaW50LCBGTSwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8c3RkOjppc19zYW1lPEZNLCBjaGFyPjo6dmFsdWUsIFY+Ojp0eXBlKiA9IDApCgkJCS0+ZGVjbHR5cGUodigpKTsKCXN0YXRpYyBJTEwgcmV0dXJuX3QoLi4uKTsKfTsKLy8gNSBwYXJhbWV0ZXJzCnRlbXBsYXRlIDx0eXBlbmFtZSBGLCB0eXBlbmFtZSBQMSwgdHlwZW5hbWUgUDIsIHR5cGVuYW1lIFAzLCB0eXBlbmFtZSBQNCwgdHlwZW5hbWUgUDU+CnN0cnVjdCBmdW5jX3NpZ25hdHVyZV9iYXNlPEYsIFAxLCBQMiwgUDMsIFA0LCBQNSwgNT4gOiBmdW5jX3NpZ25hdHVyZV9iYXNlMDxGLCBQMSwgUDIsIFAzLCBQNCwgUDU+CXsKCXR5cGVkZWYgZnVuY19zaWduYXR1cmVfYmFzZTA8RiwgUDEsIFAyLCBQMywgUDQsIFA1PgkJCQkJQjsKCXR5cGVkZWYgZGVjbHR5cGUoQjo6dGVzdChCOjpnZXRGKCksKGludCoqKioqKTApKQkJCQkJZm1fdHlwZTsKCXR5cGVkZWYgZGVjbHR5cGUoQjo6cmV0dXJuX3QoQjo6Z2V0RigpLCAoaW50KioqKiopMCwgKGZtX3R5cGUpMCkpCXJldHVybl90eXBlOwp9OwovLyA0IHBhcmFtZXRlcnMKdGVtcGxhdGUgPHR5cGVuYW1lIEYsIHR5cGVuYW1lIFAxLCB0eXBlbmFtZSBQMiwgdHlwZW5hbWUgUDMsIHR5cGVuYW1lIFA0LCB0eXBlbmFtZSBQNT4Kc3RydWN0IGZ1bmNfc2lnbmF0dXJlX2Jhc2U8RiwgUDEsIFAyLCBQMywgUDQsIFA1LCA0PiA6IGZ1bmNfc2lnbmF0dXJlX2Jhc2UwPEYsIFAxLCBQMiwgUDMsIFA0LCBQNT4JewoJdHlwZWRlZiBmdW5jX3NpZ25hdHVyZV9iYXNlMDxGLCBQMSwgUDIsIFAzLCBQNCwgUDU+CQkJCQlCOwoJdHlwZWRlZiBkZWNsdHlwZShCOjp0ZXN0KEI6OmdldEYoKSwoaW50KioqKikwKSkJCQkJCQlmbV90eXBlOwoJdHlwZWRlZiBkZWNsdHlwZShCOjpyZXR1cm5fdChCOjpnZXRGKCksIChpbnQqKioqKTAsIChmbV90eXBlKTApKQlyZXR1cm5fdHlwZTsKfTsKLy8gMyBwYXJhbWV0ZXJzCnRlbXBsYXRlIDx0eXBlbmFtZSBGLCB0eXBlbmFtZSBQMSwgdHlwZW5hbWUgUDIsIHR5cGVuYW1lIFAzLCB0eXBlbmFtZSBQNCwgdHlwZW5hbWUgUDU+CnN0cnVjdCBmdW5jX3NpZ25hdHVyZV9iYXNlPEYsIFAxLCBQMiwgUDMsIFA0LCBQNSwgMz4gOiBmdW5jX3NpZ25hdHVyZV9iYXNlMDxGLCBQMSwgUDIsIFAzLCBQNCwgUDU+CXsKCXR5cGVkZWYgZnVuY19zaWduYXR1cmVfYmFzZTA8RiwgUDEsIFAyLCBQMywgUDQsIFA1PgkJCQkJQjsKCXR5cGVkZWYgZGVjbHR5cGUoQjo6dGVzdChCOjpnZXRGKCksKGludCoqKikwKSkJCQkJCQlmbV90eXBlOwoJdHlwZWRlZiBkZWNsdHlwZShCOjpyZXR1cm5fdChCOjpnZXRGKCksIChpbnQqKiopMCwgKGZtX3R5cGUpMCkpCQlyZXR1cm5fdHlwZTsKfTsKLy8gMiBwYXJhbWV0ZXJzCnRlbXBsYXRlIDx0eXBlbmFtZSBGLCB0eXBlbmFtZSBQMSwgdHlwZW5hbWUgUDIsIHR5cGVuYW1lIFAzLCB0eXBlbmFtZSBQNCwgdHlwZW5hbWUgUDU+CnN0cnVjdCBmdW5jX3NpZ25hdHVyZV9iYXNlPEYsIFAxLCBQMiwgUDMsIFA0LCBQNSwgMj4gOiBmdW5jX3NpZ25hdHVyZV9iYXNlMDxGLCBQMSwgUDIsIFAzLCBQNCwgUDU+CXsKCXR5cGVkZWYgZnVuY19zaWduYXR1cmVfYmFzZTA8RiwgUDEsIFAyLCBQMywgUDQsIFA1PgkJCQlCOwoJdHlwZWRlZiBkZWNsdHlwZShCOjp0ZXN0KEI6OmdldEYoKSwoaW50KiopMCkpCQkJCQlmbV90eXBlOwoJdHlwZWRlZiBkZWNsdHlwZShCOjpyZXR1cm5fdChCOjpnZXRGKCksIChpbnQqKikwLCAoZm1fdHlwZSkwKSkJcmV0dXJuX3R5cGU7Cn07Ci8vIDEgcGFyYW1ldGVycwp0ZW1wbGF0ZSA8dHlwZW5hbWUgRiwgdHlwZW5hbWUgUDEsIHR5cGVuYW1lIFAyLCB0eXBlbmFtZSBQMywgdHlwZW5hbWUgUDQsIHR5cGVuYW1lIFA1PgpzdHJ1Y3QgZnVuY19zaWduYXR1cmVfYmFzZTxGLCBQMSwgUDIsIFAzLCBQNCwgUDUsIDE+IDogZnVuY19zaWduYXR1cmVfYmFzZTA8RiwgUDEsIFAyLCBQMywgUDQsIFA1Pgl7Cgl0eXBlZGVmIGZ1bmNfc2lnbmF0dXJlX2Jhc2UwPEYsIFAxLCBQMiwgUDMsIFA0LCBQNT4JCQkJQjsKCXR5cGVkZWYgZGVjbHR5cGUoQjo6dGVzdChCOjpnZXRGKCksKGludCopMCkpCQkJCQlmbV90eXBlOwoJdHlwZWRlZiBkZWNsdHlwZShCOjpyZXR1cm5fdChCOjpnZXRGKCksIChpbnQqKTAsIChmbV90eXBlKTApKQlyZXR1cm5fdHlwZTsKfTsKLy8gMCBwYXJhbWV0ZXJzCnRlbXBsYXRlIDx0eXBlbmFtZSBGLCB0eXBlbmFtZSBQMSwgdHlwZW5hbWUgUDIsIHR5cGVuYW1lIFAzLCB0eXBlbmFtZSBQNCwgdHlwZW5hbWUgUDU+CnN0cnVjdCBmdW5jX3NpZ25hdHVyZV9iYXNlPEYsIFAxLCBQMiwgUDMsIFA0LCBQNSwgMD4gOiBmdW5jX3NpZ25hdHVyZV9iYXNlMDxGLCBQMSwgUDIsIFAzLCBQNCwgUDU+CXsKCXR5cGVkZWYgZnVuY19zaWduYXR1cmVfYmFzZTA8RiwgUDEsIFAyLCBQMywgUDQsIFA1PgkJCQlCOwoJdHlwZWRlZiBkZWNsdHlwZShCOjp0ZXN0KEI6OmdldEYoKSwoaW50KTApKQkJCQkJCWZtX3R5cGU7Cgl0eXBlZGVmIGRlY2x0eXBlKEI6OnJldHVybl90KEI6OmdldEYoKSwgKGludCkwLCAoZm1fdHlwZSkwKSkJcmV0dXJuX3R5cGU7Cn07Ci8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnRlbXBsYXRlIDx0eXBlbmFtZSBGLCB0eXBlbmFtZSBQMSwgdHlwZW5hbWUgUDIsIHR5cGVuYW1lIFAzLCB0eXBlbmFtZSBQNCwgdHlwZW5hbWUgUDUsCgkJCQkJICB0eXBlbmFtZSBBMSwgdHlwZW5hbWUgQTIsIHR5cGVuYW1lIEEzLCB0eXBlbmFtZSBBNCwgdHlwZW5hbWUgQTUsIGludCBOPgpzdHJ1Y3QgZnVuY19zaWduYXR1cmUgOiBmdW5jX3NpZ25hdHVyZV9iYXNlPHR5cGVuYW1lIGFsdF90eXBlPEYgLCBBMSwgQTIsIEEzLCBBNCwgQTU+Ojp0eXBlICwKCQkJCQkJCQkJCQl0eXBlbmFtZSBhbHRfdHlwZTxQMSwgQTEsIEEyLCBBMywgQTQsIEE1Pjo6dHlwZSAsCgkJCQkJCQkJCQkJdHlwZW5hbWUgYWx0X3R5cGU8UDIsIEExLCBBMiwgQTMsIEE0LCBBNT46OnR5cGUgLAoJCQkJCQkJCQkJCXR5cGVuYW1lIGFsdF90eXBlPFAzLCBBMSwgQTIsIEEzLCBBNCwgQTU+Ojp0eXBlICwKCQkJCQkJCQkJCQl0eXBlbmFtZSBhbHRfdHlwZTxQNCwgQTEsIEEyLCBBMywgQTQsIEE1Pjo6dHlwZSAsCgkJCQkJCQkJCQkJdHlwZW5hbWUgYWx0X3R5cGU8UDUsIEExLCBBMiwgQTMsIEE0LCBBNT46OnR5cGUgLAoJCQkJCQkJCQkJCU4JCQkJCQkJCQkJCQk+CnsJfTsKLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKdGVtcGxhdGUgPHR5cGVuYW1lIFA+CnN0cnVjdCBQYXJhbU9mCXsKCXR5cGVkZWYgUCBwYXJhbV90eXBlOwoJdHlwZWRlZiB0eXBlbmFtZSBzdGQ6OnJlbW92ZV9jdjx0eXBlbmFtZSBzdGQ6OnJlbW92ZV9yZWZlcmVuY2U8UD46OnR5cGU+Ojp0eXBlIG5ha2VkX3BhcmFtX3R5cGU7CglzdGF0aWMgY29uc3Qgc2l6ZV90IHBsYWNlaG9sZGVyID0gc3RkOjppc19wbGFjZWhvbGRlcjxuYWtlZF9wYXJhbV90eXBlPjo6dmFsdWU7CgltdXRhYmxlIFAgcGFyYW07CglQYXJhbU9mKFAgcCkgOiBwYXJhbShwKQl7CX0KCVBhcmFtT2YoY29uc3QgUGFyYW1PZjxQPiYgcCkgOiBwYXJhbShwLnBhcmFtKQl7CX0KfTsKLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy9wbGFjZWhvbGRlcuOBoOOBo+OBn+OCieWun+W8leaVsOOBq+WkieaPm+OBmeOCiyBTRklOQUUKdGVtcGxhdGUgPHR5cGVuYW1lIFAsIHR5cGVuYW1lIEExLCB0eXBlbmFtZSBBMiwgdHlwZW5hbWUgQTMsIHR5cGVuYW1lIEE0LCB0eXBlbmFtZSBBNT4KdHlwZW5hbWUgUDo6cGFyYW1fdHlwZQogICAgIHBhc3MoUCogcCwgQTEmJiBhMSwgQTImJiBhMiwgQTMmJiBhMywgQTQmJiBhNCwgQTUmJiBhNSwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8UDo6cGxhY2Vob2xkZXI9PTA+Ojp0eXBlKiA9IDApCgl7CXJldHVybiBwLT5wYXJhbTsJfQp0ZW1wbGF0ZSA8dHlwZW5hbWUgUCwgdHlwZW5hbWUgQTEsIHR5cGVuYW1lIEEyLCB0eXBlbmFtZSBBMywgdHlwZW5hbWUgQTQsIHR5cGVuYW1lIEE1PgpBMSYmIHBhc3MoUCogcCwgQTEmJiBhMSwgQTImJiBhMiwgQTMmJiBhMywgQTQmJiBhNCwgQTUmJiBhNSwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8UDo6cGxhY2Vob2xkZXI9PTE+Ojp0eXBlKiA9IDApCgl7CXJldHVybiBzdGQ6OmZvcndhcmQ8QTE+KGExKTsJfQp0ZW1wbGF0ZSA8dHlwZW5hbWUgUCwgdHlwZW5hbWUgQTEsIHR5cGVuYW1lIEEyLCB0eXBlbmFtZSBBMywgdHlwZW5hbWUgQTQsIHR5cGVuYW1lIEE1PgpBMiYmIHBhc3MoUCogcCwgQTEmJiBhMSwgQTImJiBhMiwgQTMmJiBhMywgQTQmJiBhNCwgQTUmJiBhNSwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8UDo6cGxhY2Vob2xkZXI9PTI+Ojp0eXBlKiA9IDApCgl7CXJldHVybiBzdGQ6OmZvcndhcmQ8QTI+KGEyKTsJfQp0ZW1wbGF0ZSA8dHlwZW5hbWUgUCwgdHlwZW5hbWUgQTEsIHR5cGVuYW1lIEEyLCB0eXBlbmFtZSBBMywgdHlwZW5hbWUgQTQsIHR5cGVuYW1lIEE1PgpBMyYmIHBhc3MoUCogcCwgQTEmJiBhMSwgQTImJiBhMiwgQTMmJiBhMywgQTQmJiBhNCwgQTUmJiBhNSwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8UDo6cGxhY2Vob2xkZXI9PTM+Ojp0eXBlKiA9IDApCgl7CXJldHVybiBzdGQ6OmZvcndhcmQ8QTM+KGEzKTsJfQp0ZW1wbGF0ZSA8dHlwZW5hbWUgUCwgdHlwZW5hbWUgQTEsIHR5cGVuYW1lIEEyLCB0eXBlbmFtZSBBMywgdHlwZW5hbWUgQTQsIHR5cGVuYW1lIEE1PgpBNCYmIHBhc3MoUCogcCwgQTEmJiBhMSwgQTImJiBhMiwgQTMmJiBhMywgQTQmJiBhNCwgQTUmJiBhNSwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8UDo6cGxhY2Vob2xkZXI9PTQ+Ojp0eXBlKiA9IDApCgl7CXJldHVybiBzdGQ6OmZvcndhcmQ8QTQ+KGE0KTsJfQp0ZW1wbGF0ZSA8dHlwZW5hbWUgUCwgdHlwZW5hbWUgQTEsIHR5cGVuYW1lIEEyLCB0eXBlbmFtZSBBMywgdHlwZW5hbWUgQTQsIHR5cGVuYW1lIEE1PgpBNSYmIHBhc3MoUCogcCwgQTEmJiBhMSwgQTImJiBhMiwgQTMmJiBhMywgQTQmJiBhNCwgQTUmJiBhNSwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8UDo6cGxhY2Vob2xkZXI9PTU+Ojp0eXBlKiA9IDApCgl7CXJldHVybiBzdGQ6OmZvcndhcmQ8QTU+KGE1KTsJfQovLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgp0ZW1wbGF0ZSA8aW50IE4sIHR5cGVuYW1lIFMsIHR5cGVuYW1lIFQgPSBjaGFyPiBzdHJ1Y3QgZXhlY3V0ZXI7Ci8vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCnRlbXBsYXRlIDx0eXBlbmFtZSBQLCB0eXBlbmFtZSBUID0gSUxMLCB0eXBlbmFtZSBGID0gUCwgaW50IE4gPSAwPgpzdHJ1Y3QgQmluZE9mIDogUGFyYW1PZjxQPgl7CglUCQkJdGFyZ2V0OwoJc3RhdGljIGNvbnN0IGludAlkZXB0aCA9IE47Cgl0eXBlZGVmIFQJCQl0YXJnZXRfdHlwZTsKCXR5cGVkZWYgRgkJCWZ1bmNfdHlwZTsKCXR5cGVkZWYgQmluZE9mPFAsIFQsIEYsIE4+CQkJCQkJCQlNeVQ7Cgl0eXBlZGVmIHR5cGVuYW1lIFBhcmFtT2Y8UD46OnBhcmFtX3R5cGUJCQkJCXBhcmFtX3R5cGU7Cgl0eXBlZGVmIHR5cGVuYW1lIHN0ZDo6Y29uZGl0aW9uYWw8TiA9PSAwLCBNeVQsIFQ+Ojp0eXBlCWJhY2tfdHlwZTsKCXR5cGVkZWYgdHlwZW5hbWUgc3RkOjpjb25kaXRpb25hbDxOID09IDAsIE15VCwgdHlwZW5hbWUgVDo6Zmlyc3RfdHlwZT46OnR5cGUJZmlyc3RfdHlwZTsKCUJpbmRPZihjb25zdCBQJiBwKSA6IFBhcmFtT2Y8UD4ocCksIHRhcmdldCgwKQkJewl9CS8vICBiaW5kT2bjgafmnaXjgosKCUJpbmRPZihjb25zdCBQIHAsIFQmIHQpIDogUGFyYW1PZjxQPihwKSwgdGFyZ2V0KHQpCXsJfQkvLyAgPDwg44Gn5p2l44KLCglCaW5kT2YoUCBwLCBUJiYgdCkgOiBQYXJhbU9mPFA+KHApLCB0YXJnZXQoKFQmJil0KQl7CX0JLy8gIDw8IOOBp+adpeOCiwoJQmluZE9mKE15VCYmIHQpIDogUGFyYW1PZjxQPih0KSwgdGFyZ2V0KChUJiYpKHQudGFyZ2V0KSkJewl9CgliYWNrX3R5cGUqIGdldFRhcmdldCgpIGNvbnN0CXsgcmV0dXJuIChkZXB0aCA9PSAwKT8gKGJhY2tfdHlwZSopdGhpczogKGJhY2tfdHlwZSopJnRhcmdldDsgfQoJZmlyc3RfdHlwZSogZ2V0MCgpIGNvbnN0CQl7IHJldHVybiAoZGVwdGggPT0gMCk/IChmaXJzdF90eXBlKil0aGlzOiBnZXRUYXJnZXQoKS0+Z2V0MCgpOyB9CgkvLwoJdGVtcGxhdGUgPHR5cGVuYW1lIEExLCB0eXBlbmFtZSBBMiwgdHlwZW5hbWUgQTMsIHR5cGVuYW1lIEE0LCB0eXBlbmFtZSBBNT4KCXN0cnVjdCBteVNpZ25hdHVyZQl7CgkJdHlwZWRlZiB0eXBlbmFtZSBteTo6ZnVuY19zaWduYXR1cmU8ZnVuY190eXBlLAoJCQkJCQkJCQkJCXR5cGVuYW1lIGJhY2tfdHlwZTo6YmFja190eXBlOjpiYWNrX3R5cGU6OmJhY2tfdHlwZTo6cGFyYW1fdHlwZSwKCQkJCQkJCQkJCQl0eXBlbmFtZSBiYWNrX3R5cGU6OmJhY2tfdHlwZTo6YmFja190eXBlOjpwYXJhbV90eXBlLAoJCQkJCQkJCQkJCXR5cGVuYW1lIGJhY2tfdHlwZTo6YmFja190eXBlOjpwYXJhbV90eXBlLAoJCQkJCQkJCQkJCXR5cGVuYW1lIGJhY2tfdHlwZTo6cGFyYW1fdHlwZSwKCQkJCQkJCQkJCQlwYXJhbV90eXBlLAoJCQkJCQkJCQkJCUExLCBBMiwgQTMsIEE0LCBBNSwgZGVwdGg+CgkJCQkJCXR5cGU7CgkJfTsKCS8vYmluZOOBmeOCi+WkieaVsOOCkui/veWKoOOBl+OBpuOBhOOBjyBvcGVyYXRvciA8PAoJdGVtcGxhdGUgPHR5cGVuYW1lIFBOPiBCaW5kT2Y8UE4sIE15VCwgZnVuY190eXBlLCBkZXB0aCArIDE+CgkJb3BlcmF0b3IgPDwoUE4mJiBwKQoJCQl7IHJldHVybiBCaW5kT2Y8UE4sIE15VCwgZnVuY190eXBlLCBkZXB0aCArIDE+KHN0ZDo6Zm9yd2FyZDxQTj4ocCksIChNeVQmJikqdGhpcyk7IH0KCS8vIOODleOCoeODs+OCr+OCv+OBqOOBl+OBpuOBriBvcGVyYXRvcihhLGIsYyxkLGUpCgl0ZW1wbGF0ZSA8dHlwZW5hbWUgQTEsIHR5cGVuYW1lIEEyLCB0eXBlbmFtZSBBMywgdHlwZW5hbWUgQTQsIHR5cGVuYW1lIEE1PgoJCWF1dG8gb3BlcmF0b3IgKCkoQTEmJiBhMSwgQTImJiBhMiwgQTMmJiBhMywgQTQmJiBhNCwgQTUmJiBhNSkgY29uc3QKCQktPnR5cGVuYW1lIG15U2lnbmF0dXJlPEExLCBBMiwgQTMsIEE0LCBBNT46OnR5cGU6OnJldHVybl90eXBlCgkJewoJCXR5cGVkZWYgdHlwZW5hbWUgbXlTaWduYXR1cmU8QTEsIEEyLCBBMywgQTQsIEE1Pjo6dHlwZQkJc2lnbmF0dXJlOwoJCWV4ZWN1dGVyPGRlcHRoLCBzaWduYXR1cmUsIHR5cGVuYW1lIHNpZ25hdHVyZTo6Zm1fdHlwZT4KCQkJdGhlRXhlY3V0ZXIocGFzcyhnZXQwKCksIGExLCBhMiwgYTMsIGE0LCBhNSkpOwoJCXJldHVybiB0aGVFeGVjdXRlcgoJCQkoCgkJCXBhc3MoZ2V0VGFyZ2V0KCktPmdldFRhcmdldCgpLT5nZXRUYXJnZXQoKS0+Z2V0VGFyZ2V0KCksIGExLCBhMiwgYTMsIGE0LCBhNSksCgkJCXBhc3MoZ2V0VGFyZ2V0KCktPmdldFRhcmdldCgpLT5nZXRUYXJnZXQoKSwgYTEsIGEyLCBhMywgYTQsIGE1KSwKCQkJcGFzcyhnZXRUYXJnZXQoKS0+Z2V0VGFyZ2V0KCksIGExLCBhMiwgYTMsIGE0LCBhNSksCgkJCXBhc3MoZ2V0VGFyZ2V0KCksIGExLCBhMiwgYTMsIGE0LCBhNSksCgkJCXBhc3ModGhpcywgYTEsIGEyLCBhMywgYTQsIGE1KQoJCQkpOwoJCX0KCS8vIOODleOCoeODs+OCr+OCv+OBqOOBl+OBpuOBriBvcGVyYXRvcihhLGIsYyxkKQoJdGVtcGxhdGUgPHR5cGVuYW1lIEExLCB0eXBlbmFtZSBBMiwgdHlwZW5hbWUgQTMsIHR5cGVuYW1lIEE0PgoJCWF1dG8gb3BlcmF0b3IgKCkoQTEmJiBhMSwgQTImJiBhMiwgQTMmJiBhMywgQTQmJiBhNCkgY29uc3QKCQktPnR5cGVuYW1lIG15U2lnbmF0dXJlPEExLCBBMiwgQTMsIEE0LCBJTEw+Ojp0eXBlOjpyZXR1cm5fdHlwZQoJCXsJcmV0dXJuICgqdGhpcykoKEExJiYpYTEsIChBMiYmKWEyLCAoQTMmJilhMywgKEE0JiYpYTQsIElMTCgwKSk7CX0KCS8vIOODleOCoeODs+OCr+OCv+OBqOOBl+OBpuOBriBvcGVyYXRvcihhLGIsYykKCXRlbXBsYXRlIDx0eXBlbmFtZSBBMSwgdHlwZW5hbWUgQTIsIHR5cGVuYW1lIEEzPgoJCWF1dG8gb3BlcmF0b3IgKCkoQTEmJiBhMSwgQTImJiBhMiwgQTMmJiBhMykgY29uc3QKCQktPnR5cGVuYW1lIG15U2lnbmF0dXJlPEExLCBBMiwgQTMsIElMTCwgSUxMPjo6dHlwZTo6cmV0dXJuX3R5cGUKCQl7CXJldHVybiAoKnRoaXMpKChBMSYmKWExLCAoQTImJilhMiwgKEEzJiYpYTMsIElMTCgwKSwgSUxMKDApKTsJfQoJLy8g44OV44Kh44Oz44Kv44K/44Go44GX44Gm44GuIG9wZXJhdG9yKGEsYikKCXRlbXBsYXRlIDx0eXBlbmFtZSBBMSwgdHlwZW5hbWUgQTI+CgkJYXV0byBvcGVyYXRvciAoKShBMSYmIGExLCBBMiYmIGEyKSBjb25zdAoJCS0+dHlwZW5hbWUgbXlTaWduYXR1cmU8QTEsIEEyLCBJTEwsIElMTCwgSUxMPjo6dHlwZTo6cmV0dXJuX3R5cGUKCQl7CXJldHVybiAoKnRoaXMpKChBMSYmKWExLCAoQTImJilhMiwgSUxMKDApLCBJTEwoMCksIElMTCgwKSk7CX0KCS8vIOODleOCoeODs+OCr+OCv+OBqOOBl+OBpuOBriBvcGVyYXRvcihhKQoJdGVtcGxhdGUgPHR5cGVuYW1lIEExPgoJCWF1dG8gb3BlcmF0b3IgKCkoQTEmJiBhMSkgY29uc3QKCQktPnR5cGVuYW1lIG15U2lnbmF0dXJlPEExLCBJTEwsIElMTCwgSUxMLCBJTEw+Ojp0eXBlOjpyZXR1cm5fdHlwZQoJCXsJcmV0dXJuICgqdGhpcykoKEExJiYpYTEsIElMTCgwKSwgSUxMKDApLCBJTEwoMCksIElMTCgwKSk7CX0KCS8vIOODleOCoeODs+OCr+OCv+OBqOOBl+OBpuOBriBvcGVyYXRvcih2b2lkKQoJYXV0byBvcGVyYXRvciAoKSgpIGNvbnN0CgkJLT50eXBlbmFtZSBteVNpZ25hdHVyZTxJTEwsIElMTCwgSUxMLCBJTEwsIElMTD46OnR5cGU6OnJldHVybl90eXBlCgkJewlyZXR1cm4gKCp0aGlzKShJTEwoMCksIElMTCgwKSwgSUxMKDApLCBJTEwoMCksIElMTCgwKSk7CX0KfTsKLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gZXhlY3V0ZSB3aXRoIDUgcGFyYW1ldGVycwp0ZW1wbGF0ZSA8dHlwZW5hbWUgUz4Kc3RydWN0IGV4ZWN1dGVyPDUsIFM+CXsKCXR5cGVkZWYgdHlwZW5hbWUgUzo6ZnVuY190eXBlIGZ1bmNfdHlwZTsKCWZ1bmNfdHlwZSBvcmdfZnVuY3Rpb247CglleGVjdXRlcihjb25zdCBmdW5jX3R5cGUmIGYpIDogb3JnX2Z1bmN0aW9uKGYpIHsgfSAKCXR5cGVuYW1lIFM6OnJldHVybl90eXBlIG9wZXJhdG9yICgpKHR5cGVuYW1lIFM6OnBhcmFtMV90eXBlIHAxLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0yX3R5cGUgcDIsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTNfdHlwZSBwMywKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtNF90eXBlIHA0LAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW01X3R5cGUgcDUpIGNvbnN0Cgl7CXJldHVybiBvcmdfZnVuY3Rpb24ocDEsIHAyLCBwMywgcDQsIHA1KTsJfQp9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgUz4Kc3RydWN0IGV4ZWN1dGVyPDUsIFMsIHNob3J0Pgl7Cgl0eXBlZGVmIHR5cGVuYW1lIFM6OmZ1bmNfdHlwZSBmdW5jX3R5cGU7CglmdW5jX3R5cGUgb3JnX2Z1bmN0aW9uOwoJZXhlY3V0ZXIoY29uc3QgZnVuY190eXBlJiBmKSA6IG9yZ19mdW5jdGlvbihmKSB7IH0gCgl0eXBlbmFtZSBTOjpyZXR1cm5fdHlwZSBvcGVyYXRvciAoKSh0eXBlbmFtZSBTOjpwYXJhbTFfdHlwZSBPYmosCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTJfdHlwZSBwMiwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtM190eXBlIHAzLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW00X3R5cGUgcDQsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTVfdHlwZSBwNSkgY29uc3QKCXsJcmV0dXJuIChPYmouKm9yZ19mdW5jdGlvbikocDIsIHAzLCBwNCwgcDUpOwl9Cn07CnRlbXBsYXRlIDx0eXBlbmFtZSBTPgpzdHJ1Y3QgZXhlY3V0ZXI8NSwgUywgaW50Pgl7Cgl0eXBlZGVmIHR5cGVuYW1lIFM6OmZ1bmNfdHlwZSBmdW5jX3R5cGU7CglmdW5jX3R5cGUgb3JnX2Z1bmN0aW9uOwoJZXhlY3V0ZXIoY29uc3QgZnVuY190eXBlJiBmKSA6IG9yZ19mdW5jdGlvbihmKSB7IH0gCgl0eXBlbmFtZSBTOjpyZXR1cm5fdHlwZSBvcGVyYXRvciAoKSh0eXBlbmFtZSBTOjpwYXJhbTFfdHlwZSBwT2JqLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0yX3R5cGUgcDIsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTNfdHlwZSBwMywKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtNF90eXBlIHA0LAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW01X3R5cGUgcDUpIGNvbnN0Cgl7CXJldHVybiAocE9iai0+Km9yZ19mdW5jdGlvbikocDIsIHAzLCBwNCwgcDUpOwl9Cn07Ci8vIGV4ZWN1dGUgd2l0aCA0IHBhcmFtZXRlcnMKdGVtcGxhdGUgPHR5cGVuYW1lIFM+CnN0cnVjdCBleGVjdXRlcjw0LCBTPgl7Cgl0eXBlZGVmIHR5cGVuYW1lIFM6OmZ1bmNfdHlwZSBmdW5jX3R5cGU7CglmdW5jX3R5cGUgb3JnX2Z1bmN0aW9uOwoJZXhlY3V0ZXIoY29uc3QgZnVuY190eXBlJiBmKSA6IG9yZ19mdW5jdGlvbihmKSB7IH0gCgl0eXBlbmFtZSBTOjpyZXR1cm5fdHlwZSBvcGVyYXRvciAoKSh0eXBlbmFtZSBTOjpwYXJhbTFfdHlwZSBwMSwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtMl90eXBlIHAyLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0zX3R5cGUgcDMsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTRfdHlwZSBwNCwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtNV90eXBlIHA1KSBjb25zdAoJewlyZXR1cm4gb3JnX2Z1bmN0aW9uKHAyLCBwMywgcDQsIHA1KTsJfQp9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgUz4Kc3RydWN0IGV4ZWN1dGVyPDQsIFMsIHNob3J0Pgl7Cgl0eXBlZGVmIHR5cGVuYW1lIFM6OmZ1bmNfdHlwZSBmdW5jX3R5cGU7CglmdW5jX3R5cGUgb3JnX2Z1bmN0aW9uOwoJZXhlY3V0ZXIoY29uc3QgZnVuY190eXBlJiBmKSA6IG9yZ19mdW5jdGlvbihmKSB7IH0gCgl0eXBlbmFtZSBTOjpyZXR1cm5fdHlwZSBvcGVyYXRvciAoKSh0eXBlbmFtZSBTOjpwYXJhbTFfdHlwZSBwMSwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtMl90eXBlIE9iaiwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtM190eXBlIHAzLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW00X3R5cGUgcDQsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTVfdHlwZSBwNSkgY29uc3QKCXsJcmV0dXJuIChPYmouKm9yZ19mdW5jdGlvbikocDMsIHA0LCBwNSk7CX0KfTsKdGVtcGxhdGUgPHR5cGVuYW1lIFM+CnN0cnVjdCBleGVjdXRlcjw0LCBTLCBpbnQ+CXsKCXR5cGVkZWYgdHlwZW5hbWUgUzo6ZnVuY190eXBlIGZ1bmNfdHlwZTsKCWZ1bmNfdHlwZSBvcmdfZnVuY3Rpb247CglleGVjdXRlcihjb25zdCBmdW5jX3R5cGUmIGYpIDogb3JnX2Z1bmN0aW9uKGYpIHsgfSAKCXR5cGVuYW1lIFM6OnJldHVybl90eXBlIG9wZXJhdG9yICgpKHR5cGVuYW1lIFM6OnBhcmFtMV90eXBlIHAxLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0yX3R5cGUgcE9iaiwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtM190eXBlIHAzLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW00X3R5cGUgcDQsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTVfdHlwZSBwNSkgY29uc3QKCXsJcmV0dXJuIChwT2JqLT4qb3JnX2Z1bmN0aW9uKShwMywgcDQsIHA1KTsJfQp9OwovLyBleGVjdXRlIHdpdGggMyBwYXJhbWV0ZXJzCnRlbXBsYXRlIDx0eXBlbmFtZSBTPgpzdHJ1Y3QgZXhlY3V0ZXI8MywgUz4JewoJdHlwZWRlZiB0eXBlbmFtZSBTOjpmdW5jX3R5cGUgZnVuY190eXBlOwoJZnVuY190eXBlIG9yZ19mdW5jdGlvbjsKCWV4ZWN1dGVyKGNvbnN0IGZ1bmNfdHlwZSYgZikgOiBvcmdfZnVuY3Rpb24oZikgeyB9IAoJdHlwZW5hbWUgUzo6cmV0dXJuX3R5cGUgb3BlcmF0b3IgKCkodHlwZW5hbWUgUzo6cGFyYW0xX3R5cGUgcDEsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTJfdHlwZSBwMiwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtM190eXBlIHAzLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW00X3R5cGUgcDQsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTVfdHlwZSBwNSkgY29uc3QKCXsJcmV0dXJuIG9yZ19mdW5jdGlvbihwMywgcDQsIHA1KTsJfQp9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgUz4Kc3RydWN0IGV4ZWN1dGVyPDMsIFMsIHNob3J0Pgl7Cgl0eXBlZGVmIHR5cGVuYW1lIFM6OmZ1bmNfdHlwZSBmdW5jX3R5cGU7CglmdW5jX3R5cGUgb3JnX2Z1bmN0aW9uOwoJZXhlY3V0ZXIoY29uc3QgZnVuY190eXBlJiBmKSA6IG9yZ19mdW5jdGlvbihmKSB7IH0gCgl0eXBlbmFtZSBTOjpyZXR1cm5fdHlwZSBvcGVyYXRvciAoKSh0eXBlbmFtZSBTOjpwYXJhbTFfdHlwZSBwMSwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtMl90eXBlIHAyLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0zX3R5cGUgT2JqLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW00X3R5cGUgcDQsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTVfdHlwZSBwNSkgY29uc3QKCXsJcmV0dXJuIChPYmouKm9yZ19mdW5jdGlvbikocDQsIHA1KTsJfQp9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgUz4Kc3RydWN0IGV4ZWN1dGVyPDMsIFMsIGludD4JewoJdHlwZWRlZiB0eXBlbmFtZSBTOjpmdW5jX3R5cGUgZnVuY190eXBlOwoJZnVuY190eXBlIG9yZ19mdW5jdGlvbjsKCWV4ZWN1dGVyKGNvbnN0IGZ1bmNfdHlwZSYgZikgOiBvcmdfZnVuY3Rpb24oZikgeyB9IAoJdHlwZW5hbWUgUzo6cmV0dXJuX3R5cGUgb3BlcmF0b3IgKCkodHlwZW5hbWUgUzo6cGFyYW0xX3R5cGUgcDEsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTJfdHlwZSBwMiwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtM190eXBlIHBPYmosCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTRfdHlwZSBwNCwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtNV90eXBlIHA1KSBjb25zdAoJewlyZXR1cm4gKHBPYmotPipvcmdfZnVuY3Rpb24pKHA0LCBwNSk7CX0KfTsKLy8gZXhlY3V0ZSB3aXRoIDIgcGFyYW1ldGVycwp0ZW1wbGF0ZSA8dHlwZW5hbWUgUz4Kc3RydWN0IGV4ZWN1dGVyPDIsIFM+CXsKCXR5cGVkZWYgdHlwZW5hbWUgUzo6ZnVuY190eXBlIGZ1bmNfdHlwZTsKCWZ1bmNfdHlwZSBvcmdfZnVuY3Rpb247CglleGVjdXRlcihjb25zdCBmdW5jX3R5cGUmIGYpIDogb3JnX2Z1bmN0aW9uKGYpIHsgfSAKCXR5cGVuYW1lIFM6OnJldHVybl90eXBlIG9wZXJhdG9yICgpKHR5cGVuYW1lIFM6OnBhcmFtMV90eXBlIHAxLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0yX3R5cGUgcDIsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTNfdHlwZSBwMywKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtNF90eXBlIHA0LAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW01X3R5cGUgcDUpIGNvbnN0Cgl7CXJldHVybiBvcmdfZnVuY3Rpb24ocDQsIHA1KTsJfQp9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgUz4Kc3RydWN0IGV4ZWN1dGVyPDIsIFMsIHNob3J0Pgl7Cgl0eXBlZGVmIHR5cGVuYW1lIFM6OmZ1bmNfdHlwZSBmdW5jX3R5cGU7CglmdW5jX3R5cGUgb3JnX2Z1bmN0aW9uOwoJZXhlY3V0ZXIoY29uc3QgZnVuY190eXBlJiBmKSA6IG9yZ19mdW5jdGlvbihmKSB7IH0gCgl0eXBlbmFtZSBTOjpyZXR1cm5fdHlwZSBvcGVyYXRvciAoKSh0eXBlbmFtZSBTOjpwYXJhbTFfdHlwZSBwMSwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtMl90eXBlIHAyLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0zX3R5cGUgcDMsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTRfdHlwZSBPYmosCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTVfdHlwZSBwNSkgY29uc3QKCXsJcmV0dXJuIChPYmouKm9yZ19mdW5jdGlvbikocDUpOwl9Cn07CnRlbXBsYXRlIDx0eXBlbmFtZSBTPgpzdHJ1Y3QgZXhlY3V0ZXI8MiwgUywgaW50Pgl7Cgl0eXBlZGVmIHR5cGVuYW1lIFM6OmZ1bmNfdHlwZSBmdW5jX3R5cGU7CglmdW5jX3R5cGUgb3JnX2Z1bmN0aW9uOwoJZXhlY3V0ZXIoY29uc3QgZnVuY190eXBlJiBmKSA6IG9yZ19mdW5jdGlvbihmKSB7IH0gCgl0eXBlbmFtZSBTOjpyZXR1cm5fdHlwZSBvcGVyYXRvciAoKSh0eXBlbmFtZSBTOjpwYXJhbTFfdHlwZSBwMSwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtMl90eXBlIHAyLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0zX3R5cGUgcDMsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTRfdHlwZSBwT2JqLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW01X3R5cGUgcDUpIGNvbnN0Cgl7CXJldHVybiAocE9iai0+Km9yZ19mdW5jdGlvbikocDUpOwl9Cn07Ci8vIGV4ZWN1dGUgd2l0aCAxIHBhcmFtZXRlcnMKdGVtcGxhdGUgPHR5cGVuYW1lIFM+CnN0cnVjdCBleGVjdXRlcjwxLCBTPgl7Cgl0eXBlZGVmIHR5cGVuYW1lIFM6OmZ1bmNfdHlwZSBmdW5jX3R5cGU7CglmdW5jX3R5cGUgb3JnX2Z1bmN0aW9uOwoJZXhlY3V0ZXIoY29uc3QgZnVuY190eXBlJiBmKSA6IG9yZ19mdW5jdGlvbihmKSB7IH0gCgl0eXBlbmFtZSBTOjpyZXR1cm5fdHlwZSBvcGVyYXRvciAoKSh0eXBlbmFtZSBTOjpwYXJhbTFfdHlwZSBwMSwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtMl90eXBlIHAyLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0zX3R5cGUgcDMsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTRfdHlwZSBwNCwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtNV90eXBlIHA1KSBjb25zdAoJewlyZXR1cm4gb3JnX2Z1bmN0aW9uKHA1KTsJfQp9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgUz4Kc3RydWN0IGV4ZWN1dGVyPDEsIFMsIHNob3J0Pgl7Cgl0eXBlZGVmIHR5cGVuYW1lIFM6OmZ1bmNfdHlwZSBmdW5jX3R5cGU7CglmdW5jX3R5cGUgb3JnX2Z1bmN0aW9uOwoJZXhlY3V0ZXIoY29uc3QgZnVuY190eXBlJiBmKSA6IG9yZ19mdW5jdGlvbihmKSB7IH0gCgl0eXBlbmFtZSBTOjpyZXR1cm5fdHlwZSBvcGVyYXRvciAoKSh0eXBlbmFtZSBTOjpwYXJhbTFfdHlwZSBwMSwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtMl90eXBlIHAyLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0zX3R5cGUgcDMsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTRfdHlwZSBwNCwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtNV90eXBlIE9iaikgY29uc3QKCXsJcmV0dXJuIChPYmouKm9yZ19mdW5jdGlvbikoKTsJfQp9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgUz4Kc3RydWN0IGV4ZWN1dGVyPDEsIFMsIGludD4JewoJdHlwZWRlZiB0eXBlbmFtZSBTOjpmdW5jX3R5cGUgZnVuY190eXBlOwoJZnVuY190eXBlIG9yZ19mdW5jdGlvbjsKCWV4ZWN1dGVyKGNvbnN0IGZ1bmNfdHlwZSYgZikgOiBvcmdfZnVuY3Rpb24oZikgeyB9IAoJdHlwZW5hbWUgUzo6cmV0dXJuX3R5cGUgb3BlcmF0b3IgKCkodHlwZW5hbWUgUzo6cGFyYW0xX3R5cGUgcDEsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTJfdHlwZSBwMiwKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtM190eXBlIHAzLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW00X3R5cGUgcDQsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTVfdHlwZSBwT2JqKSBjb25zdAoJewlyZXR1cm4gKHBPYmotPipvcmdfZnVuY3Rpb24pKCk7CX0KfTsKLy8gZXhlY3V0ZSB3aXRoIDAgcGFyYW1ldGVycwp0ZW1wbGF0ZSA8dHlwZW5hbWUgUz4Kc3RydWN0IGV4ZWN1dGVyPDAsIFM+CXsKCXR5cGVkZWYgdHlwZW5hbWUgUzo6ZnVuY190eXBlIGZ1bmNfdHlwZTsKCWZ1bmNfdHlwZSBvcmdfZnVuY3Rpb247CglleGVjdXRlcihjb25zdCBmdW5jX3R5cGUmIGYpIDogb3JnX2Z1bmN0aW9uKGYpIHsgfSAKCXR5cGVuYW1lIFM6OnJldHVybl90eXBlIG9wZXJhdG9yICgpKHR5cGVuYW1lIFM6OnBhcmFtMV90eXBlIHAxLAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW0yX3R5cGUgcDIsCgkJCQkJCQkJCQl0eXBlbmFtZSBTOjpwYXJhbTNfdHlwZSBwMywKCQkJCQkJCQkJCXR5cGVuYW1lIFM6OnBhcmFtNF90eXBlIHA0LAoJCQkJCQkJCQkJdHlwZW5hbWUgUzo6cGFyYW01X3R5cGUgcDUpIGNvbnN0Cgl7CXJldHVybiBvcmdfZnVuY3Rpb24oKTsJfQp9OwoKLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy/plqLmlbDjg53jgqTjg7Pjgr/ku6XlpJbjga7jgqrjg5bjgrjjgqfjgq/jg4gKdGVtcGxhdGUgPHR5cGVuYW1lIEY+CkJpbmRPZjx0eXBlbmFtZSBzdGQ6OnJlbW92ZV9yZWZlcmVuY2U8Rj46OnR5cGU+CmJpbmRPZihGJiYgZikKeyByZXR1cm4gQmluZE9mPHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX3JlZmVyZW5jZTxGPjo6dHlwZT4oc3RkOjpmb3J3YXJkPEY+KGYpKTsgfQoKLy/plqLmlbDjg53jgqTjg7Pjgr8KdGVtcGxhdGUgPHR5cGVuYW1lIEY+CkJpbmRPZjxGKj4KYmluZE9mKEYqIGYpCnsgcmV0dXJuIEJpbmRPZjxGKj4oZik7IH0KLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy/jg6bjg7zjgrbjgYzkvb/jgYYgYmluZOmWouaVsAp0ZW1wbGF0ZSA8dHlwZW5hbWUgRiwgdHlwZW5hbWUgUDE+CmF1dG8gYmluZChGJiYgZiwgUDEmJiBwMSktPmRlY2x0eXBlKGJpbmRPZihzdGQ6OmZvcndhcmQ8Rj4oZikpIDw8IHN0ZDo6Zm9yd2FyZDxQMT4ocDEpKQp7CXJldHVybiBiaW5kT2Yoc3RkOjpmb3J3YXJkPEY+KGYpKSA8PCBzdGQ6OmZvcndhcmQ8UDE+KHAxKTsJfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEYsIHR5cGVuYW1lIFAxLCB0eXBlbmFtZSBQMj4KYXV0byBiaW5kKEYmJiBmLCBQMSYmIHAxLCBQMiYmIHAyKS0+ZGVjbHR5cGUoYmluZE9mKHN0ZDo6Zm9yd2FyZDxGPihmKSkgPDwgc3RkOjpmb3J3YXJkPFAxPihwMSkgPDwgc3RkOjpmb3J3YXJkPFAyPihwMikpCnsJcmV0dXJuIGJpbmRPZihzdGQ6OmZvcndhcmQ8Rj4oZikpIDw8IHN0ZDo6Zm9yd2FyZDxQMT4ocDEpIDw8IHN0ZDo6Zm9yd2FyZDxQMj4ocDIpOwl9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRiwgdHlwZW5hbWUgUDEsIHR5cGVuYW1lIFAyLCB0eXBlbmFtZSBQMz4KYXV0byBiaW5kKEYmJiBmLCBQMSYmIHAxLCBQMiYmIHAyLCBQMyYmIHAzKS0+ZGVjbHR5cGUoYmluZE9mKHN0ZDo6Zm9yd2FyZDxGPihmKSkgPDwgc3RkOjpmb3J3YXJkPFAxPihwMSkKCQkJCQkJCQkJCQkJCSAgPDwgc3RkOjpmb3J3YXJkPFAyPihwMikgPDwgc3RkOjpmb3J3YXJkPFAzPihwMykpCnsJcmV0dXJuIGJpbmRPZihzdGQ6OmZvcndhcmQ8Rj4oZikpIDw8IHN0ZDo6Zm9yd2FyZDxQMT4ocDEpIDw8IHN0ZDo6Zm9yd2FyZDxQMj4ocDIpIDw8IHN0ZDo6Zm9yd2FyZDxQMz4ocDMpOwl9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRiwgdHlwZW5hbWUgUDEsIHR5cGVuYW1lIFAyLCB0eXBlbmFtZSBQMywgdHlwZW5hbWUgUDQ+CmF1dG8gYmluZChGJiYgZiwgUDEmJiBwMSwgUDImJiBwMiwgUDMmJiBwMywgUDQmJiBwNCkKCS0+ZGVjbHR5cGUoYmluZE9mKHN0ZDo6Zm9yd2FyZDxGPihmKSkgPDwgc3RkOjpmb3J3YXJkPFAxPihwMSkgPDwgc3RkOjpmb3J3YXJkPFAyPihwMikgPDwgc3RkOjpmb3J3YXJkPFAzPihwMykgPDwgc3RkOjpmb3J3YXJkPFA0PihwNCkpCnsJcmV0dXJuIGJpbmRPZihzdGQ6OmZvcndhcmQ8Rj4oZikpIDw8IHN0ZDo6Zm9yd2FyZDxQMT4ocDEpIDw8IHN0ZDo6Zm9yd2FyZDxQMj4ocDIpIDw8IHN0ZDo6Zm9yd2FyZDxQMz4ocDMpIDw8IHN0ZDo6Zm9yd2FyZDxQND4ocDQpOwl9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRiwgdHlwZW5hbWUgUDEsIHR5cGVuYW1lIFAyLCB0eXBlbmFtZSBQMywgdHlwZW5hbWUgUDQsIHR5cGVuYW1lIFA1PgphdXRvIGJpbmQoRiYmIGYsIFAxJiYgcDEsIFAyJiYgcDIsIFAzJiYgcDMsIFA0JiYgcDQsIFA1JiYgcDUpCgktPmRlY2x0eXBlKGJpbmRPZihzdGQ6OmZvcndhcmQ8Rj4oZikpIDw8IHN0ZDo6Zm9yd2FyZDxQMT4ocDEpIDw8IHN0ZDo6Zm9yd2FyZDxQMj4ocDIpIDw8IHN0ZDo6Zm9yd2FyZDxQMz4ocDMpCgkJCQkJCQkJCQkJPDwgc3RkOjpmb3J3YXJkPFA0PihwNCkgPDwgc3RkOjpmb3J3YXJkPFA1PihwNSkpCnsJcmV0dXJuIGJpbmRPZihzdGQ6OmZvcndhcmQ8Rj4oZikpIDw8IHN0ZDo6Zm9yd2FyZDxQMT4ocDEpIDw8IHN0ZDo6Zm9yd2FyZDxQMj4ocDIpIDw8IHN0ZDo6Zm9yd2FyZDxQMz4ocDMpCgkJCQkJCQkJCQk8PCBzdGQ6OmZvcndhcmQ8UDQ+KHA0KSA8PCBzdGQ6OmZvcndhcmQ8UDU+KHA1KTsJfQoKfSAvL25hbWVzcGFjZSBteQoKCi8vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vCi8vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCgppbnQgZjEoaW50IGEpCXsgcmV0dXJuIDEgKyBhOyB9CmludCBmMihpbnQgYSwgaW50JiBiKQl7IHJldHVybiBhICsgKGIgKj0gMTApOyB9CmludCBmMyhpbnQgYSwgaW50JiBiLCBpbnQgYykgeyByZXR1cm4gYSArIChiICo9IDIwKSArIGM7IH0KaW50IGY0KGludCBhLCBpbnQmIGIsIGludCBjLCBpbnQmIGQpIHsgcmV0dXJuIGEgKyAoYiAqPSAzMCkgKyBjICsgKGQgKz0gMzApOyB9CmludCBmNShpbnQgYSwgaW50JiBiLCBpbnQgYywgaW50JiBkLCBpbnQgZSkgeyByZXR1cm4gYSArIChiICo9IDQwKSArIGMgKyAoZCArPSA0MCkgKyBlOyB9CgpzdHJ1Y3QgRnVuYwl7CglpbnQgb3BlcmF0b3IgKCkoKSBjb25zdCB7IHJldHVybiAxMDAwOyB9CglpbnQgb3BlcmF0b3IgKCkoaW50IGEpIGNvbnN0IHsgcmV0dXJuIDEwMDAgKyBhOyB9CglpbnQgb3BlcmF0b3IgKCkoaW50IGEsIGludCYgYikgY29uc3QgeyByZXR1cm4gYSArIChiICo9IDEwMDApOyB9CglpbnQgb3BlcmF0b3IgKCkoaW50IGEsIGludCYgYiwgaW50IGMpIGNvbnN0IHsgcmV0dXJuIGEgKyAoYiAqPSAyMDAwKSArIGM7IH0KCWludCBvcGVyYXRvciAoKShpbnQgYSwgaW50JiBiLCBpbnQgYywgaW50JiBkKSBjb25zdCB7IHJldHVybiBhICsgKGIgKj0gMzAwMCkgKyBjICsgKGQgKz0gMzAwMCk7IH0KCWludCBmdW5jMCgpIGNvbnN0IHsgcmV0dXJuICgqdGhpcykoKTsgfQoJaW50IGZ1bmMxKGludCBhKSBjb25zdCB7IHJldHVybiAoKnRoaXMpKGEpOyB9CglpbnQgZnVuYzIoaW50IGEsIGludCYgYikgY29uc3QgeyByZXR1cm4gKCp0aGlzKShhLCBiKTsgfQoJaW50IGZ1bmMzKGludCBhLCBpbnQmIGIsIGludCBjKSBjb25zdCB7IHJldHVybiAoKnRoaXMpKGEsIGIsIGMpOyB9CglpbnQgZnVuYzQoaW50IGEsIGludCYgYiwgaW50IGMsIGludCYgZCkgY29uc3QgeyByZXR1cm4gKCp0aGlzKShhLCBiLCBjLCBkKTsgfQoJfTsKCiNpbmNsdWRlIDxpb3N0cmVhbT4KCmludCBtYWluKCkgewoJdXNpbmcgbmFtZXNwYWNlIHN0ZDo6cGxhY2Vob2xkZXJzOwoJaW50IGIgPSAxOwoJaW50IGQgPSAxOwoJaW50IHJlc3VsdCA9IDA7CgkKCXN0ZDo6Y291dCA8PCAi44OV44Oq44O86Zai5pWwIDHlpInmlbDjg5DjgqTjg7Pjg4kiIDw8IHN0ZDo6ZW5kbDsKCWF1dG8gYmYxMSA9IG15OjpiaW5kKGYxLCAxKTsKCXJlc3VsdCA9IGJmMTEoKTsKCXN0ZDo6Y291dCA8PCAiICBmMSgxKSA9ICIgPDwgcmVzdWx0IDw8ICdcbic7CglzdGQ6OmNvdXQgPDwgIuODleODquODvOmWouaVsCAx5aSJ5pWw44OQ44Kk44Oz44OJ44Gb44GaIiA8PCBzdGQ6OmVuZGw7CglhdXRvIGJmMTIgPSBteTo6YmluZChmMSwgXzEpOwoJcmVzdWx0ID0gYmYxMigyKTsKCXN0ZDo6Y291dCA8PCAiICBmMSgyKSA9ICIgPDwgcmVzdWx0IDw8ICdcbic7CglzdGQ6OmNvdXQgPDwgIuODleODquODvOmWouaVsCA15aSJ5pWwIiA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgIiAgYiA9ICIgPDwgYiA8PCAiLCBkID0gIiA8PCBkIDw8ICIgICAgICAiOwoJYXV0byBiZjUxID0gbXk6OmJpbmQoZjUsIDEsIF8xLCA4LCBkLCBfMik7CglyZXN1bHQgPSBiZjUxKGIsIDMpOwoJc3RkOjpjb3V0IDw8ICJmNSgxLCBiLCA4LCBkLCAzKSA9ICIgPDwgcmVzdWx0IDw8ICIgICAgICAgIGIgPSAiICA8PCBiIDw8ICIsIGQgPSAiIDw8IGQgPDwgc3RkOjplbmRsOwoJc3RkOjpjb3V0IDw8ICLjg5XjgqHjg7Pjgq/jgr8gNOWkieaVsCIgPDwgc3RkOjplbmRsOwoJYiA9IGQgPSAxOwoJRnVuYyBmbjsKCXN0ZDo6Y291dCA8PCAiICBiID0gIiA8PCBiIDw8ICIsIGQgPSAiIDw8IGQgPDwgIiAgICAgICI7CglhdXRvIGJmbjQgPSBteTo6YmluZChmbiwgMSwgXzEsIDIsIF8yKTsKCXJlc3VsdCA9IGJmbjQoYiwgZCk7CglzdGQ6OmNvdXQgPDwgImZuKDEsIGIsIDIsIGQpID0gIiA8PCByZXN1bHQgPDwgIiAgICAgICAgYiA9ICIgIDw8IGIgPDwgIiwgZCA9ICIgPDwgZCA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgIuODleOCoeODs+OCr+OCvyDjg6Hjg7Pjg5Djg53jgqTjg7Pjgr8iIDw8IHN0ZDo6ZW5kbDsKCWIgPSBkID0gMTsKCXN0ZDo6Y291dCA8PCAiICBiID0gIiA8PCBiIDw8ICIsIGQgPSAiIDw8IGQgPDwgIiAgICAgICI7CglhdXRvIGJmbjRtID0gbXk6OmJpbmQoJkZ1bmM6OmZ1bmM0LCBmbiwgMSwgXzEsIDIsIF8yKTsKCXJlc3VsdCA9IGJmbjRtKGIsIGQpOwoJc3RkOjpjb3V0IDw8ICJmbi4qbUYoMSwgYiwgMiwgZCkgPSAiIDw8IHJlc3VsdCA8PCAiICAgICAgICBiID0gIiAgPDwgYiA8PCAiLCBkID0gIiA8PCBkIDw8IHN0ZDo6ZW5kbDsKCWIgPSBkID0gMTsKCXN0ZDo6Y291dCA8PCAiICBiID0gIiA8PCBiIDw8ICIsIGQgPSAiIDw8IGQgPDwgIiAgICAgICI7CglhdXRvIGJmbjRtcCA9IG15OjpiaW5kKCZGdW5jOjpmdW5jNCwgJmZuLCAxLCBfMSwgMiwgXzIpOwoJcmVzdWx0ID0gYmZuNG1wKGIsIGQpOwoJc3RkOjpjb3V0IDw8ICJmbi0+Km1GKDEsIGIsIDIsIGQpID0gIiA8PCByZXN1bHQgPDwgIiAgICAgICAgYiA9ICIgIDw8IGIgPDwgIiwgZCA9ICIgPDwgZCA8PCBzdGQ6OmVuZGw7CgoJYiA9IGQgPSAxOwoJc3RkOjpjb3V0IDw8ICLnrKzkuIDlvJXmlbDjgoLjg5fjg6zjg7zjgrnjg5vjg6vjg4DjgavjgafjgY3jgosiIDw8IHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dCA8PCAiICBiID0gIiA8PCBiIDw8ICIsIGQgPSAiIDw8IGQgPDwgIiAgICAgICI7CglhdXRvIGJmbjRiMSA9IG15OjpiaW5kKF8xLCAmZm4sIDEwMSwgXzIsIDIwMiwgXzMpOwoJcmVzdWx0ID0gYmZuNGIxKCZGdW5jOjpmdW5jNCwgYiwgZCk7CglzdGQ6OmNvdXQgPDwgImZuLT4qbUYoMTAxLCBiLCAyMDIsIGQpID0gIiA8PCByZXN1bHQgPDwgIiAgICAgICAgYiA9ICIgIDw8IGIgPDwgIiwgZCA9ICIgPDwgZCA8PCBzdGQ6OmVuZGw7CgoJYiA9IGQgPSAyOwoJc3RkOjpjb3V0IDw8ICLjganjgZPjgavjgafjgoLnva7jgZHjgosiIDw8IHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dCA8PCAiICBiID0gIiA8PCBiIDw8ICIsIGQgPSAiIDw8IGQgPDwgIiAgICAgICI7CglhdXRvIGJmbjViRiA9IG15OjpiaW5kKF8zLCBmbiwgODEsIF8xLCA5MiwgXzIpOwoJcmVzdWx0ID0gYmZuNWJGKGIsIGQsICZGdW5jOjpmdW5jNCk7CglzdGQ6OmNvdXQgPDwgImZuLiptRig4MSwgYiwgOTIsIGQpID0gIiA8PCByZXN1bHQgPDwgIiAgICAgICAgYiA9ICIgIDw8IGIgPDwgIiwgZCA9ICIgPDwgZCA8PCBzdGQ6OmVuZGw7CglyZXR1cm4gMDsKfQo=