/*
The Great Type Loophole
This example is part of the blog post http://a...content-available-to-author-only...b.io/type-loophole.html
The main function is at the bottom.
*/
#include <type_traits>
#include <utility>
#include <cstdio>
#include <typeinfo>
#include <string>
#include <vector>
/************* luple.h ***************/
/*
This header is for the luple (a lightweight tuple) which is useful to work with a type list.
Source code with comments: https://g...content-available-to-author-only...b.com/alexpolt/luple/blob/master/luple.h
The header for the type loophole comes next.
*/
namespace luple_ns {
template < typename ... TT > struct type_list { static const int size = sizeof ...( TT) ; } ;
template < typename T, int N, int M = 0 > struct tlist_get;
template < int N, int M, typename T, typename ... TT > struct tlist_get< type_list< T, TT...> , N, M > {
static_assert( N < ( int ) sizeof ...( TT) + 1 + M, "type index out of bounds" ) ;
using type = std:: conditional_t < N == M, T, typename tlist_get< type_list< TT...> , N, M + 1 > :: type > ;
} ;
template < int N, int M> struct tlist_get< type_list<> , N, M > { using type = void ; } ;
template < int N> struct tlist_get< type_list<> , N, 0 > { } ;
template < typename T, int N>
using tlist_get_t = typename tlist_get< T, N> :: type ;
template < typename T, typename U, int N = 0 > struct tlist_get_n;
template < typename U, int N, typename T, typename ... TT > struct tlist_get_n< type_list< T, TT...> , U, N > {
static const int value = std:: is_same < T, U > :: value ? N : tlist_get_n< type_list< TT...> , U, N + 1 > :: value ;
} ;
template < typename U, int N> struct tlist_get_n< type_list<> , U, N > {
static const int value = - 1 ;
} ;
template < typename T, int N> struct tuple_element {
tlist_get_t< T, N> value;
} ;
template < typename T, typename U> struct tuple_base;
template < typename ... TT , int ... NN >
struct tuple_base< type_list< TT...> , std:: integer_sequence < int , NN...> > : tuple_element< type_list< TT...> , NN > ... {
using tlist = type_list< TT...> ;
template < typename ... UU , typename U = std:: enable_if_t < sizeof ...( UU) == sizeof ...( NN) >>
constexpr tuple_base ( UU&& ... args ) : tuple_element< tlist, NN > { std:: forward < UU> ( args) } ... { }
constexpr tuple_base ( TT const & ... args ) : tuple_element< tlist, NN > { args } ... { }
constexpr tuple_base ( TT&& ... args ) : tuple_element< tlist, NN > { std:: move ( args) } ... { }
constexpr tuple_base ( ) { }
} ;
template < typename T> struct tuple : tuple_base< T, std:: make_integer_sequence < int , T:: size > > {
using type_list = T;
using base = tuple_base< T, std:: make_integer_sequence < int , T:: size > > ;
template < int N> constexpr auto & get( ) {
static_assert( N < T:: size , "tuple::get -> out of bounds access" ) ;
return tuple_element< T, N > :: value ;
}
template < typename U> constexpr auto & get( ) {
static_assert( tlist_get_n< T, U> :: value ! = - 1 , "no such type in type list" ) ;
return tuple_element< T, tlist_get_n< T, U> :: value > :: value ;
}
template < int N> constexpr auto & get( ) const {
static_assert( N < T:: size , "tuple::get -> out of bounds access" ) ;
return tuple_element< T, N > :: value ;
}
template < typename U> constexpr auto & get( ) const {
static_assert( tlist_get_n< T, U> :: value ! = - 1 , "no such type in type list" ) ;
return tuple_element< T, tlist_get_n< T, U> :: value > :: value ;
}
using base:: base ;
} ;
template < int N, typename T> constexpr auto & get ( tuple< T> & t ) { return t.template get< N> ( ) ; }
template < typename U, typename T> constexpr auto & get ( tuple< T> & t ) { return t.template get< U> ( ) ; }
template < int N, typename T> constexpr auto & get ( tuple< T> const & t ) { return t.template get< N> ( ) ; }
template < typename U, typename T> constexpr auto & get ( tuple< T> const & t ) { return t.template get< U> ( ) ; }
template < typename T> constexpr auto size ( tuple< T> const & t ) { return T:: size ; }
template < typename U, typename T> constexpr auto index ( tuple< T> const & t ) { return tlist_get_n< T, U > :: value ; }
template < typename T, int N>
using element_t = tlist_get_t< typename T:: type_list , N > ;
template < typename T> struct luple_impl {
using type = tuple< T> ;
} ;
template < typename ... TT > struct luple_impl< type_list< type_list< TT...> > > {
using type = typename luple_impl< type_list< TT...> > :: type ;
} ;
template < typename ... TT >
using luple = typename luple_impl< type_list< TT...> > :: type ;
template < int ... N , typename T0, typename T1>
void luple_do_impl ( std:: integer_sequence < int , N...> , T0& t, T1 fn) {
char dummy[ ] { ( fn( get< N> ( t) ) , char { } ) ... } ;
( void ) dummy;
}
template < typename T0, typename T1>
void luple_do ( T0& t, T1 fn) {
luple_do_impl( std:: make_integer_sequence < int , T0:: type_list :: size > { } , t, fn ) ;
}
}
using luple_ns:: luple ;
using luple_ns:: get ;
using luple_ns:: index ;
/************* end of luple.h ***************/
/************* type-loophole.h ***************/
/*
This header is for the Great Type Loophole.
Source code with comments: https://g...content-available-to-author-only...b.com/alexpolt/luple/blob/master/type-loophole.h
*/
namespace loophole_ns {
template < typename T, int N>
struct tag {
friend auto loophole( tag< T,N> ) ;
constexpr friend int cloophole( tag< T,N> ) ;
} ;
template < typename T, typename U, int N, bool B>
struct fn_def {
friend auto loophole( tag< T,N> ) { return U{ } ; }
constexpr friend int cloophole( tag< T,N> ) { return 0 ; }
} ;
template < typename T, typename U, int N>
struct fn_def< T, U, N, true > { } ;
template < typename T, int N>
struct c_op {
template < typename U, int M> static auto ins( ...) - > int ;
template < typename U, int M, int = cloophole( tag< T,M> { } ) > static auto ins( int ) - > char ;
template < typename U, int = sizeof ( fn_def< T, U, N, sizeof ( ins< U, N> ( 0 ) ) == sizeof ( char ) > ) >
operator U( ) ;
} ;
template < typename T, int ... NN >
constexpr int fields_number( ...) { return sizeof ...( NN) - 1 ; }
template < typename T, int ... NN >
constexpr auto fields_number( int ) - > decltype( T{ c_op< T,NN> { } ... } , 0 ) {
return fields_number< T, NN..., sizeof ...( NN) > ( 0 ) ;
}
template < typename T, typename U>
struct loophole_type_list;
template < typename T, int ... NN >
struct loophole_type_list< T, std:: integer_sequence < int , NN...> > {
using type = luple_ns:: type_list < decltype( loophole( tag< T, NN> { } ) ) ... > ;
} ;
template < typename T>
using as_type_list =
typename loophole_type_list< T, std:: make_integer_sequence < int , fields_number< T> ( 0 ) >> :: type ;
}
struct test1 {
test1( ) {
printf ( "test::test()\n " ) ;
}
} ;
struct data {
test1 t0;
std:: string t1;
std:: vector < int > t2;
} ;
int main( ) {
using data_tlist = loophole_ns:: as_type_list < data > ;
using data_luple = luple< data_tlist > ;
data d{ { } , "Hello World!" , { 1 ,2 ,3 } } ;
auto & l = reinterpret_cast < data_luple& > ( d ) ;
printf ( "%s\n " , get< std:: string > ( l) .data ( ) ) ;
for ( auto i : get< 2 > ( l) ) printf ( "%d, " ,i) ;
puts ( "" ) ;
luple_ns:: element_t < data_luple,1 > & str = get< 1 > ( l) ;
str = "Welcome the the New World!" ;
printf ( "%s\n \n " , str.data ( ) ) ;
luple_do( l, [ i= 0 ] ( auto & value ) mutable { printf ( "field %d: %s\n " , i++ , typeid ( value) .name ( ) ) ; } ) ;
}
LyoKICBUaGUgR3JlYXQgVHlwZSBMb29waG9sZQoKICBUaGlzIGV4YW1wbGUgaXMgcGFydCBvZiB0aGUgYmxvZyBwb3N0IGh0dHA6Ly9hLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5iLmlvL3R5cGUtbG9vcGhvbGUuaHRtbAoKICBUaGUgbWFpbiBmdW5jdGlvbiBpcyBhdCB0aGUgYm90dG9tLgoqLwoKI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8dXRpbGl0eT4KCiNpbmNsdWRlIDxjc3RkaW8+CiNpbmNsdWRlIDx0eXBlaW5mbz4KCiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx2ZWN0b3I+CgoKLyoqKioqKioqKioqKiogIGx1cGxlLmggKioqKioqKioqKioqKioqLwoKLyogCiAgVGhpcyBoZWFkZXIgaXMgZm9yIHRoZSBsdXBsZSAoYSBsaWdodHdlaWdodCB0dXBsZSkgd2hpY2ggaXMgdXNlZnVsIHRvIHdvcmsgd2l0aCBhIHR5cGUgbGlzdC4KICBTb3VyY2UgY29kZSB3aXRoIGNvbW1lbnRzOiBodHRwczovL2cuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmIuY29tL2FsZXhwb2x0L2x1cGxlL2Jsb2IvbWFzdGVyL2x1cGxlLmgKCiAgVGhlIGhlYWRlciBmb3IgdGhlIHR5cGUgbG9vcGhvbGUgY29tZXMgbmV4dC4KKi8KCm5hbWVzcGFjZSBsdXBsZV9ucyB7CgogIHRlbXBsYXRlPHR5cGVuYW1lLi4uIFRUPiBzdHJ1Y3QgdHlwZV9saXN0IHsgc3RhdGljIGNvbnN0IGludCBzaXplID0gc2l6ZW9mLi4uKFRUKTsgfTsKCiAgdGVtcGxhdGU8dHlwZW5hbWUgVCwgaW50IE4sIGludCBNID0gMD4gc3RydWN0IHRsaXN0X2dldDsKCiAgdGVtcGxhdGU8aW50IE4sIGludCBNLCB0eXBlbmFtZSBULCB0eXBlbmFtZS4uLiBUVD4gc3RydWN0IHRsaXN0X2dldDwgdHlwZV9saXN0PFQsIFRULi4uPiwgTiwgTSA+IHsKICAgIHN0YXRpY19hc3NlcnQoTiA8IChpbnQpIHNpemVvZi4uLihUVCkrMSArIE0sICJ0eXBlIGluZGV4IG91dCBvZiBib3VuZHMiKTsKICAgIHVzaW5nIHR5cGUgPSBzdGQ6OmNvbmRpdGlvbmFsX3Q8IE4gPT0gTSwgVCwgdHlwZW5hbWUgdGxpc3RfZ2V0PCB0eXBlX2xpc3Q8VFQuLi4+LCBOLCBNICsgMSA+Ojp0eXBlID47CiAgfTsKICB0ZW1wbGF0ZTxpbnQgTiwgaW50IE0+IHN0cnVjdCB0bGlzdF9nZXQ8IHR5cGVfbGlzdDw+LCBOLCBNID4geyB1c2luZyB0eXBlID0gdm9pZDsgfTsKICB0ZW1wbGF0ZTxpbnQgTj4gc3RydWN0IHRsaXN0X2dldDwgdHlwZV9saXN0PD4sIE4sIDAgPiB7fTsKCiAgdGVtcGxhdGU8dHlwZW5hbWUgVCwgaW50IE4+CiAgdXNpbmcgdGxpc3RfZ2V0X3QgPSB0eXBlbmFtZSB0bGlzdF9nZXQ8VCwgTj46OnR5cGU7CgogIHRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFUsIGludCBOID0gMD4gc3RydWN0IHRsaXN0X2dldF9uOwoKICB0ZW1wbGF0ZTx0eXBlbmFtZSBVLCBpbnQgTiwgdHlwZW5hbWUgVCwgdHlwZW5hbWUuLi4gVFQ+IHN0cnVjdCB0bGlzdF9nZXRfbjwgdHlwZV9saXN0PFQsIFRULi4uPiwgVSwgTiA+IHsKICAgIHN0YXRpYyBjb25zdCBpbnQgdmFsdWUgPSBzdGQ6OmlzX3NhbWU8IFQsIFUgPjo6dmFsdWUgPyBOIDogdGxpc3RfZ2V0X248IHR5cGVfbGlzdDxUVC4uLj4sIFUsIE4gKyAxID46OnZhbHVlOwogIH07CiAgdGVtcGxhdGU8dHlwZW5hbWUgVSwgaW50IE4+IHN0cnVjdCB0bGlzdF9nZXRfbjwgdHlwZV9saXN0PD4sIFUsIE4gPiB7CiAgICBzdGF0aWMgY29uc3QgaW50IHZhbHVlID0gLTE7CiAgfTsKCiAgdGVtcGxhdGU8dHlwZW5hbWUgVCwgaW50IE4+IHN0cnVjdCB0dXBsZV9lbGVtZW50IHsKICAgIHRsaXN0X2dldF90PFQsIE4+IHZhbHVlOwogIH07CgogIHRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFU+IHN0cnVjdCB0dXBsZV9iYXNlOwoKICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBUVCwgaW50Li4uIE5OPgogIHN0cnVjdCB0dXBsZV9iYXNlPCB0eXBlX2xpc3Q8VFQuLi4+LCBzdGQ6OmludGVnZXJfc2VxdWVuY2U8aW50LCBOTi4uLj4gPiA6IHR1cGxlX2VsZW1lbnQ8IHR5cGVfbGlzdDxUVC4uLj4sIE5OID4uLi4gewoKICAgIHVzaW5nIHRsaXN0ID0gdHlwZV9saXN0PFRULi4uPjsKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBVVSwgdHlwZW5hbWUgVSA9IHN0ZDo6ZW5hYmxlX2lmX3Q8IHNpemVvZi4uLihVVSkgPT0gc2l6ZW9mLi4uKE5OKSA+PgogICAgY29uc3RleHByIHR1cGxlX2Jhc2UgKCBVVSYmLi4uIGFyZ3MgKSA6IHR1cGxlX2VsZW1lbnQ8IHRsaXN0LCBOTiA+eyBzdGQ6OmZvcndhcmQ8VVU+KGFyZ3MpIH0uLi4ge30KICAgIGNvbnN0ZXhwciB0dXBsZV9iYXNlICggVFQgY29uc3QmLi4uIGFyZ3MgKSA6IHR1cGxlX2VsZW1lbnQ8IHRsaXN0LCBOTiA+eyBhcmdzIH0uLi4ge30KICAgIGNvbnN0ZXhwciB0dXBsZV9iYXNlICggVFQmJi4uLiBhcmdzICkgOiB0dXBsZV9lbGVtZW50PCB0bGlzdCwgTk4gPnsgc3RkOjptb3ZlKGFyZ3MpIH0uLi4ge30KICAgIGNvbnN0ZXhwciB0dXBsZV9iYXNlICgpIHt9CiAgfTsKCiAgdGVtcGxhdGU8dHlwZW5hbWUgVD4gc3RydWN0IHR1cGxlIDogdHVwbGVfYmFzZTwgVCwgc3RkOjptYWtlX2ludGVnZXJfc2VxdWVuY2U8aW50LCBUOjpzaXplPiA+IHsKCiAgICB1c2luZyB0eXBlX2xpc3QgPSBUOwogICAgdXNpbmcgYmFzZSA9IHR1cGxlX2Jhc2U8IFQsIHN0ZDo6bWFrZV9pbnRlZ2VyX3NlcXVlbmNlPGludCwgVDo6c2l6ZT4gPjsKCiAgICB0ZW1wbGF0ZTxpbnQgTj4gY29uc3RleHByIGF1dG8mIGdldCgpIHsKICAgICAgc3RhdGljX2Fzc2VydChOIDwgVDo6c2l6ZSwgInR1cGxlOjpnZXQgLT4gb3V0IG9mIGJvdW5kcyBhY2Nlc3MiKTsKICAgICAgcmV0dXJuIHR1cGxlX2VsZW1lbnQ8IFQsIE4gPjo6dmFsdWU7CiAgICB9CgogICAgdGVtcGxhdGU8dHlwZW5hbWUgVT4gY29uc3RleHByIGF1dG8mIGdldCgpIHsKICAgICAgc3RhdGljX2Fzc2VydCh0bGlzdF9nZXRfbjxULCBVPjo6dmFsdWUgIT0gLTEsICJubyBzdWNoIHR5cGUgaW4gdHlwZSBsaXN0Iik7CiAgICAgIHJldHVybiB0dXBsZV9lbGVtZW50PCBULCB0bGlzdF9nZXRfbjxULCBVPjo6dmFsdWUgPjo6dmFsdWU7CiAgICB9CgogICAgdGVtcGxhdGU8aW50IE4+IGNvbnN0ZXhwciBhdXRvJiBnZXQoKSBjb25zdCB7CiAgICAgIHN0YXRpY19hc3NlcnQoTiA8IFQ6OnNpemUsICJ0dXBsZTo6Z2V0IC0+IG91dCBvZiBib3VuZHMgYWNjZXNzIik7CiAgICAgIHJldHVybiB0dXBsZV9lbGVtZW50PCBULCBOID46OnZhbHVlOwogICAgfQoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFU+IGNvbnN0ZXhwciBhdXRvJiBnZXQoKSBjb25zdCB7CiAgICAgIHN0YXRpY19hc3NlcnQodGxpc3RfZ2V0X248VCwgVT46OnZhbHVlICE9IC0xLCAibm8gc3VjaCB0eXBlIGluIHR5cGUgbGlzdCIpOwogICAgICByZXR1cm4gdHVwbGVfZWxlbWVudDwgVCwgdGxpc3RfZ2V0X248VCwgVT46OnZhbHVlID46OnZhbHVlOwogICAgfQoKICAgIHVzaW5nIGJhc2U6OmJhc2U7CiAgfTsKCiAgdGVtcGxhdGU8aW50IE4sIHR5cGVuYW1lIFQ+IGNvbnN0ZXhwciBhdXRvJiBnZXQgKCB0dXBsZTxUPiYgdCApIHsgcmV0dXJuIHQudGVtcGxhdGUgZ2V0PE4+KCk7IH0KICB0ZW1wbGF0ZTx0eXBlbmFtZSBVLCB0eXBlbmFtZSBUPiBjb25zdGV4cHIgYXV0byYgZ2V0ICggdHVwbGU8VD4mIHQgKSB7IHJldHVybiB0LnRlbXBsYXRlIGdldDxVPigpOyB9CgogIHRlbXBsYXRlPGludCBOLCB0eXBlbmFtZSBUPiBjb25zdGV4cHIgYXV0byYgZ2V0ICggdHVwbGU8VD4gY29uc3QmIHQgKSB7IHJldHVybiB0LnRlbXBsYXRlIGdldDxOPigpOyB9CiAgdGVtcGxhdGU8dHlwZW5hbWUgVSwgdHlwZW5hbWUgVD4gY29uc3RleHByIGF1dG8mIGdldCAoIHR1cGxlPFQ+IGNvbnN0JiB0ICkgeyByZXR1cm4gdC50ZW1wbGF0ZSBnZXQ8VT4oKTsgfQoKICB0ZW1wbGF0ZTx0eXBlbmFtZSBUPiBjb25zdGV4cHIgYXV0byBzaXplICggdHVwbGU8VD4gY29uc3QmIHQgKSB7IHJldHVybiBUOjpzaXplOyB9CiAgdGVtcGxhdGU8dHlwZW5hbWUgVSwgdHlwZW5hbWUgVD4gY29uc3RleHByIGF1dG8gaW5kZXggKCB0dXBsZTxUPiBjb25zdCYgdCApIHsgcmV0dXJuIHRsaXN0X2dldF9uPCBULCBVID46OnZhbHVlOyB9CgogIHRlbXBsYXRlPHR5cGVuYW1lIFQsIGludCBOPgogIHVzaW5nIGVsZW1lbnRfdCA9IHRsaXN0X2dldF90PCB0eXBlbmFtZSBUOjp0eXBlX2xpc3QsIE4gPjsKCiAgdGVtcGxhdGU8dHlwZW5hbWUgVD4gc3RydWN0IGx1cGxlX2ltcGwgewogICAgdXNpbmcgdHlwZSA9IHR1cGxlPFQ+OwogIH07CgogIHRlbXBsYXRlPHR5cGVuYW1lLi4uIFRUPiBzdHJ1Y3QgbHVwbGVfaW1wbDwgdHlwZV9saXN0PCB0eXBlX2xpc3Q8VFQuLi4+ID4gPiB7CiAgICB1c2luZyB0eXBlID0gdHlwZW5hbWUgbHVwbGVfaW1wbDwgdHlwZV9saXN0PFRULi4uPiA+Ojp0eXBlOwogIH07CgogIHRlbXBsYXRlPHR5cGVuYW1lLi4uIFRUPgogIHVzaW5nIGx1cGxlID0gdHlwZW5hbWUgbHVwbGVfaW1wbDwgdHlwZV9saXN0PFRULi4uPiA+Ojp0eXBlOwoKICB0ZW1wbGF0ZTxpbnQuLi4gTiwgdHlwZW5hbWUgVDAsIHR5cGVuYW1lIFQxPgogIHZvaWQgbHVwbGVfZG9faW1wbCAoc3RkOjppbnRlZ2VyX3NlcXVlbmNlPGludCwgTi4uLj4sIFQwJiB0LCBUMSBmbikgewogICAgY2hhciBkdW1teVtdeyAoZm4oIGdldDxOPih0KSApLCBjaGFye30pLi4uIH07CiAgICAodm9pZClkdW1teTsKICB9CgogIHRlbXBsYXRlPHR5cGVuYW1lIFQwLCB0eXBlbmFtZSBUMT4KICB2b2lkIGx1cGxlX2RvIChUMCYgdCwgVDEgZm4pIHsKICAgIGx1cGxlX2RvX2ltcGwoIHN0ZDo6bWFrZV9pbnRlZ2VyX3NlcXVlbmNlPCBpbnQsIFQwOjp0eXBlX2xpc3Q6OnNpemUgPnt9LCB0LCBmbiApOwogIH0KICAKfQoKdXNpbmcgbHVwbGVfbnM6Omx1cGxlOwp1c2luZyBsdXBsZV9uczo6Z2V0Owp1c2luZyBsdXBsZV9uczo6aW5kZXg7CgovKioqKioqKioqKioqKiAgZW5kIG9mIGx1cGxlLmggKioqKioqKioqKioqKioqLwoKCi8qKioqKioqKioqKioqICB0eXBlLWxvb3Bob2xlLmggKioqKioqKioqKioqKioqLwoKLyogCiAgVGhpcyBoZWFkZXIgaXMgZm9yIHRoZSBHcmVhdCBUeXBlIExvb3Bob2xlLgogIFNvdXJjZSBjb2RlIHdpdGggY29tbWVudHM6IGh0dHBzOi8vZy4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4uYi5jb20vYWxleHBvbHQvbHVwbGUvYmxvYi9tYXN0ZXIvdHlwZS1sb29waG9sZS5oCiovCgpuYW1lc3BhY2UgbG9vcGhvbGVfbnMgewoKICB0ZW1wbGF0ZTx0eXBlbmFtZSBULCBpbnQgTj4KICBzdHJ1Y3QgdGFnIHsKICAgIGZyaWVuZCBhdXRvIGxvb3Bob2xlKHRhZzxULE4+KTsKICAgIGNvbnN0ZXhwciBmcmllbmQgaW50IGNsb29waG9sZSh0YWc8VCxOPik7CiAgfTsKCiAgdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVSwgaW50IE4sIGJvb2wgQj4KICBzdHJ1Y3QgZm5fZGVmIHsKICAgIGZyaWVuZCBhdXRvIGxvb3Bob2xlKHRhZzxULE4+KSB7IHJldHVybiBVe307IH0KICAgIGNvbnN0ZXhwciBmcmllbmQgaW50IGNsb29waG9sZSh0YWc8VCxOPikgeyByZXR1cm4gMDsgfQogIH07CgogIHRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFUsIGludCBOPgogIHN0cnVjdCBmbl9kZWY8VCwgVSwgTiwgdHJ1ZT4ge307CgogIHRlbXBsYXRlPHR5cGVuYW1lIFQsIGludCBOPgogIHN0cnVjdCBjX29wIHsKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFUsIGludCBNPiBzdGF0aWMgYXV0byBpbnMoLi4uKSAtPiBpbnQ7CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBVLCBpbnQgTSwgaW50ID0gY2xvb3Bob2xlKHRhZzxULE0+e30pID4gc3RhdGljIGF1dG8gaW5zKGludCkgLT4gY2hhcjsKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBVLCBpbnQgPSBzaXplb2YoZm5fZGVmPFQsIFUsIE4sIHNpemVvZihpbnM8VSwgTj4oMCkpID09IHNpemVvZihjaGFyKT4pPgogICAgb3BlcmF0b3IgVSgpOwogIH07CgogIHRlbXBsYXRlPHR5cGVuYW1lIFQsIGludC4uLiBOTj4KICBjb25zdGV4cHIgaW50IGZpZWxkc19udW1iZXIoLi4uKSB7IHJldHVybiBzaXplb2YuLi4oTk4pLTE7IH0KCiAgdGVtcGxhdGU8dHlwZW5hbWUgVCwgaW50Li4uIE5OPgogIGNvbnN0ZXhwciBhdXRvIGZpZWxkc19udW1iZXIoaW50KSAtPiBkZWNsdHlwZShUeyBjX29wPFQsTk4+e30uLi4gfSwgMCkgewogICAgcmV0dXJuIGZpZWxkc19udW1iZXI8VCwgTk4uLi4sIHNpemVvZi4uLihOTik+KDApOwogIH0KCiAgdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVT4KICBzdHJ1Y3QgbG9vcGhvbGVfdHlwZV9saXN0OwoKICB0ZW1wbGF0ZTx0eXBlbmFtZSBULCBpbnQuLi4gTk4+CiAgc3RydWN0IGxvb3Bob2xlX3R5cGVfbGlzdDwgVCwgc3RkOjppbnRlZ2VyX3NlcXVlbmNlPGludCwgTk4uLi4+ID4gewogICAgdXNpbmcgdHlwZSA9IGx1cGxlX25zOjp0eXBlX2xpc3Q8IGRlY2x0eXBlKGxvb3Bob2xlKHRhZzxULCBOTj57fSkpLi4uID47CiAgfTsKCiAgdGVtcGxhdGU8dHlwZW5hbWUgVD4KICB1c2luZyBhc190eXBlX2xpc3QgPQogICAgdHlwZW5hbWUgbG9vcGhvbGVfdHlwZV9saXN0PFQsIHN0ZDo6bWFrZV9pbnRlZ2VyX3NlcXVlbmNlPGludCwgZmllbGRzX251bWJlcjxUPigwKT4+Ojp0eXBlOwoKfQoKCnN0cnVjdCB0ZXN0MSB7IAogIHRlc3QxKCkgeyAKICAgIHByaW50ZigidGVzdDo6dGVzdCgpXG4iKTsgCiAgfSAKfTsKCnN0cnVjdCBkYXRhIHsgCiAgdGVzdDEgdDA7ICAKICBzdGQ6OnN0cmluZyB0MTsgCiAgc3RkOjp2ZWN0b3I8aW50PiB0MjsgCn07CgoKaW50IG1haW4oKSB7CgogIHVzaW5nIGRhdGFfdGxpc3QgPSBsb29waG9sZV9uczo6YXNfdHlwZV9saXN0PCBkYXRhID47CgogIHVzaW5nIGRhdGFfbHVwbGUgPSBsdXBsZTwgZGF0YV90bGlzdCA+OwoKICBkYXRhIGR7IHt9LCAiSGVsbG8gV29ybGQhIiwgezEsMiwzfSB9OwoKICBhdXRvJiBsID0gcmVpbnRlcnByZXRfY2FzdDwgZGF0YV9sdXBsZSYgPiggZCApOwoKICBwcmludGYoIiVzXG4iLCBnZXQ8c3RkOjpzdHJpbmc+KGwpLmRhdGEoKSk7CgogIGZvciAoYXV0byBpIDogZ2V0PDI+KGwpKSBwcmludGYoIiVkLCAiLGkpOwogIHB1dHMoIiIpOwoKICBsdXBsZV9uczo6ZWxlbWVudF90PGRhdGFfbHVwbGUsMT4mIHN0ciA9IGdldDwxPihsKTsKCiAgc3RyID0gIldlbGNvbWUgdGhlIHRoZSBOZXcgV29ybGQhIjsKCiAgcHJpbnRmKCIlc1xuXG4iLCBzdHIuZGF0YSgpKTsKCiAgbHVwbGVfZG8obCwgW2k9MF0gKCBhdXRvJiB2YWx1ZSApIG11dGFibGUgeyBwcmludGYoICJmaWVsZCAlZDogJXNcbiIsIGkrKywgdHlwZWlkKHZhbHVlKS5uYW1lKCkgKTsgfSApOwp9Cgo=