#include <iostream>
#include <tuple>
namespace adv
{
namespace type
{
using index_t = unsigned ;
}
namespace utility
{
template < typename ... Types >
struct type_carrier
{
using carrier_type = type_carrier< Types ... > ;
static constexpr type:: index_t size( )
{
return static_cast < type:: index_t > ( sizeof ... ( Types) ) ;
}
} ;
template < unsigned ... Indices >
struct index_carrier
{
using carrier_type = index_carrier< Indices ... > ;
static constexpr type:: index_t size( )
{
return static_cast < type:: index_t > ( sizeof ... ( Indices) ) ;
}
} ;
namespace detail
{
template < typename , typename >
struct type_carrier_contains;
template < typename Type, typename Current>
struct type_carrier_contains< type_carrier< Current> , Type>
{
enum : bool { value = std:: is_same < Current, Type> :: value } ;
} ;
template < typename Type, typename Current, typename Next, typename ... Rest >
struct type_carrier_contains< type_carrier< Current, Next, Rest ... > , Type>
{
enum : bool { value = type_carrier_contains< type_carrier< Current> , Type> :: value || type_carrier_contains< type_carrier< Next, Rest ... > , Type> :: value } ;
} ;
template < typename , unsigned >
struct index_carrier_contains;
template < unsigned Index, unsigned Current>
struct index_carrier_contains< index_carrier< Current> , Index>
{
enum : bool { value = Current == Index } ;
} ;
template < unsigned Index, unsigned Current, unsigned Next, unsigned ... Rest >
struct index_carrier_contains< index_carrier< Current, Next, Rest ... > , Index>
{
enum : bool { value = index_carrier_contains< index_carrier< Current> , Index> :: value || index_carrier_contains< index_carrier< Next, Rest ... > , Index> :: value } ;
} ;
}
template < typename , typename >
struct carrier_contains;
template < typename ... Types , typename Current>
struct carrier_contains< type_carrier< Types ... > , type_carrier< Current>>
{
enum : bool { value = detail:: type_carrier_contains < type_carrier< Types ... > , Current> :: value } ;
} ;
template < typename ... Types , typename Current, typename Next, typename ... Rest >
struct carrier_contains< type_carrier< Types ... > , type_carrier< Current, Next, Rest ... >>
{
enum : bool { value = detail:: type_carrier_contains < type_carrier< Types ... > , Current> :: value && carrier_contains< type_carrier< Types ... > , type_carrier< Next, Rest ... >> :: value } ;
} ;
template < unsigned ... Indices , unsigned Current>
struct carrier_contains< index_carrier< Indices ... > , index_carrier< Current>>
{
enum : bool { value = detail:: index_carrier_contains < index_carrier< Indices ... > , Current> :: value } ;
} ;
template < unsigned ... Indices , unsigned Current, unsigned Next, unsigned ... Rest >
struct carrier_contains< index_carrier< Indices ... > , index_carrier< Current, Next, Rest ... >>
{
enum : bool { value = detail:: index_carrier_contains < index_carrier< Indices ... > , Current> :: value && carrier_contains< index_carrier< Indices ... > , index_carrier< Next, Rest ... >> :: value } ;
} ;
// ----------------------------------------->
namespace detail {
template < typename , typename >
struct type_carrier_count;
template < typename Type>
struct type_carrier_count< type_carrier<> , Type>
{
enum : type:: index_t { value = 0 } ;
} ;
template < typename Type, typename Current>
struct type_carrier_count< type_carrier< Current> , Type>
{
enum : type:: index_t { value = std:: is_same < Current, Type> :: value ? 1 : 0 } ;
} ;
template < typename Type, typename Current, typename ... Rest >
struct type_carrier_count< type_carrier< Current, Rest ... > , Type>
{
enum : type:: index_t { value = type_carrier_count< type_carrier< Current> , Type> :: value + type_carrier_count< type_carrier< Rest ... > , Type> :: value } ;
} ;
template < typename , unsigned >
struct index_carrier_count;
template < unsigned Index>
struct index_carrier_count< index_carrier<> , Index>
{
enum : type:: index_t { value = 0 } ;
} ;
template < unsigned Index, unsigned Current>
struct index_carrier_count< index_carrier< Current> , Index>
{
enum : type:: index_t { value = ( Current == Index) ? 1 : 0 } ;
} ;
template < unsigned Index, unsigned Current, unsigned ... Rest >
struct index_carrier_count< index_carrier< Current, Rest ... > , Index>
{
enum : type:: index_t { value = index_carrier_count< index_carrier< Current> , Index> :: value + index_carrier_count< index_carrier< Rest ... > , Index> :: value } ;
} ;
}
template < typename , typename >
struct carrier_count;
template < typename ... Types , typename Current>
struct carrier_count< type_carrier< Types ... > , type_carrier< Current>>
{
enum : type:: index_t { value = detail:: type_carrier_count < type_carrier< Types ... > , Current> :: value } ;
} ;
template < unsigned ... Indices , unsigned Current>
struct carrier_count< index_carrier< Indices ... > , index_carrier< Current>>
{
enum : type:: index_t { value = detail:: index_carrier_contains < index_carrier< Indices ... > , Current> :: value } ;
} ;
// ----------------------------------------->
namespace detail {
template < typename , typename , unsigned , unsigned , unsigned >
struct type_carrier_nth_index;
template < typename Type, unsigned Index, unsigned Count, unsigned Target>
struct type_carrier_nth_index< type_carrier<> , Type, Index, Count, Target>
{
enum : type:: index_t { value = 0 } ;
} ;
template < typename Type, typename Current, unsigned Index, unsigned Count, unsigned Target>
struct type_carrier_nth_index< type_carrier< Current> , Type, Index, Count, Target>
{
enum : type:: index_t { value = ( ( Count == Target) && std:: is_same < Current, Type> :: value ) ? Index : 0 } ;
} ;
template < typename Type, typename Current, typename ... Rest , unsigned Index, unsigned Count, unsigned Target>
struct type_carrier_nth_index< type_carrier< Current, Rest ... > , Type, Index, Count, Target>
{
enum : type:: index_t
{
value = type_carrier_nth_index< type_carrier< Current> , Type, Index, Count, Target> :: value + type_carrier_nth_index< type_carrier< Rest ... > , Type, Index + 1 , Count + ( std:: is_same < Current, Type> :: value ? 1 : 0 ) , Target> :: value
} ;
} ;
template < typename , unsigned , unsigned , unsigned , unsigned >
struct index_carrier_nth_index;
template < unsigned Other, unsigned Index, unsigned Count, unsigned Target>
struct index_carrier_nth_index< index_carrier<> , Other, Index, Count, Target>
{
enum : type:: index_t { value = 0 } ;
} ;
template < unsigned Other, unsigned Current, unsigned Index, unsigned Count, unsigned Target>
struct index_carrier_nth_index< index_carrier< Current> , Other, Index, Count, Target>
{
enum : type:: index_t { value = ( ( Count == Target) && ( Current == Other) ) ? Index : 0 } ;
} ;
template < unsigned Other, unsigned Current, unsigned ... Rest , unsigned Index, unsigned Count, unsigned Target>
struct index_carrier_nth_index< index_carrier< Current, Rest ... > , Other, Index, Count, Target>
{
enum : type:: index_t { value = index_carrier_nth_index< index_carrier< Current> , Other, Index, Count, Target> :: value + index_carrier_nth_index< index_carrier< Rest ... > , Other, Index + 1 , Count + ( Current == Other ? 1 : 0 ) , Target> :: value } ;
} ;
}
template < typename , typename , unsigned >
struct carrier_nth_index;
template < typename ... Types , typename Current, unsigned Number>
struct carrier_nth_index< type_carrier< Types ... > , Current, Number>
{
static_assert( carrier_count< type_carrier< Types ... > , type_carrier< Current>> :: value > Number, "Type carrier does not contain type with this index!" ) ;
enum : type:: index_t { value = detail:: type_carrier_nth_index < type_carrier< Types ... > , Current, 0 , 0 , Number> :: value } ;
} ;
template < unsigned ... Indices , unsigned Current, unsigned Number>
struct carrier_nth_index< index_carrier< Indices ... > , index_carrier< Current> , Number>
{
static_assert( carrier_count< index_carrier< Indices ... > , index_carrier< Current>> :: value > Number, "Index carrier does not contain index with this index!" ) ;
enum : type:: index_t { value = detail:: index_carrier_nth_index < index_carrier< Indices ... > , Current, 0 , 0 , Number> :: value } ;
} ;
namespace detail
{
template < typename >
struct parameters;
template < typename Return, typename Type, typename ... Arguments >
struct parameters< Return( Type:: * ) ( Arguments ...) >
{
using type = type_carrier< std:: decay_t < Arguments> ... > ;
} ;
template < typename Return, typename Type, typename ... Arguments >
struct parameters< Return( Type:: * ) ( Arguments ...) const >
{
using type = type_carrier< std:: decay_t < Arguments> ... > ;
} ;
}
template < typename Type>
using parameters_t = typename detail:: parameters < decltype( & Type:: operator ( ) ) > :: type ;
namespace detail
{
template < typename , typename , typename , typename >
struct map_parameters_to_carrier;
template < typename Parameter, typename ... Types >
struct map_parameters_to_carrier< type_carrier< Parameter> , type_carrier< Types ... > , index_carrier<> , type_carrier<>>
{
using type = index_carrier< carrier_nth_index< type_carrier< Types ... > , Parameter, 0 > :: value > ;
} ;
template < typename Parameter, typename ... Types , unsigned ... Indices , typename ... Visited >
struct map_parameters_to_carrier< type_carrier< Parameter> , type_carrier< Types ... > , index_carrier< Indices ... > , type_carrier< Visited ... >>
{
using type = index_carrier< Indices ... , carrier_nth_index< type_carrier< Types ... > , Parameter, carrier_count< type_carrier< Visited ... > , type_carrier< Parameter>> :: value > :: value > ;
} ;
template < typename Current, typename ... Parameters , typename ... Types >
struct map_parameters_to_carrier< type_carrier< Current, Parameters ... > , type_carrier< Types ... > , index_carrier<> , type_carrier<>>
{
using type = typename map_parameters_to_carrier< type_carrier< Parameters ... > , type_carrier< Types ... > , index_carrier< carrier_nth_index< type_carrier< Types ... > , Current, 0 > :: value > , type_carrier< Current>> :: type ;
} ;
template < typename Current, typename ... Parameters , typename ... Types , unsigned ... Indices , typename ... Visited >
struct map_parameters_to_carrier< type_carrier< Current, Parameters ... > , type_carrier< Types ... > , index_carrier< Indices ... > , type_carrier< Visited ... >>
{
using type = typename map_parameters_to_carrier< type_carrier< Parameters ... > , type_carrier< Types ... > , index_carrier< Indices ... , carrier_nth_index< type_carrier< Types ... > , Current, carrier_count< type_carrier< Visited ... > , type_carrier< Current>> :: value > :: value > , type_carrier< Visited ... , Current>> :: type ;
} ;
}
template < typename Parameters, typename Carrier>
using map_parameters_to_carrier_t = typename detail:: map_parameters_to_carrier < Parameters, Carrier, index_carrier<> , type_carrier<>> :: type ;
}
namespace detail
{
template < typename ... Types , unsigned ... Indices , typename Functor>
decltype( auto ) this_with( std:: tuple < Types ... > & object, utility:: index_carrier < Indices ... > , Functor&& functor)
{
return functor( std:: get < Indices> ( object) ...) ;
}
}
template < typename ... Types , typename Functor>
decltype( auto ) apply( std:: tuple < Types ... > & object, Functor && functor)
{
static_assert( utility:: carrier_contains < utility:: type_carrier < Types ... > , utility:: parameters_t < Functor>> :: value , "This tuple does not contain one or more of these types!" ) ;
constexpr auto parameters = utility:: map_parameters_to_carrier_t < utility:: parameters_t < Functor> , utility:: type_carrier < Types ... >>
{
// ...
} ;
return detail:: this_with ( object, parameters, std:: forward < Functor> ( functor) ) ;
}
}
int main( ) {
auto x = std:: make_tuple ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8.0 , 9 , 10 , 11 , 33 , 13 , 14 , 15 .f , 16 , 17 , 18 , 2 ) ;
std:: cout << adv:: apply ( x, [ ] ( float a, double b, int c, int d) {
std:: cout << a << std:: endl ;
std:: cout << b << std:: endl ;
std:: cout << c << std:: endl ;
std:: cout << d << std:: endl ;
return d;
} ) ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHVwbGU+CgpuYW1lc3BhY2UgYWR2CnsKCW5hbWVzcGFjZSB0eXBlCgl7CgkJdXNpbmcgaW5kZXhfdCA9IHVuc2lnbmVkOwoJfQoKCW5hbWVzcGFjZSB1dGlsaXR5Cgl7CgkJdGVtcGxhdGUgPHR5cGVuYW1lIC4uLiBUeXBlcz4KCQlzdHJ1Y3QgdHlwZV9jYXJyaWVyCgkJewoJCQl1c2luZyBjYXJyaWVyX3R5cGUgPSB0eXBlX2NhcnJpZXI8VHlwZXMgLi4uID47CgoJCQlzdGF0aWMgY29uc3RleHByIHR5cGU6OmluZGV4X3Qgc2l6ZSgpCgkJCXsKCQkJCXJldHVybiBzdGF0aWNfY2FzdDx0eXBlOjppbmRleF90PihzaXplb2YgLi4uIChUeXBlcykpOwoJCQl9CgkJfTsKCgkJdGVtcGxhdGUgPHVuc2lnbmVkIC4uLiBJbmRpY2VzPgoJCXN0cnVjdCBpbmRleF9jYXJyaWVyCgkJewoJCQl1c2luZyBjYXJyaWVyX3R5cGUgPSBpbmRleF9jYXJyaWVyPEluZGljZXMgLi4uID47CgoJCQlzdGF0aWMgY29uc3RleHByIHR5cGU6OmluZGV4X3Qgc2l6ZSgpCgkJCXsKCQkJCXJldHVybiBzdGF0aWNfY2FzdDx0eXBlOjppbmRleF90PihzaXplb2YgLi4uIChJbmRpY2VzKSk7CgkJCX0KCQl9OwoKCQluYW1lc3BhY2UgZGV0YWlsCgkJewoJCQl0ZW1wbGF0ZSA8dHlwZW5hbWUsIHR5cGVuYW1lPgoJCQlzdHJ1Y3QgdHlwZV9jYXJyaWVyX2NvbnRhaW5zOwoKCQkJdGVtcGxhdGUgPHR5cGVuYW1lIFR5cGUsIHR5cGVuYW1lIEN1cnJlbnQ+CgkJCXN0cnVjdCB0eXBlX2NhcnJpZXJfY29udGFpbnM8dHlwZV9jYXJyaWVyPEN1cnJlbnQ+LCBUeXBlPgoJCQl7CgkJCQllbnVtIDogYm9vbCB7IHZhbHVlID0gc3RkOjppc19zYW1lPEN1cnJlbnQsIFR5cGU+Ojp2YWx1ZSB9OwoJCQl9OwoKCQkJdGVtcGxhdGUgPHR5cGVuYW1lIFR5cGUsIHR5cGVuYW1lIEN1cnJlbnQsIHR5cGVuYW1lIE5leHQsIHR5cGVuYW1lIC4uLiBSZXN0PgoJCQlzdHJ1Y3QgdHlwZV9jYXJyaWVyX2NvbnRhaW5zPHR5cGVfY2FycmllcjxDdXJyZW50LCBOZXh0LCBSZXN0IC4uLiA+LCBUeXBlPgoJCQl7CgkJCQllbnVtIDogYm9vbCB7IHZhbHVlID0gdHlwZV9jYXJyaWVyX2NvbnRhaW5zPHR5cGVfY2FycmllcjxDdXJyZW50PiwgVHlwZT46OnZhbHVlIHx8IHR5cGVfY2Fycmllcl9jb250YWluczx0eXBlX2NhcnJpZXI8TmV4dCwgUmVzdCAuLi4gPiwgVHlwZT46OnZhbHVlIH07CgkJCX07CgoJCQl0ZW1wbGF0ZSA8dHlwZW5hbWUsIHVuc2lnbmVkPgoJCQlzdHJ1Y3QgaW5kZXhfY2Fycmllcl9jb250YWluczsKCgkJCXRlbXBsYXRlIDx1bnNpZ25lZCBJbmRleCwgdW5zaWduZWQgQ3VycmVudD4KCQkJc3RydWN0IGluZGV4X2NhcnJpZXJfY29udGFpbnM8aW5kZXhfY2FycmllcjxDdXJyZW50PiwgSW5kZXg+CgkJCXsKCQkJCWVudW0gOiBib29sIHsgdmFsdWUgPSBDdXJyZW50ID09IEluZGV4IH07CgkJCX07CgoJCQl0ZW1wbGF0ZSA8dW5zaWduZWQgSW5kZXgsIHVuc2lnbmVkIEN1cnJlbnQsIHVuc2lnbmVkIE5leHQsIHVuc2lnbmVkIC4uLiBSZXN0PgoJCQlzdHJ1Y3QgaW5kZXhfY2Fycmllcl9jb250YWluczxpbmRleF9jYXJyaWVyPEN1cnJlbnQsIE5leHQsIFJlc3QgLi4uID4sIEluZGV4PgoJCQl7CgkJCQllbnVtIDogYm9vbCB7IHZhbHVlID0gaW5kZXhfY2Fycmllcl9jb250YWluczxpbmRleF9jYXJyaWVyPEN1cnJlbnQ+LCBJbmRleD46OnZhbHVlIHx8IGluZGV4X2NhcnJpZXJfY29udGFpbnM8aW5kZXhfY2FycmllcjxOZXh0LCBSZXN0IC4uLiA+LCBJbmRleD46OnZhbHVlIH07CgkJCX07CgkJfQoKCQl0ZW1wbGF0ZSA8dHlwZW5hbWUsIHR5cGVuYW1lPgoJCXN0cnVjdCBjYXJyaWVyX2NvbnRhaW5zOwoKCQl0ZW1wbGF0ZSA8dHlwZW5hbWUgLi4uIFR5cGVzLCB0eXBlbmFtZSBDdXJyZW50PgoJCXN0cnVjdCBjYXJyaWVyX2NvbnRhaW5zPHR5cGVfY2FycmllcjxUeXBlcyAuLi4gPiwgdHlwZV9jYXJyaWVyPEN1cnJlbnQ+PgoJCXsKCQkJZW51bSA6IGJvb2wgeyB2YWx1ZSA9IGRldGFpbDo6dHlwZV9jYXJyaWVyX2NvbnRhaW5zPHR5cGVfY2FycmllcjxUeXBlcyAuLi4gPiwgQ3VycmVudD46OnZhbHVlIH07CgkJfTsKCgkJdGVtcGxhdGUgPHR5cGVuYW1lIC4uLiBUeXBlcywgdHlwZW5hbWUgQ3VycmVudCwgdHlwZW5hbWUgTmV4dCwgdHlwZW5hbWUgLi4uIFJlc3Q+CgkJc3RydWN0IGNhcnJpZXJfY29udGFpbnM8dHlwZV9jYXJyaWVyPFR5cGVzIC4uLiA+LCB0eXBlX2NhcnJpZXI8Q3VycmVudCwgTmV4dCwgUmVzdCAuLi4gPj4KCQl7CgkJCWVudW0gOiBib29sIHsgdmFsdWUgPSBkZXRhaWw6OnR5cGVfY2Fycmllcl9jb250YWluczx0eXBlX2NhcnJpZXI8VHlwZXMgLi4uID4sIEN1cnJlbnQ+Ojp2YWx1ZSYmIGNhcnJpZXJfY29udGFpbnM8dHlwZV9jYXJyaWVyPFR5cGVzIC4uLiA+LCB0eXBlX2NhcnJpZXI8TmV4dCwgUmVzdCAuLi4gPj46OnZhbHVlIH07CgkJfTsKCgkJdGVtcGxhdGUgPHVuc2lnbmVkIC4uLiBJbmRpY2VzLCB1bnNpZ25lZCBDdXJyZW50PgoJCXN0cnVjdCBjYXJyaWVyX2NvbnRhaW5zPGluZGV4X2NhcnJpZXI8SW5kaWNlcyAuLi4gPiwgaW5kZXhfY2FycmllcjxDdXJyZW50Pj4KCQl7CgkJCWVudW0gOiBib29sIHsgdmFsdWUgPSBkZXRhaWw6OmluZGV4X2NhcnJpZXJfY29udGFpbnM8aW5kZXhfY2FycmllcjxJbmRpY2VzIC4uLiA+LCBDdXJyZW50Pjo6dmFsdWUgfTsKCQl9OwoKCQl0ZW1wbGF0ZSA8dW5zaWduZWQgLi4uIEluZGljZXMsIHVuc2lnbmVkIEN1cnJlbnQsIHVuc2lnbmVkIE5leHQsIHVuc2lnbmVkIC4uLiBSZXN0PgoJCXN0cnVjdCBjYXJyaWVyX2NvbnRhaW5zPGluZGV4X2NhcnJpZXI8SW5kaWNlcyAuLi4gPiwgaW5kZXhfY2FycmllcjxDdXJyZW50LCBOZXh0LCBSZXN0IC4uLiA+PgoJCXsKCQkJZW51bSA6IGJvb2wgeyB2YWx1ZSA9IGRldGFpbDo6aW5kZXhfY2Fycmllcl9jb250YWluczxpbmRleF9jYXJyaWVyPEluZGljZXMgLi4uID4sIEN1cnJlbnQ+Ojp2YWx1ZSYmIGNhcnJpZXJfY29udGFpbnM8aW5kZXhfY2FycmllcjxJbmRpY2VzIC4uLiA+LCBpbmRleF9jYXJyaWVyPE5leHQsIFJlc3QgLi4uID4+Ojp2YWx1ZSB9OwoJCX07CgoJCS8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPgoKCQluYW1lc3BhY2UgZGV0YWlsIHsKCQkJdGVtcGxhdGUgPHR5cGVuYW1lLCB0eXBlbmFtZT4KCQkJc3RydWN0IHR5cGVfY2Fycmllcl9jb3VudDsKCgkJCXRlbXBsYXRlIDx0eXBlbmFtZSBUeXBlPgoJCQlzdHJ1Y3QgdHlwZV9jYXJyaWVyX2NvdW50PHR5cGVfY2Fycmllcjw+LCBUeXBlPgoJCQl7CgkJCQllbnVtIDogdHlwZTo6aW5kZXhfdCB7IHZhbHVlID0gMCB9OwoJCQl9OwoKCQkJdGVtcGxhdGUgPHR5cGVuYW1lIFR5cGUsIHR5cGVuYW1lIEN1cnJlbnQ+CgkJCXN0cnVjdCB0eXBlX2NhcnJpZXJfY291bnQ8dHlwZV9jYXJyaWVyPEN1cnJlbnQ+LCBUeXBlPgoJCQl7CgkJCQllbnVtIDogdHlwZTo6aW5kZXhfdCB7IHZhbHVlID0gc3RkOjppc19zYW1lPEN1cnJlbnQsIFR5cGU+Ojp2YWx1ZSA/IDEgOiAwIH07CgkJCX07CgoJCQl0ZW1wbGF0ZSA8dHlwZW5hbWUgVHlwZSwgdHlwZW5hbWUgQ3VycmVudCwgdHlwZW5hbWUgLi4uIFJlc3Q+CgkJCXN0cnVjdCB0eXBlX2NhcnJpZXJfY291bnQ8dHlwZV9jYXJyaWVyPEN1cnJlbnQsIFJlc3QgLi4uID4sIFR5cGU+CgkJCXsKCQkJCWVudW0gOiB0eXBlOjppbmRleF90IHsgdmFsdWUgPSB0eXBlX2NhcnJpZXJfY291bnQ8dHlwZV9jYXJyaWVyPEN1cnJlbnQ+LCBUeXBlPjo6dmFsdWUgKyB0eXBlX2NhcnJpZXJfY291bnQ8dHlwZV9jYXJyaWVyPFJlc3QgLi4uID4sIFR5cGU+Ojp2YWx1ZSB9OwoJCQl9OwoKCQkJdGVtcGxhdGUgPHR5cGVuYW1lLCB1bnNpZ25lZD4KCQkJc3RydWN0IGluZGV4X2NhcnJpZXJfY291bnQ7CgoJCQl0ZW1wbGF0ZSA8dW5zaWduZWQgSW5kZXg+CgkJCXN0cnVjdCBpbmRleF9jYXJyaWVyX2NvdW50PGluZGV4X2NhcnJpZXI8PiwgSW5kZXg+CgkJCXsKCQkJCWVudW0gOiB0eXBlOjppbmRleF90IHsgdmFsdWUgPSAwIH07CgkJCX07CgoJCQl0ZW1wbGF0ZSA8dW5zaWduZWQgSW5kZXgsIHVuc2lnbmVkIEN1cnJlbnQ+CgkJCXN0cnVjdCBpbmRleF9jYXJyaWVyX2NvdW50PGluZGV4X2NhcnJpZXI8Q3VycmVudD4sIEluZGV4PgoJCQl7CgkJCQllbnVtIDogdHlwZTo6aW5kZXhfdCB7IHZhbHVlID0gKEN1cnJlbnQgPT0gSW5kZXgpID8gMSA6IDAgfTsKCQkJfTsKCgkJCXRlbXBsYXRlIDx1bnNpZ25lZCBJbmRleCwgdW5zaWduZWQgQ3VycmVudCwgdW5zaWduZWQgLi4uIFJlc3Q+CgkJCXN0cnVjdCBpbmRleF9jYXJyaWVyX2NvdW50PGluZGV4X2NhcnJpZXI8Q3VycmVudCwgUmVzdCAuLi4gPiwgSW5kZXg+CgkJCXsKCQkJCWVudW0gOiB0eXBlOjppbmRleF90IHsgdmFsdWUgPSBpbmRleF9jYXJyaWVyX2NvdW50PGluZGV4X2NhcnJpZXI8Q3VycmVudD4sIEluZGV4Pjo6dmFsdWUgKyBpbmRleF9jYXJyaWVyX2NvdW50PGluZGV4X2NhcnJpZXI8UmVzdCAuLi4gPiwgSW5kZXg+Ojp2YWx1ZSB9OwoJCQl9OwoJCX0KCgkJdGVtcGxhdGUgPHR5cGVuYW1lLCB0eXBlbmFtZT4KCQlzdHJ1Y3QgY2Fycmllcl9jb3VudDsKCgkJdGVtcGxhdGUgPHR5cGVuYW1lIC4uLiBUeXBlcywgdHlwZW5hbWUgQ3VycmVudD4KCQlzdHJ1Y3QgY2Fycmllcl9jb3VudDx0eXBlX2NhcnJpZXI8VHlwZXMgLi4uID4sIHR5cGVfY2FycmllcjxDdXJyZW50Pj4KCQl7CgkJCWVudW0gOiB0eXBlOjppbmRleF90IHsgdmFsdWUgPSBkZXRhaWw6OnR5cGVfY2Fycmllcl9jb3VudDx0eXBlX2NhcnJpZXI8VHlwZXMgLi4uID4sIEN1cnJlbnQ+Ojp2YWx1ZSB9OwoJCX07CgoJCXRlbXBsYXRlIDx1bnNpZ25lZCAuLi4gSW5kaWNlcywgdW5zaWduZWQgQ3VycmVudD4KCQlzdHJ1Y3QgY2Fycmllcl9jb3VudDxpbmRleF9jYXJyaWVyPEluZGljZXMgLi4uID4sIGluZGV4X2NhcnJpZXI8Q3VycmVudD4+CgkJewoJCQllbnVtIDogdHlwZTo6aW5kZXhfdCB7IHZhbHVlID0gZGV0YWlsOjppbmRleF9jYXJyaWVyX2NvbnRhaW5zPGluZGV4X2NhcnJpZXI8SW5kaWNlcyAuLi4gPiwgQ3VycmVudD46OnZhbHVlIH07CgkJfTsKCgkJLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+CgoJCW5hbWVzcGFjZSBkZXRhaWwgewoJCQl0ZW1wbGF0ZSA8dHlwZW5hbWUsIHR5cGVuYW1lLCB1bnNpZ25lZCwgdW5zaWduZWQsIHVuc2lnbmVkPgoJCQlzdHJ1Y3QgdHlwZV9jYXJyaWVyX250aF9pbmRleDsKCgkJCXRlbXBsYXRlIDx0eXBlbmFtZSBUeXBlLCB1bnNpZ25lZCBJbmRleCwgdW5zaWduZWQgQ291bnQsIHVuc2lnbmVkIFRhcmdldD4KCQkJc3RydWN0IHR5cGVfY2Fycmllcl9udGhfaW5kZXg8dHlwZV9jYXJyaWVyPD4sIFR5cGUsIEluZGV4LCBDb3VudCwgVGFyZ2V0PgoJCQl7CgkJCQllbnVtIDogdHlwZTo6aW5kZXhfdCB7IHZhbHVlID0gMCB9OwoJCQl9OwoKCQkJdGVtcGxhdGUgPHR5cGVuYW1lIFR5cGUsIHR5cGVuYW1lIEN1cnJlbnQsIHVuc2lnbmVkIEluZGV4LCB1bnNpZ25lZCBDb3VudCwgdW5zaWduZWQgVGFyZ2V0PgoJCQlzdHJ1Y3QgdHlwZV9jYXJyaWVyX250aF9pbmRleDx0eXBlX2NhcnJpZXI8Q3VycmVudD4sIFR5cGUsIEluZGV4LCBDb3VudCwgVGFyZ2V0PgoJCQl7CgkJCQllbnVtIDogdHlwZTo6aW5kZXhfdCB7IHZhbHVlID0gKChDb3VudCA9PSBUYXJnZXQpICYmIHN0ZDo6aXNfc2FtZTxDdXJyZW50LCBUeXBlPjo6dmFsdWUpID8gSW5kZXggOiAwIH07CgkJCX07CgoJCQl0ZW1wbGF0ZSA8dHlwZW5hbWUgVHlwZSwgdHlwZW5hbWUgQ3VycmVudCwgdHlwZW5hbWUgLi4uIFJlc3QsIHVuc2lnbmVkIEluZGV4LCB1bnNpZ25lZCBDb3VudCwgdW5zaWduZWQgVGFyZ2V0PgoJCQlzdHJ1Y3QgdHlwZV9jYXJyaWVyX250aF9pbmRleDx0eXBlX2NhcnJpZXI8Q3VycmVudCwgUmVzdCAuLi4gPiwgVHlwZSwgSW5kZXgsIENvdW50LCBUYXJnZXQ+CgkJCXsKCQkJCWVudW0gOiB0eXBlOjppbmRleF90CgkJCQl7CgkJCQkJdmFsdWUgPSB0eXBlX2NhcnJpZXJfbnRoX2luZGV4PHR5cGVfY2FycmllcjxDdXJyZW50PiwgVHlwZSwgSW5kZXgsIENvdW50LCBUYXJnZXQ+Ojp2YWx1ZSArIHR5cGVfY2Fycmllcl9udGhfaW5kZXg8dHlwZV9jYXJyaWVyPFJlc3QgLi4uID4sIFR5cGUsIEluZGV4ICsgMSwgQ291bnQgKyAoc3RkOjppc19zYW1lPEN1cnJlbnQsIFR5cGU+Ojp2YWx1ZSA/IDEgOiAwKSwgVGFyZ2V0Pjo6dmFsdWUKCQkJCX07CgkJCX07CgoJCQl0ZW1wbGF0ZSA8dHlwZW5hbWUsIHVuc2lnbmVkLCB1bnNpZ25lZCwgdW5zaWduZWQsIHVuc2lnbmVkPgoJCQlzdHJ1Y3QgaW5kZXhfY2Fycmllcl9udGhfaW5kZXg7CgoJCQl0ZW1wbGF0ZSA8dW5zaWduZWQgT3RoZXIsIHVuc2lnbmVkIEluZGV4LCB1bnNpZ25lZCBDb3VudCwgdW5zaWduZWQgVGFyZ2V0PgoJCQlzdHJ1Y3QgaW5kZXhfY2Fycmllcl9udGhfaW5kZXg8aW5kZXhfY2Fycmllcjw+LCBPdGhlciwgSW5kZXgsIENvdW50LCBUYXJnZXQ+CgkJCXsKCQkJCWVudW0gOiB0eXBlOjppbmRleF90IHsgdmFsdWUgPSAwIH07CgkJCX07CgoJCQl0ZW1wbGF0ZSA8dW5zaWduZWQgT3RoZXIsIHVuc2lnbmVkIEN1cnJlbnQsIHVuc2lnbmVkIEluZGV4LCB1bnNpZ25lZCBDb3VudCwgdW5zaWduZWQgVGFyZ2V0PgoJCQlzdHJ1Y3QgaW5kZXhfY2Fycmllcl9udGhfaW5kZXg8aW5kZXhfY2FycmllcjxDdXJyZW50PiwgT3RoZXIsIEluZGV4LCBDb3VudCwgVGFyZ2V0PgoJCQl7CgkJCQllbnVtIDogdHlwZTo6aW5kZXhfdCB7IHZhbHVlID0gKChDb3VudCA9PSBUYXJnZXQpICYmIChDdXJyZW50ID09IE90aGVyKSkgPyBJbmRleCA6IDAgfTsKCQkJfTsKCgkJCXRlbXBsYXRlIDx1bnNpZ25lZCBPdGhlciwgdW5zaWduZWQgQ3VycmVudCwgdW5zaWduZWQgLi4uIFJlc3QsIHVuc2lnbmVkIEluZGV4LCB1bnNpZ25lZCBDb3VudCwgdW5zaWduZWQgVGFyZ2V0PgoJCQlzdHJ1Y3QgaW5kZXhfY2Fycmllcl9udGhfaW5kZXg8aW5kZXhfY2FycmllcjxDdXJyZW50LCBSZXN0IC4uLiA+LCBPdGhlciwgSW5kZXgsIENvdW50LCBUYXJnZXQ+CgkJCXsKCQkJCWVudW0gOiB0eXBlOjppbmRleF90IHsgdmFsdWUgPSBpbmRleF9jYXJyaWVyX250aF9pbmRleDxpbmRleF9jYXJyaWVyPEN1cnJlbnQ+LCBPdGhlciwgSW5kZXgsIENvdW50LCBUYXJnZXQ+Ojp2YWx1ZSArIGluZGV4X2NhcnJpZXJfbnRoX2luZGV4PGluZGV4X2NhcnJpZXI8UmVzdCAuLi4gPiwgT3RoZXIsIEluZGV4ICsgMSwgQ291bnQgKyAoQ3VycmVudCA9PSBPdGhlciA/IDEgOiAwKSwgVGFyZ2V0Pjo6dmFsdWUgfTsKCQkJfTsKCQl9CgoJCXRlbXBsYXRlIDx0eXBlbmFtZSwgdHlwZW5hbWUsIHVuc2lnbmVkPgoJCXN0cnVjdCBjYXJyaWVyX250aF9pbmRleDsKCgkJdGVtcGxhdGUgPHR5cGVuYW1lIC4uLiBUeXBlcywgdHlwZW5hbWUgQ3VycmVudCwgdW5zaWduZWQgTnVtYmVyPgoJCXN0cnVjdCBjYXJyaWVyX250aF9pbmRleDx0eXBlX2NhcnJpZXI8VHlwZXMgLi4uID4sIEN1cnJlbnQsIE51bWJlcj4KCQl7CgkJCXN0YXRpY19hc3NlcnQoY2Fycmllcl9jb3VudDx0eXBlX2NhcnJpZXI8VHlwZXMgLi4uID4sIHR5cGVfY2FycmllcjxDdXJyZW50Pj46OnZhbHVlID4gTnVtYmVyLCAiVHlwZSBjYXJyaWVyIGRvZXMgbm90IGNvbnRhaW4gdHlwZSB3aXRoIHRoaXMgaW5kZXghIik7CgkJCWVudW0gOiB0eXBlOjppbmRleF90IHsgdmFsdWUgPSBkZXRhaWw6OnR5cGVfY2Fycmllcl9udGhfaW5kZXg8dHlwZV9jYXJyaWVyPFR5cGVzIC4uLiA+LCBDdXJyZW50LCAwLCAwLCBOdW1iZXI+Ojp2YWx1ZSB9OwoJCX07CgoJCXRlbXBsYXRlIDx1bnNpZ25lZCAuLi4gSW5kaWNlcywgdW5zaWduZWQgQ3VycmVudCwgdW5zaWduZWQgTnVtYmVyPgoJCXN0cnVjdCBjYXJyaWVyX250aF9pbmRleDxpbmRleF9jYXJyaWVyPEluZGljZXMgLi4uID4sIGluZGV4X2NhcnJpZXI8Q3VycmVudD4sIE51bWJlcj4KCQl7CgkJCXN0YXRpY19hc3NlcnQoY2Fycmllcl9jb3VudDxpbmRleF9jYXJyaWVyPEluZGljZXMgLi4uID4sIGluZGV4X2NhcnJpZXI8Q3VycmVudD4+Ojp2YWx1ZSA+IE51bWJlciwgIkluZGV4IGNhcnJpZXIgZG9lcyBub3QgY29udGFpbiBpbmRleCB3aXRoIHRoaXMgaW5kZXghIik7CgkJCWVudW0gOiB0eXBlOjppbmRleF90IHsgdmFsdWUgPSBkZXRhaWw6OmluZGV4X2NhcnJpZXJfbnRoX2luZGV4PGluZGV4X2NhcnJpZXI8SW5kaWNlcyAuLi4gPiwgQ3VycmVudCwgMCwgMCwgTnVtYmVyPjo6dmFsdWUgfTsKCQl9OwoKCQluYW1lc3BhY2UgZGV0YWlsCgkJewoJCQl0ZW1wbGF0ZSA8dHlwZW5hbWU+CgkJCXN0cnVjdCBwYXJhbWV0ZXJzOwoKCQkJdGVtcGxhdGUgPHR5cGVuYW1lIFJldHVybiwgdHlwZW5hbWUgVHlwZSwgdHlwZW5hbWUgLi4uIEFyZ3VtZW50cz4KCQkJc3RydWN0IHBhcmFtZXRlcnM8UmV0dXJuKFR5cGU6OiopKEFyZ3VtZW50cyAuLi4pPgoJCQl7CgkJCQl1c2luZyB0eXBlID0gdHlwZV9jYXJyaWVyPHN0ZDo6ZGVjYXlfdDxBcmd1bWVudHM+IC4uLiA+OwoJCQl9OwoKCQkJdGVtcGxhdGUgPHR5cGVuYW1lIFJldHVybiwgdHlwZW5hbWUgVHlwZSwgdHlwZW5hbWUgLi4uIEFyZ3VtZW50cz4KCQkJc3RydWN0IHBhcmFtZXRlcnM8UmV0dXJuKFR5cGU6OiopKEFyZ3VtZW50cyAuLi4pIGNvbnN0PgoJCQl7CgkJCQl1c2luZyB0eXBlID0gdHlwZV9jYXJyaWVyPHN0ZDo6ZGVjYXlfdDxBcmd1bWVudHM+IC4uLiA+OwoJCQl9OwoJCX0KCgkJdGVtcGxhdGUgPHR5cGVuYW1lIFR5cGU+CgkJdXNpbmcgcGFyYW1ldGVyc190ID0gdHlwZW5hbWUgZGV0YWlsOjpwYXJhbWV0ZXJzPGRlY2x0eXBlKCZUeXBlOjpvcGVyYXRvciAoKSk+Ojp0eXBlOwoKCQluYW1lc3BhY2UgZGV0YWlsCgkJewoJCQl0ZW1wbGF0ZSA8dHlwZW5hbWUsIHR5cGVuYW1lLCB0eXBlbmFtZSwgdHlwZW5hbWU+CgkJCXN0cnVjdCBtYXBfcGFyYW1ldGVyc190b19jYXJyaWVyOwoKCQkJdGVtcGxhdGUgPHR5cGVuYW1lIFBhcmFtZXRlciwgdHlwZW5hbWUgLi4uIFR5cGVzPgoJCQlzdHJ1Y3QgbWFwX3BhcmFtZXRlcnNfdG9fY2Fycmllcjx0eXBlX2NhcnJpZXI8UGFyYW1ldGVyPiwgdHlwZV9jYXJyaWVyPFR5cGVzIC4uLiA+LCBpbmRleF9jYXJyaWVyPD4sIHR5cGVfY2Fycmllcjw+PgoJCQl7CgkJCQl1c2luZyB0eXBlID0gaW5kZXhfY2FycmllcjxjYXJyaWVyX250aF9pbmRleDx0eXBlX2NhcnJpZXI8VHlwZXMgLi4uID4sIFBhcmFtZXRlciwgMD46OnZhbHVlPjsKCQkJfTsKCgkJCXRlbXBsYXRlIDx0eXBlbmFtZSBQYXJhbWV0ZXIsIHR5cGVuYW1lIC4uLiBUeXBlcywgdW5zaWduZWQgLi4uIEluZGljZXMsIHR5cGVuYW1lIC4uLiBWaXNpdGVkPgoJCQlzdHJ1Y3QgbWFwX3BhcmFtZXRlcnNfdG9fY2Fycmllcjx0eXBlX2NhcnJpZXI8UGFyYW1ldGVyPiwgdHlwZV9jYXJyaWVyPFR5cGVzIC4uLiA+LCBpbmRleF9jYXJyaWVyPEluZGljZXMgLi4uID4sIHR5cGVfY2FycmllcjxWaXNpdGVkIC4uLiA+PgoJCQl7CgkJCQl1c2luZyB0eXBlID0gaW5kZXhfY2FycmllcjxJbmRpY2VzIC4uLiAsIGNhcnJpZXJfbnRoX2luZGV4PHR5cGVfY2FycmllcjxUeXBlcyAuLi4gPiwgUGFyYW1ldGVyLCBjYXJyaWVyX2NvdW50PHR5cGVfY2FycmllcjxWaXNpdGVkIC4uLiA+LCB0eXBlX2NhcnJpZXI8UGFyYW1ldGVyPj46OnZhbHVlPjo6dmFsdWU+OwoJCQl9OwoKCQkJdGVtcGxhdGUgPHR5cGVuYW1lIEN1cnJlbnQsIHR5cGVuYW1lIC4uLiBQYXJhbWV0ZXJzLCB0eXBlbmFtZSAuLi4gVHlwZXM+CgkJCXN0cnVjdCBtYXBfcGFyYW1ldGVyc190b19jYXJyaWVyPHR5cGVfY2FycmllcjxDdXJyZW50LCBQYXJhbWV0ZXJzIC4uLiA+LCB0eXBlX2NhcnJpZXI8VHlwZXMgLi4uID4sIGluZGV4X2NhcnJpZXI8PiwgdHlwZV9jYXJyaWVyPD4+CgkJCXsKCQkJCXVzaW5nIHR5cGUgPSB0eXBlbmFtZSBtYXBfcGFyYW1ldGVyc190b19jYXJyaWVyPHR5cGVfY2FycmllcjxQYXJhbWV0ZXJzIC4uLiA+LCB0eXBlX2NhcnJpZXI8VHlwZXMgLi4uID4sIGluZGV4X2NhcnJpZXI8Y2Fycmllcl9udGhfaW5kZXg8dHlwZV9jYXJyaWVyPFR5cGVzIC4uLiA+LCBDdXJyZW50LCAwPjo6dmFsdWU+LCB0eXBlX2NhcnJpZXI8Q3VycmVudD4+Ojp0eXBlOwoJCQl9OwoKCQkJdGVtcGxhdGUgPHR5cGVuYW1lIEN1cnJlbnQsIHR5cGVuYW1lIC4uLiBQYXJhbWV0ZXJzLCB0eXBlbmFtZSAuLi4gVHlwZXMsIHVuc2lnbmVkIC4uLiBJbmRpY2VzLCB0eXBlbmFtZSAuLi4gVmlzaXRlZD4KCQkJc3RydWN0IG1hcF9wYXJhbWV0ZXJzX3RvX2NhcnJpZXI8dHlwZV9jYXJyaWVyPEN1cnJlbnQsIFBhcmFtZXRlcnMgLi4uID4sIHR5cGVfY2FycmllcjxUeXBlcyAuLi4gPiwgaW5kZXhfY2FycmllcjxJbmRpY2VzIC4uLiA+LCB0eXBlX2NhcnJpZXI8VmlzaXRlZCAuLi4gPj4KCQkJewoJCQkJdXNpbmcgdHlwZSA9IHR5cGVuYW1lIG1hcF9wYXJhbWV0ZXJzX3RvX2NhcnJpZXI8dHlwZV9jYXJyaWVyPFBhcmFtZXRlcnMgLi4uID4sIHR5cGVfY2FycmllcjxUeXBlcyAuLi4gPiwgaW5kZXhfY2FycmllcjxJbmRpY2VzIC4uLiAsIGNhcnJpZXJfbnRoX2luZGV4PHR5cGVfY2FycmllcjxUeXBlcyAuLi4gPiwgQ3VycmVudCwgY2Fycmllcl9jb3VudDx0eXBlX2NhcnJpZXI8VmlzaXRlZCAuLi4gPiwgdHlwZV9jYXJyaWVyPEN1cnJlbnQ+Pjo6dmFsdWU+Ojp2YWx1ZT4sIHR5cGVfY2FycmllcjxWaXNpdGVkIC4uLiAsIEN1cnJlbnQ+Pjo6dHlwZTsKCQkJfTsKCQl9CgoJCXRlbXBsYXRlIDx0eXBlbmFtZSBQYXJhbWV0ZXJzLCB0eXBlbmFtZSBDYXJyaWVyPgoJCXVzaW5nIG1hcF9wYXJhbWV0ZXJzX3RvX2NhcnJpZXJfdCA9IHR5cGVuYW1lIGRldGFpbDo6bWFwX3BhcmFtZXRlcnNfdG9fY2FycmllcjxQYXJhbWV0ZXJzLCBDYXJyaWVyLCBpbmRleF9jYXJyaWVyPD4sIHR5cGVfY2Fycmllcjw+Pjo6dHlwZTsKCX0KCgluYW1lc3BhY2UgZGV0YWlsCgl7CgkJdGVtcGxhdGUgPHR5cGVuYW1lIC4uLiBUeXBlcywgdW5zaWduZWQgLi4uIEluZGljZXMsIHR5cGVuYW1lIEZ1bmN0b3I+CgkJZGVjbHR5cGUoYXV0bykgdGhpc193aXRoKHN0ZDo6dHVwbGU8VHlwZXMgLi4uID4gJiBvYmplY3QsIHV0aWxpdHk6OmluZGV4X2NhcnJpZXI8SW5kaWNlcyAuLi4gPiwgRnVuY3RvciYmIGZ1bmN0b3IpCgkJewoJCQlyZXR1cm4gZnVuY3RvcihzdGQ6OmdldDxJbmRpY2VzPihvYmplY3QpIC4uLik7CgkJfQoJfQoKCXRlbXBsYXRlIDx0eXBlbmFtZSAuLi4gVHlwZXMsIHR5cGVuYW1lIEZ1bmN0b3I+CglkZWNsdHlwZShhdXRvKSBhcHBseShzdGQ6OnR1cGxlPFR5cGVzIC4uLiA+ICYgb2JqZWN0LCBGdW5jdG9yICYmIGZ1bmN0b3IpCgl7CgkJc3RhdGljX2Fzc2VydCh1dGlsaXR5OjpjYXJyaWVyX2NvbnRhaW5zPHV0aWxpdHk6OnR5cGVfY2FycmllcjxUeXBlcyAuLi4gPiwgdXRpbGl0eTo6cGFyYW1ldGVyc190PEZ1bmN0b3I+Pjo6dmFsdWUsICJUaGlzIHR1cGxlIGRvZXMgbm90IGNvbnRhaW4gb25lIG9yIG1vcmUgb2YgdGhlc2UgdHlwZXMhIik7CgoJCWNvbnN0ZXhwciBhdXRvIHBhcmFtZXRlcnMgPSB1dGlsaXR5OjptYXBfcGFyYW1ldGVyc190b19jYXJyaWVyX3Q8dXRpbGl0eTo6cGFyYW1ldGVyc190PEZ1bmN0b3I+LCB1dGlsaXR5Ojp0eXBlX2NhcnJpZXI8VHlwZXMgLi4uID4+CgkJewoJCQkvLyAuLi4KCQl9OwoKCQlyZXR1cm4gZGV0YWlsOjp0aGlzX3dpdGgob2JqZWN0LCBwYXJhbWV0ZXJzLCBzdGQ6OmZvcndhcmQ8RnVuY3Rvcj4oZnVuY3RvcikpOwoJfQp9CgppbnQgbWFpbigpIHsKCWF1dG8geCA9IHN0ZDo6bWFrZV90dXBsZSgxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LjAsIDksIDEwLCAxMSwgMzMsIDEzLCAxNCwgMTUuZiwgMTYsIDE3LCAxOCwgMik7CgoJc3RkOjpjb3V0IDw8IGFkdjo6YXBwbHkoeCwgW10oZmxvYXQgYSwgZG91YmxlIGIsIGludCBjLCBpbnQgZCkgewoKCQlzdGQ6OmNvdXQgPDwgYSA8PCBzdGQ6OmVuZGw7CgkJc3RkOjpjb3V0IDw8IGIgPDwgc3RkOjplbmRsOwoJCXN0ZDo6Y291dCA8PCBjIDw8IHN0ZDo6ZW5kbDsKCQlzdGQ6OmNvdXQgPDwgZCA8PCBzdGQ6OmVuZGw7CgkJCgkJcmV0dXJuIGQ7Cgl9KTsKfQ==