#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