#include <iostream>
#include <type_traits>
namespace ParameterCheck {
namespace ParamGetter {
// Based on an answer from GManNickG ( http://stackoverflow.com/a/4693493/5386374 )
// Turn the type list into a single type we can use with std::is_same.
template < typename ... Ts > struct variadic_typedef { } ;
// Generic case, to catch passed parameter types list.
template < typename ... Ts > struct variadic_wrapper {
using type = variadic_typedef< Ts...> ;
} ;
// Special case to catch void parameter types list.
template <> struct variadic_wrapper<> {
using type = variadic_typedef< void > ;
} ;
// Generic case to isolate parameter list from function signature.
template < typename RT, typename ... Ts > struct variadic_wrapper< RT ( * ) ( Ts...) > {
using type = variadic_typedef< Ts...> ;
} ;
// Special case to isolate void parameter from function signature.
template < typename RT> struct variadic_wrapper< RT ( * ) ( ) > {
using type = variadic_typedef< void > ;
} ;
/*
template<typename... Ts> struct convert_in_tuple {
using type = std::tuple<Ts...>;
};
template<typename... Ts> struct convert_in_tuple<variadic_typedef<Ts...> > {
using type = typename convert_in_tuple<Ts...>::type;
};
*/
} // namespace ParamGetter
template < typename ... Ts > using PGetter = typename ParamGetter:: variadic_wrapper < Ts...> :: type ;
// template<typename... Ts> using PGetter = typename ParamGetter::convert_in_tuple<ParamGetter::variadic_typedef<Ts...> >::type;
// Declare class template.
template < typename ... Ts > struct parameter_match;
// Actual class. Becomes either std::true_type or std::false_type.
template < typename F, typename ... Ts > struct parameter_match< F, Ts...> : public std:: integral_constant < bool , std:: is_same < PGetter< F> , PGetter< Ts...> > { } > { } ;
} // namespace ParameterCheck
template < typename F, typename ... Ts > using PChecker = ParameterCheck:: parameter_match < F, Ts...> ;
// template<typename F, typename... Ts> using PChecker = ParameterCheck::parameter_match<F, Ts&...>;
// -------------------------
// Looking for a way to just grab the parameter list right out of the passed function, feel free to ignore this section for now.
namespace ParameterListCapture {
template < typename T> struct p_list;
template < typename RT> struct p_list< RT ( * ) ( ) > { } ;
/*
// Doesn't work, sadly.
template<typename RT, typename... Ts> struct p_list<RT (*)(Ts...)> {
using type = Ts...;
};
*/
} // namespace ParameterListCapture
// -------------------------
// The actual calling function.
template < typename Func, typename ... Ts > auto caller2( std:: true_type x, Func f, Ts... args ) {
std:: cout << "Now calling... " ;
return f( args...) ;
}
// Parameter mismatch overload.
template < typename Func, typename ... Ts > auto caller2( std:: false_type x, Func f, Ts... args ) {
std:: cout << "Parameter list mismatch." << std:: endl ;
}
// Wrapper to check for parameter mismatch.
template < typename Func, typename ... Ts > auto caller( Func f, Ts... args ) {
// return caller2(ParameterCheck::parameter_match<Func, Ts...>{}, f, args...);
return caller2( PChecker< Func, Ts...> { } , f, args...) ;
}
// -------------------------
void f1( ) { std:: cout << "Hi." << std:: endl ; }
int f2( int a, int b, int * c) {
std:: cout << a + b + * c << std:: endl ;
return b - a;
}
void f3( const int a, const bool b, bool c) { std:: cout << "Arguments? What arguments?" << std:: endl ; }
bool f4( int & a, const float b) { std:: cout << ( b > a) ; return ( a > b) ; }
void f5( const char * a) { std:: cout << a << std:: endl ; }
void f0( int & a) {
std:: cout << "f5(): Value is: " << a++ << std:: endl ;
std:: cout << "Incremented, returning." << std:: endl ;
}
void f01( int a) { std:: cout << "Let's see what this does." << std:: endl ; }
template < typename Func, typename ... Ts > void checker( Func f, Ts... args ) {
std:: cout << PChecker< Func, Ts...> { } << std:: endl ;
caller( f, args...) ;
}
template < typename Func, typename T> void passThrough2( Func f, T t) {
// template<typename Func, typename T> void passThrough2(Func f, T& t) { // Makes f0() work properly, but still not pass checker().
f( t) ;
std:: cout << "passThrough2(): Value is now: " << t << std:: endl ;
}
template < typename Func, typename ... Ts > void passThrough( Func f, Ts... args ) {
// template<typename Func, typename... Ts> void passThrough(Func f, Ts&... args) { // Makes f0() work properly, but still not pass checker().
std:: cout << "Passing through passThrough()..." << std:: endl ;
passThrough2( f, args...) ;
}
int main( ) {
int a = - 17 , x = 3 ;
int refA = a;
const float b = 1.2f ;
bool c = false ;
const char * d = "Hihihi.\n " ;
char * e = const_cast < char * > ( d) ;
std:: cout << std:: boolalpha ;
std:: cout << "Empty parameter list testing:" << std:: endl ;
std:: cout << "Testing (void(*)(), void): " ;
checker( f1) ;
std:: cout << "Testing (void(*)(), int): " ;
checker( f1, 3 ) ;
std:: cout << "Testing (void(*)(), void*): " ;
checker( f1, ( void * ) nullptr) ;
std:: cout << " - - - -" << std:: endl ;
std:: cout << "Standard parameters (including pointers) testing:" << std:: endl ;
std:: cout << "Testing (int(*)(int, int, int*), int, int, int*): " ;
checker( f2, 3 , 9 , & a) ;
std:: cout << "Testing (int(*)(int, int, int*), int*, int, int): " ;
checker( f2, & a, 3 , 9 ) ;
std:: cout << " - - - -" << std:: endl ;
std:: cout << "Const testing:" << std:: endl ;
std:: cout << "Testing (void(*)(const int, const bool, bool), int, bool [literal], bool [literal]): " ;
checker( f3, a, true , false ) ;
std:: cout << "Testing (void(*)(const int, const bool, bool), int [literal], bool, bool): " ;
checker( f3, 4 , c, c) ;
std:: cout << "Testing (void(*)(const char*), const char*): " ;
checker( f5, d) ;
std:: cout << "Testing (void(*)(const char*), char*): " ;
checker( f5, e) ;
std:: cout << "Adds const-ness to primitives during function call, but not to pointers." << std:: endl ;
std:: cout << " - - - -" << std:: endl ;
std:: cout << "Reference testing:" << std:: endl ;
std:: cout << "Testing (bool(*)(int&, const float), int&, const float): " ;
checker( f4, a, b) ;
std:: cout << "Testing (bool(*)(int&, const float), [explicit] int&, float): " ;
checker( f4, refA, b) ;
std:: cout << "Testing (bool(*)(int&, float), int&, int): " ;
checker( f4, a, a) ;
std:: cout << "Still some issues." << std:: endl ;
std:: cout << " - - - -" << std:: endl ;
std:: cout << "Testing passing reference through variadic template:" << std:: endl ;
std:: cout << "Variable 'x' original value: " << x << std:: endl ;
passThrough( f0, x) ;
std:: cout << "And finally, back in main(): 'x' new value: " << x << std:: endl ;
std:: cout << "Let's try it straight into passThrough2(): " << std:: endl ;
std:: cout << "x starting value: " << x << std:: endl ;
passThrough2( f0, x) ;
std:: cout << "x new value: " << x << std:: endl ;
std:: cout << "And now, one last thing, 1) passing (int) to template func expecting (int&):" << std:: endl ;
passThrough( f01, x) ;
std:: cout << "And 2) Checking function signatures:" << std:: endl ;
std:: cout << "Comment out the above checker() calls, and change \" Ts...\" to \" Ts&...\" in checker()." << std:: endl ;
std:: cout << "Also, use the second version of PChecker (currently commented out), instead of the first." << std:: endl ;
std:: cout << "Note that if we explicitly specify that a parameter [pack] is a reference(s) like this, PChecker matching to non-reference types will fail." << std:: endl ;
std:: cout << "Testing for (void(*)(int&), int&): " ;
checker( f0, x) ;
std:: cout << "Testing for (void(*)(int), int&): " ;
checker( f1, x) ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgogICAgbmFtZXNwYWNlIFBhcmFtZXRlckNoZWNrIHsKICAgICAgICBuYW1lc3BhY2UgUGFyYW1HZXR0ZXIgewogICAgICAgIAkvLyBCYXNlZCBvbiBhbiBhbnN3ZXIgZnJvbSBHTWFuTmlja0cgKCBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS80NjkzNDkzLzUzODYzNzQgKQogICAgICAgIAkKICAgICAgICAgICAgLy8gVHVybiB0aGUgdHlwZSBsaXN0IGludG8gYSBzaW5nbGUgdHlwZSB3ZSBjYW4gdXNlIHdpdGggc3RkOjppc19zYW1lLgogICAgICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBUcz4gc3RydWN0IHZhcmlhZGljX3R5cGVkZWYgeyB9OwoKICAgICAgICAgICAgLy8gR2VuZXJpYyBjYXNlLCB0byBjYXRjaCBwYXNzZWQgcGFyYW1ldGVyIHR5cGVzIGxpc3QuCiAgICAgICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lLi4uIFRzPiBzdHJ1Y3QgdmFyaWFkaWNfd3JhcHBlciB7CiAgICAgICAgICAgIAl1c2luZyB0eXBlID0gdmFyaWFkaWNfdHlwZWRlZjxUcy4uLj47CiAgICAgICAgICAgIH07CiAgCiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSB0byBjYXRjaCB2b2lkIHBhcmFtZXRlciB0eXBlcyBsaXN0LgogICAgICAgICAgICB0ZW1wbGF0ZTw+IHN0cnVjdCB2YXJpYWRpY193cmFwcGVyPD4gewogICAgICAgICAgICAJdXNpbmcgdHlwZSA9IHZhcmlhZGljX3R5cGVkZWY8dm9pZD47CiAgICAgICAgICAgIH07CgogICAgICAgICAgICAvLyBHZW5lcmljIGNhc2UgdG8gaXNvbGF0ZSBwYXJhbWV0ZXIgbGlzdCBmcm9tIGZ1bmN0aW9uIHNpZ25hdHVyZS4KICAgICAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgUlQsIHR5cGVuYW1lLi4uIFRzPiBzdHJ1Y3QgdmFyaWFkaWNfd3JhcHBlcjxSVCAoKikoVHMuLi4pPiB7CiAgICAgICAgICAgIAl1c2luZyB0eXBlID0gdmFyaWFkaWNfdHlwZWRlZjxUcy4uLj47CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIAogICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgdG8gaXNvbGF0ZSB2b2lkIHBhcmFtZXRlciBmcm9tIGZ1bmN0aW9uIHNpZ25hdHVyZS4KICAgICAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgUlQ+IHN0cnVjdCB2YXJpYWRpY193cmFwcGVyPFJUICgqKSgpPiB7CiAgICAgICAgICAgIAl1c2luZyB0eXBlID0gdmFyaWFkaWNfdHlwZWRlZjx2b2lkPjsKICAgICAgICAgICAgfTsKCi8qCiAgICAgICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lLi4uIFRzPiBzdHJ1Y3QgY29udmVydF9pbl90dXBsZSB7CiAgICAgICAgICAgICAgICB1c2luZyB0eXBlID0gc3RkOjp0dXBsZTxUcy4uLj47CiAgICAgICAgICAgIH07CgogICAgICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBUcz4gc3RydWN0IGNvbnZlcnRfaW5fdHVwbGU8dmFyaWFkaWNfdHlwZWRlZjxUcy4uLj4gPiB7CiAgICAgICAgICAgICAgICB1c2luZyB0eXBlID0gdHlwZW5hbWUgY29udmVydF9pbl90dXBsZTxUcy4uLj46OnR5cGU7CiAgICAgICAgICAgIH07CiovCiAgICAgICAgfSAvLyBuYW1lc3BhY2UgUGFyYW1HZXR0ZXIKICAgICAgICAKICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBUcz4gdXNpbmcgUEdldHRlciA9IHR5cGVuYW1lIFBhcmFtR2V0dGVyOjp2YXJpYWRpY193cmFwcGVyPFRzLi4uPjo6dHlwZTsKCi8vICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBUcz4gdXNpbmcgUEdldHRlciA9IHR5cGVuYW1lIFBhcmFtR2V0dGVyOjpjb252ZXJ0X2luX3R1cGxlPFBhcmFtR2V0dGVyOjp2YXJpYWRpY190eXBlZGVmPFRzLi4uPiA+Ojp0eXBlOwoKICAgICAgICAvLyBEZWNsYXJlIGNsYXNzIHRlbXBsYXRlLgogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lLi4uIFRzPiBzdHJ1Y3QgcGFyYW1ldGVyX21hdGNoOwoKICAgICAgICAvLyBBY3R1YWwgY2xhc3MuICBCZWNvbWVzIGVpdGhlciBzdGQ6OnRydWVfdHlwZSBvciBzdGQ6OmZhbHNlX3R5cGUuCiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgRiwgdHlwZW5hbWUuLi4gVHM+IHN0cnVjdCBwYXJhbWV0ZXJfbWF0Y2g8RiwgVHMuLi4+IDogcHVibGljIHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8Ym9vbCwgc3RkOjppc19zYW1lPFBHZXR0ZXI8Rj4sIFBHZXR0ZXI8VHMuLi4+ID57fT4ge307CiAgICB9IC8vIG5hbWVzcGFjZSBQYXJhbWV0ZXJDaGVjawogICAgCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBGLCB0eXBlbmFtZS4uLiBUcz4gdXNpbmcgUENoZWNrZXIgPSBQYXJhbWV0ZXJDaGVjazo6cGFyYW1ldGVyX21hdGNoPEYsIFRzLi4uPjsKICAgIC8vIHRlbXBsYXRlPHR5cGVuYW1lIEYsIHR5cGVuYW1lLi4uIFRzPiB1c2luZyBQQ2hlY2tlciA9IFBhcmFtZXRlckNoZWNrOjpwYXJhbWV0ZXJfbWF0Y2g8RiwgVHMmLi4uPjsKICAgIAovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgovLyBMb29raW5nIGZvciBhIHdheSB0byBqdXN0IGdyYWIgdGhlIHBhcmFtZXRlciBsaXN0IHJpZ2h0IG91dCBvZiB0aGUgcGFzc2VkIGZ1bmN0aW9uLCBmZWVsIGZyZWUgdG8gaWdub3JlIHRoaXMgc2VjdGlvbiBmb3Igbm93LgpuYW1lc3BhY2UgUGFyYW1ldGVyTGlzdENhcHR1cmUgewoJdGVtcGxhdGU8dHlwZW5hbWUgVD4gc3RydWN0IHBfbGlzdDsKCQoJdGVtcGxhdGU8dHlwZW5hbWUgUlQ+IHN0cnVjdCBwX2xpc3Q8UlQgKCopKCk+IHsgfTsKCQoJLyoKCS8vIERvZXNuJ3Qgd29yaywgc2FkbHkuCgl0ZW1wbGF0ZTx0eXBlbmFtZSBSVCwgdHlwZW5hbWUuLi4gVHM+IHN0cnVjdCBwX2xpc3Q8UlQgKCopKFRzLi4uKT4gewoJCXVzaW5nIHR5cGUgPSBUcy4uLjsKCX07CgkqLwoKfSAvLyBuYW1lc3BhY2UgUGFyYW1ldGVyTGlzdENhcHR1cmUKCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiAgICAvLyBUaGUgYWN0dWFsIGNhbGxpbmcgZnVuY3Rpb24uCnRlbXBsYXRlPHR5cGVuYW1lIEZ1bmMsIHR5cGVuYW1lLi4uIFRzPiBhdXRvIGNhbGxlcjIoc3RkOjp0cnVlX3R5cGUgeCwgRnVuYyBmLCBUcy4uLiBhcmdzKSB7CiAgICBzdGQ6OmNvdXQgPDwgIk5vdyBjYWxsaW5nLi4uICI7CiAgICByZXR1cm4gZihhcmdzLi4uKTsKfQoKLy8gUGFyYW1ldGVyIG1pc21hdGNoIG92ZXJsb2FkLgp0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jLCB0eXBlbmFtZS4uLiBUcz4gYXV0byBjYWxsZXIyKHN0ZDo6ZmFsc2VfdHlwZSB4LCBGdW5jIGYsIFRzLi4uIGFyZ3MpIHsKICAgIHN0ZDo6Y291dCA8PCAiUGFyYW1ldGVyIGxpc3QgbWlzbWF0Y2guIiA8PCBzdGQ6OmVuZGw7Cn0KCi8vIFdyYXBwZXIgdG8gY2hlY2sgZm9yIHBhcmFtZXRlciBtaXNtYXRjaC4KdGVtcGxhdGU8dHlwZW5hbWUgRnVuYywgdHlwZW5hbWUuLi4gVHM+IGF1dG8gY2FsbGVyKEZ1bmMgZiwgVHMuLi4gYXJncykgewogICAgLy8gcmV0dXJuIGNhbGxlcjIoUGFyYW1ldGVyQ2hlY2s6OnBhcmFtZXRlcl9tYXRjaDxGdW5jLCBUcy4uLj57fSwgZiwgYXJncy4uLik7CiAgICByZXR1cm4gY2FsbGVyMihQQ2hlY2tlcjxGdW5jLCBUcy4uLj57fSwgZiwgYXJncy4uLik7Cn0KICAgIAovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgp2b2lkIGYxKCkgeyBzdGQ6OmNvdXQgPDwgIkhpLiIgPDwgc3RkOjplbmRsOyB9CmludCBmMihpbnQgYSwgaW50IGIsIGludCogYykgewoJc3RkOjpjb3V0IDw8IGEgKyBiICsgKmMgPDwgc3RkOjplbmRsOwoJcmV0dXJuIGIgLSBhOwp9CnZvaWQgZjMoY29uc3QgaW50IGEsIGNvbnN0IGJvb2wgYiwgYm9vbCBjKSB7IHN0ZDo6Y291dCA8PCAiQXJndW1lbnRzPyAgV2hhdCBhcmd1bWVudHM/IiA8PCBzdGQ6OmVuZGw7IH0KYm9vbCBmNChpbnQmIGEsIGNvbnN0IGZsb2F0IGIpIHsgc3RkOjpjb3V0IDw8IChiID4gYSk7IHJldHVybiAoYSA+IGIpOyB9CnZvaWQgZjUoY29uc3QgY2hhciogYSkgeyBzdGQ6OmNvdXQgPDwgYSA8PCBzdGQ6OmVuZGw7IH0KCnZvaWQgZjAoaW50JiBhKSB7CglzdGQ6OmNvdXQgPDwgImY1KCk6IFZhbHVlIGlzOiAiIDw8IGErKyA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgIkluY3JlbWVudGVkLCByZXR1cm5pbmcuIiA8PCBzdGQ6OmVuZGw7Cn0KCnZvaWQgZjAxKGludCBhKSB7IHN0ZDo6Y291dCA8PCAiTGV0J3Mgc2VlIHdoYXQgdGhpcyBkb2VzLiIgPDwgc3RkOjplbmRsOyB9CgoKdGVtcGxhdGU8dHlwZW5hbWUgRnVuYywgdHlwZW5hbWUuLi4gVHM+IHZvaWQgY2hlY2tlcihGdW5jIGYsIFRzLi4uIGFyZ3MpIHsKCXN0ZDo6Y291dCA8PCBQQ2hlY2tlcjxGdW5jLCBUcy4uLj57fSA8PCBzdGQ6OmVuZGwgOwoJY2FsbGVyKGYsIGFyZ3MuLi4pOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jLCB0eXBlbmFtZSBUPiB2b2lkIHBhc3NUaHJvdWdoMihGdW5jIGYsIFQgdCkgewovLyB0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jLCB0eXBlbmFtZSBUPiB2b2lkIHBhc3NUaHJvdWdoMihGdW5jIGYsIFQmIHQpIHsgLy8gTWFrZXMgZjAoKSB3b3JrIHByb3Blcmx5LCBidXQgc3RpbGwgbm90IHBhc3MgY2hlY2tlcigpLgoJZih0KTsKCXN0ZDo6Y291dCA8PCAicGFzc1Rocm91Z2gyKCk6IFZhbHVlIGlzIG5vdzogIiA8PCB0IDw8IHN0ZDo6ZW5kbDsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgRnVuYywgdHlwZW5hbWUuLi4gVHM+IHZvaWQgcGFzc1Rocm91Z2goRnVuYyBmLCBUcy4uLiBhcmdzKSB7Ci8vIHRlbXBsYXRlPHR5cGVuYW1lIEZ1bmMsIHR5cGVuYW1lLi4uIFRzPiB2b2lkIHBhc3NUaHJvdWdoKEZ1bmMgZiwgVHMmLi4uIGFyZ3MpIHsgLy8gTWFrZXMgZjAoKSB3b3JrIHByb3Blcmx5LCBidXQgc3RpbGwgbm90IHBhc3MgY2hlY2tlcigpLgoJc3RkOjpjb3V0IDw8ICJQYXNzaW5nIHRocm91Z2ggcGFzc1Rocm91Z2goKS4uLiIgPDwgc3RkOjplbmRsOwoJcGFzc1Rocm91Z2gyKGYsIGFyZ3MuLi4pOwp9CgppbnQgbWFpbigpIHsKCWludCBhID0gLTE3LCB4ID0gMzsKCWludCByZWZBID0gYTsKCWNvbnN0IGZsb2F0IGIgPSAxLjJmOwoJYm9vbCBjID0gZmFsc2U7Cgljb25zdCBjaGFyKiBkID0gIkhpaGloaS5cbiI7CgljaGFyKiBlID0gY29uc3RfY2FzdDxjaGFyKj4oZCk7CglzdGQ6OmNvdXQgPDwgc3RkOjpib29sYWxwaGE7CgkKCXN0ZDo6Y291dCA8PCAiRW1wdHkgcGFyYW1ldGVyIGxpc3QgdGVzdGluZzoiIDw8IHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dCA8PCAiVGVzdGluZyAodm9pZCgqKSgpLCB2b2lkKTogIjsKCWNoZWNrZXIoZjEpOwoJCglzdGQ6OmNvdXQgPDwgIlRlc3RpbmcgKHZvaWQoKikoKSwgaW50KTogIjsKCWNoZWNrZXIoZjEsIDMpOwoJCglzdGQ6OmNvdXQgPDwgIlRlc3RpbmcgKHZvaWQoKikoKSwgdm9pZCopOiAiOwoJY2hlY2tlcihmMSwgKHZvaWQqKSBudWxscHRyKTsKCQoJc3RkOjpjb3V0IDw8ICIgLSAtIC0gLSIgPDwgc3RkOjplbmRsOwoJc3RkOjpjb3V0IDw8ICJTdGFuZGFyZCBwYXJhbWV0ZXJzIChpbmNsdWRpbmcgcG9pbnRlcnMpIHRlc3Rpbmc6IiA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgIlRlc3RpbmcgKGludCgqKShpbnQsIGludCwgaW50KiksIGludCwgaW50LCBpbnQqKTogIjsKCWNoZWNrZXIoZjIsIDMsIDksICZhKTsKCQoJc3RkOjpjb3V0IDw8ICJUZXN0aW5nIChpbnQoKikoaW50LCBpbnQsIGludCopLCBpbnQqLCBpbnQsIGludCk6ICI7CgljaGVja2VyKGYyLCAmYSwgMywgOSk7CgoJc3RkOjpjb3V0IDw8ICIgLSAtIC0gLSIgPDwgc3RkOjplbmRsOwoJc3RkOjpjb3V0IDw8ICJDb25zdCB0ZXN0aW5nOiIgPDwgc3RkOjplbmRsOwoJc3RkOjpjb3V0IDw8ICJUZXN0aW5nICh2b2lkKCopKGNvbnN0IGludCwgY29uc3QgYm9vbCwgYm9vbCksIGludCwgYm9vbCBbbGl0ZXJhbF0sIGJvb2wgW2xpdGVyYWxdKTogIjsKCWNoZWNrZXIoZjMsIGEsIHRydWUsIGZhbHNlKTsKCQoJc3RkOjpjb3V0IDw8ICJUZXN0aW5nICh2b2lkKCopKGNvbnN0IGludCwgY29uc3QgYm9vbCwgYm9vbCksIGludCBbbGl0ZXJhbF0sIGJvb2wsIGJvb2wpOiAiOwoJY2hlY2tlcihmMywgNCwgYywgYyk7CgkKCXN0ZDo6Y291dCA8PCAiVGVzdGluZyAodm9pZCgqKShjb25zdCBjaGFyKiksIGNvbnN0IGNoYXIqKTogIjsKCWNoZWNrZXIoZjUsIGQpOwoJCglzdGQ6OmNvdXQgPDwgIlRlc3RpbmcgKHZvaWQoKikoY29uc3QgY2hhciopLCBjaGFyKik6ICI7CgljaGVja2VyKGY1LCBlKTsKCXN0ZDo6Y291dCA8PCAiQWRkcyBjb25zdC1uZXNzIHRvIHByaW1pdGl2ZXMgZHVyaW5nIGZ1bmN0aW9uIGNhbGwsIGJ1dCBub3QgdG8gcG9pbnRlcnMuIiA8PCBzdGQ6OmVuZGw7CgoJc3RkOjpjb3V0IDw8ICIgLSAtIC0gLSIgPDwgc3RkOjplbmRsOwogICAgc3RkOjpjb3V0IDw8ICJSZWZlcmVuY2UgdGVzdGluZzoiIDw8IHN0ZDo6ZW5kbDsJCglzdGQ6OmNvdXQgPDwgIlRlc3RpbmcgKGJvb2woKikoaW50JiwgY29uc3QgZmxvYXQpLCBpbnQmLCBjb25zdCBmbG9hdCk6ICI7CgljaGVja2VyKGY0LCBhLCBiKTsKCQoJc3RkOjpjb3V0IDw8ICJUZXN0aW5nIChib29sKCopKGludCYsIGNvbnN0IGZsb2F0KSwgW2V4cGxpY2l0XSBpbnQmLCBmbG9hdCk6ICI7CgljaGVja2VyKGY0LCByZWZBLCBiKTsKCQoJc3RkOjpjb3V0IDw8ICJUZXN0aW5nIChib29sKCopKGludCYsIGZsb2F0KSwgaW50JiwgaW50KTogIjsKCWNoZWNrZXIoZjQsIGEsIGEpOwoJc3RkOjpjb3V0IDw8ICJTdGlsbCBzb21lIGlzc3Vlcy4iIDw8IHN0ZDo6ZW5kbDsKCQoJc3RkOjpjb3V0IDw8ICIgLSAtIC0gLSIgPDwgc3RkOjplbmRsOwoJc3RkOjpjb3V0IDw8ICJUZXN0aW5nIHBhc3NpbmcgcmVmZXJlbmNlIHRocm91Z2ggdmFyaWFkaWMgdGVtcGxhdGU6IiA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgIlZhcmlhYmxlICd4JyBvcmlnaW5hbCB2YWx1ZTogIiA8PCB4IDw8IHN0ZDo6ZW5kbDsKCXBhc3NUaHJvdWdoKGYwLCB4KTsKCXN0ZDo6Y291dCA8PCAiQW5kIGZpbmFsbHksIGJhY2sgaW4gbWFpbigpOiAneCcgbmV3IHZhbHVlOiAiIDw8IHggPDwgc3RkOjplbmRsOwoKCXN0ZDo6Y291dCA8PCAiTGV0J3MgdHJ5IGl0IHN0cmFpZ2h0IGludG8gcGFzc1Rocm91Z2gyKCk6ICIgPDwgc3RkOjplbmRsOwoJc3RkOjpjb3V0IDw8ICJ4IHN0YXJ0aW5nIHZhbHVlOiAiIDw8IHggPDwgc3RkOjplbmRsOwoJcGFzc1Rocm91Z2gyKGYwLCB4KTsKCXN0ZDo6Y291dCA8PCAieCBuZXcgdmFsdWU6ICIgPDwgeCA8PCBzdGQ6OmVuZGw7CgkKCXN0ZDo6Y291dCA8PCAiQW5kIG5vdywgb25lIGxhc3QgdGhpbmcsIDEpIHBhc3NpbmcgKGludCkgdG8gdGVtcGxhdGUgZnVuYyBleHBlY3RpbmcgKGludCYpOiIgPDwgc3RkOjplbmRsOwoJcGFzc1Rocm91Z2goZjAxLCB4KTsKCQoJc3RkOjpjb3V0IDw8ICJBbmQgMikgQ2hlY2tpbmcgZnVuY3Rpb24gc2lnbmF0dXJlczoiIDw8IHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dCA8PCAiQ29tbWVudCBvdXQgdGhlIGFib3ZlIGNoZWNrZXIoKSBjYWxscywgYW5kIGNoYW5nZSBcIlRzLi4uXCIgdG8gXCJUcyYuLi5cIiBpbiBjaGVja2VyKCkuIiA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgIkFsc28sIHVzZSB0aGUgc2Vjb25kIHZlcnNpb24gb2YgUENoZWNrZXIgKGN1cnJlbnRseSBjb21tZW50ZWQgb3V0KSwgaW5zdGVhZCBvZiB0aGUgZmlyc3QuIiA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgIk5vdGUgdGhhdCBpZiB3ZSBleHBsaWNpdGx5IHNwZWNpZnkgdGhhdCBhIHBhcmFtZXRlciBbcGFja10gaXMgYSByZWZlcmVuY2UocykgbGlrZSB0aGlzLCBQQ2hlY2tlciBtYXRjaGluZyB0byBub24tcmVmZXJlbmNlIHR5cGVzIHdpbGwgZmFpbC4iIDw8IHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dCA8PCAiVGVzdGluZyBmb3IgKHZvaWQoKikoaW50JiksIGludCYpOiAiOwoJY2hlY2tlcihmMCwgeCk7CglzdGQ6OmNvdXQgPDwgIlRlc3RpbmcgZm9yICh2b2lkKCopKGludCksIGludCYpOiAiOwoJY2hlY2tlcihmMSwgeCk7CgkKCQp9