#include <iostream>
#include <set>
#include <stdexcept>
#include <string>
#include <functional>
template<typename T>
struct identity
{
using type = T;
};
template<char ... Ch>
struct const_string : identity<const_string<Ch...>>
{
static char constexpr nt_arr[]{ Ch..., '\0' };
static std::size_t constexpr length = sizeof...(Ch);
private:
constexpr std::size_t _count_impl( char c, std::size_t index )
{
return nt_arr[index] == c + (index == 0 ? 0 : _count_impl(c, index - 1));
}
public:
constexpr std::size_t count( char c )
{ return _count_impl( c, sizeof(nt_arr) - 1 ); }
};
template<char ... Ch>
char constexpr const_string<Ch...>::nt_arr[];
/// concat_strings //////////////////////////////////////////////////////////////////
template<typename, typename> struct concat_strings;
template<char ... first,
char ... second>
struct concat_strings<const_string<first...>, const_string<second...>> : const_string<first..., second...> {};
/// type_list ///////////////////////////////////////////////////////////////////////
// Geht natürlich auch ohne Rekursion, ist nunmal auf die Schnelle gemacht:
template<std::size_t index, typename T, typename ... Types>
struct at : at<index-1, Types...> {};
template<typename T, typename ... Types>
struct at<0, T, Types...> : identity<T> {};
template<typename ... Types>
struct type_list : identity<type_list<Types...>>
{
static std::size_t constexpr length = sizeof...(Types);
template<std::size_t index>
struct get : at<index, Types...> {};
};
template<typename... Args>
type_list<Args...> arg_type_list( Args&&... );
template<std::size_t i, typename T>
struct indexed_type
{
static constexpr std::size_t index = i;
using type = T;
};
/// concat_type_lists //////////////////////////////////////////////////////////
template<typename, typename> struct concat_type_lists;
template<typename ... first,
typename ... second>
struct concat_type_lists<type_list<first...>, type_list<second...>> : type_list<first..., second...> {};
/// split ////////////////////////////////////////////////////////////////////////
template<char, typename, typename, typename> struct split_on;
template<char token,
typename ... pairs>
struct split_on< token, type_list<pairs...>, const_string<>, const_string<> > : type_list<pairs...> {};
template<char token,
char ... last,
typename ... pairs>
struct split_on< token, type_list<pairs...>, const_string<last...>, const_string<> > : type_list< pairs..., indexed_type<0, const_string<last...>> > {};
// Kein Token vorhanden:
template<char token,
char current,
char ... last,
char ... tail,
typename ... pairs>
struct split_on< token, type_list<pairs...>, const_string<last...>, const_string<current, tail...> > : split_on<token, type_list<pairs...>, const_string<last..., current>, const_string<tail...>> {};
template<char C>
struct enable_if_digit
{
static_assert( C >= '0' && C <= '9', "Not a digit!" );
static constexpr char ch = C;
static constexpr int number = C - '0';
};
template<char token,
char digit,
char ... last,
typename ... pairs>
struct split_on< token, type_list<pairs...>, const_string<last...>, const_string<token, digit> > :
type_list<pairs..., indexed_type<enable_if_digit<digit>::number, const_string<last...>>, indexed_type<0, const_string<>>> {};
template<char token,
char digit,
char ... last,
char ... tail,
typename ... pairs>
struct split_on< token, type_list<pairs...>, const_string<last...>, const_string<token, digit, tail...> > :
split_on<token, type_list< pairs..., indexed_type<enable_if_digit<digit>::number, const_string<last...>> >, const_string<>, const_string<tail...>> {};
template<char token,
char ... last,
char ... tail,
typename ... pairs>
struct split_on< token, type_list<pairs...>, const_string<last...>, const_string<token, token, tail...> > : split_on<token, type_list<pairs...>, const_string<last..., token, token>, const_string<tail...>> {};
template<char c, typename> struct split;
template<char c, char... chars> struct split<c, const_string<chars...>> : split_on<c, type_list<>, const_string<>, const_string<chars...>> {};
/// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<char, typename> struct rtrim;
template<char token, char first, char ... ch>
struct rtrim<token, const_string<first, ch...>> : concat_strings<const_string<first>, typename rtrim<token, const_string<ch...>>::type> {};
template<char token, char ... ch>
struct rtrim<token, const_string<token, ch...>> : const_string<> {};
template<char token>
struct rtrim<token, const_string<>> : const_string<> {};
/// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<std::size_t Index, typename T>
struct rack
{
static constexpr std::size_t index = Index;
T&& arg;
rack( T&& a ):
arg( std::forward<T>(a) ) {}
};
/// index-list (v. camper)
template<int ... args>
struct index_list
{
static constexpr int arr[]{args...};
using type = index_list;
};
template <typename T, typename U> struct concat_list;
template <int... i, int... j>
struct concat_list<index_list<i...>,index_list<j...>>
: index_list<i..., (sizeof...(i)+i)..., (2*sizeof...(i)+j)...> {};
template <int N> struct make_index_list
: concat_list<typename make_index_list<N/2>::type, typename make_index_list<N%2>::type> {};
template <> struct make_index_list<1> : index_list<0> {};
template <> struct make_index_list<0> : index_list<> {};
/// </camper> /
template<typename, typename...> struct Indicer;
template<int... indices, typename... Args>
struct Indicer<index_list<indices...>, Args...> : rack<indices, Args>...
{
Indicer( Args&&... args ):
rack<indices, Args>(std::forward<Args>(args))... {}
};
template<typename format_string,
typename CharT,
typename Traits,
typename index_list>
struct ts_printf_env;
template<typename format_string,
typename CharT,
typename Traits,
int... indices>
struct ts_printf_env<format_string, CharT, Traits, index_list<indices...>>
{
static char constexpr format_sign = '%';
using string_list = typename split<format_sign, format_string>::type;
private:
template<std::size_t type_list_index>
static void ts_printf_impl( std::basic_ostream<CharT, Traits>& os )
{
using to_put = typename string_list::template get<type_list_index>::type::type;
if( os.rdbuf()->sputn( to_put::nt_arr, to_put::length ) != to_put::length )
os.setstate( std::ios_base::badbit );
}
template<std::size_t type_list_index,
typename FirstArg,
typename ...Args>
static void ts_printf_impl( std::basic_ostream<CharT, Traits>& os,
FirstArg&& first,
Args&&... tail)
{
ts_printf_impl<type_list_index>( os );
if( os << std::forward<FirstArg>(first) )
ts_printf_impl<type_list_index + 1>( os, std::forward<Args>(tail)... );
}
public:
template<typename ... Args>
static std::basic_ostream<CharT, Traits>& ts_printf( std::basic_ostream<CharT, Traits>& os, Args&&... args )
{
static_assert( sizeof...(Args) + 1 == string_list::length, "Invalid format string!" );
typename std::basic_ostream<CharT, Traits>::sentry ok{os};
if( ok ) try
{
Indicer<typename make_index_list<sizeof...(Args)>::type, Args...> indicer( std::forward<Args>(args)... );
#define index string_list::template get<indices>::type::index
ts_printf_impl<0>( os, indicer.rack< index,
typename at<index, Args...>::type >::arg... );
#undef index
}
catch( std::ios::failure const& )
{ throw; }
catch(...)
{
os.clear( os.rdstate() | std::ios_base::badbit );
if( os.exceptions() & std::ios_base::badbit )
throw;
}
return os;
}
};
#define SPLIT_1(str,pos) str [ pos < sizeof str ? pos : sizeof(str) - 1 ]
#define SPLIT_2(str,x) SPLIT_1(str,x), SPLIT_1(str,x + 1)
#define SPLIT_4(str,x) SPLIT_2(str,x), SPLIT_2(str,x + 2)
#define SPLIT_8(str,x) SPLIT_4(str,x), SPLIT_4(str,x + 4)
#define SPLIT_16(str,x) SPLIT_8(str,x), SPLIT_8(str,x + 8)
#define SPLIT_32(str,x) SPLIT_16(str,x), SPLIT_16(str,x + 16)
#define SPLIT_64(str,x) SPLIT_32(str,x), SPLIT_32(str,x + 32)
#define SPLIT_128(str,x) SPLIT_64(str,x), SPLIT_64(str,x + 64)
#define ts_printf(os, format, ...) ts_printf_env<typename rtrim<'\0', const_string<SPLIT_128(format, 0)>>::type, \
decltype(os)::char_type, \
decltype(os)::traits_type, \
make_index_list<decltype(arg_type_list(__VA_ARGS__))::length>::type>::ts_printf( os, __VA_ARGS__ )
int main()
{
ts_printf(std::cout, "%1 + %2 = %0", 10, 6, 4);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c2V0PgojaW5jbHVkZSA8c3RkZXhjZXB0PgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBpZGVudGl0eQp7CiAgICB1c2luZyB0eXBlID0gVDsKfTsKCnRlbXBsYXRlPGNoYXIgLi4uIENoPgpzdHJ1Y3QgY29uc3Rfc3RyaW5nIDogaWRlbnRpdHk8Y29uc3Rfc3RyaW5nPENoLi4uPj4KewoJc3RhdGljIGNoYXIgY29uc3RleHByIG50X2FycltdeyBDaC4uLiwgJ1wwJyB9OwoKCXN0YXRpYyBzdGQ6OnNpemVfdCBjb25zdGV4cHIgbGVuZ3RoID0gc2l6ZW9mLi4uKENoKTsKCnByaXZhdGU6Cgljb25zdGV4cHIgc3RkOjpzaXplX3QgX2NvdW50X2ltcGwoIGNoYXIgYywgc3RkOjpzaXplX3QgaW5kZXggKQoJewoJCXJldHVybiBudF9hcnJbaW5kZXhdID09IGMgKyAoaW5kZXggPT0gMCA/IDAgOiBfY291bnRfaW1wbChjLCBpbmRleCAtIDEpKTsKCX0KCnB1YmxpYzoKCWNvbnN0ZXhwciBzdGQ6OnNpemVfdCBjb3VudCggY2hhciBjICkKCXsgcmV0dXJuIF9jb3VudF9pbXBsKCBjLCBzaXplb2YobnRfYXJyKSAtIDEgKTsgIH0KfTsKCnRlbXBsYXRlPGNoYXIgLi4uIENoPgpjaGFyIGNvbnN0ZXhwciBjb25zdF9zdHJpbmc8Q2guLi4+OjpudF9hcnJbXTsKCi8vLyBjb25jYXRfc3RyaW5ncyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCnRlbXBsYXRlPHR5cGVuYW1lLCB0eXBlbmFtZT4gc3RydWN0IGNvbmNhdF9zdHJpbmdzOwoKdGVtcGxhdGU8Y2hhciAuLi4gZmlyc3QsCiAgICAgICAgIGNoYXIgLi4uIHNlY29uZD4Kc3RydWN0IGNvbmNhdF9zdHJpbmdzPGNvbnN0X3N0cmluZzxmaXJzdC4uLj4sIGNvbnN0X3N0cmluZzxzZWNvbmQuLi4+PiA6IGNvbnN0X3N0cmluZzxmaXJzdC4uLiwgc2Vjb25kLi4uPiB7fTsKCi8vLyB0eXBlX2xpc3QgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCi8vIEdlaHQgbmF0w7xybGljaCBhdWNoIG9obmUgUmVrdXJzaW9uLCBpc3QgbnVubWFsIGF1ZiBkaWUgU2NobmVsbGUgZ2VtYWNodDoKdGVtcGxhdGU8c3RkOjpzaXplX3QgaW5kZXgsIHR5cGVuYW1lIFQsIHR5cGVuYW1lIC4uLiBUeXBlcz4Kc3RydWN0IGF0IDogYXQ8aW5kZXgtMSwgVHlwZXMuLi4+IHt9Owp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSAuLi4gVHlwZXM+CnN0cnVjdCBhdDwwLCBULCBUeXBlcy4uLj4gOiBpZGVudGl0eTxUPiB7fTsKCnRlbXBsYXRlPHR5cGVuYW1lIC4uLiBUeXBlcz4Kc3RydWN0IHR5cGVfbGlzdCA6IGlkZW50aXR5PHR5cGVfbGlzdDxUeXBlcy4uLj4+CnsKCXN0YXRpYyBzdGQ6OnNpemVfdCBjb25zdGV4cHIgbGVuZ3RoID0gc2l6ZW9mLi4uKFR5cGVzKTsKCgl0ZW1wbGF0ZTxzdGQ6OnNpemVfdCBpbmRleD4KCXN0cnVjdCBnZXQgOiBhdDxpbmRleCwgVHlwZXMuLi4+IHt9Owp9OwoKdGVtcGxhdGU8dHlwZW5hbWUuLi4gQXJncz4KdHlwZV9saXN0PEFyZ3MuLi4+IGFyZ190eXBlX2xpc3QoIEFyZ3MmJi4uLiApOwoKdGVtcGxhdGU8c3RkOjpzaXplX3QgaSwgdHlwZW5hbWUgVD4Kc3RydWN0IGluZGV4ZWRfdHlwZQp7CglzdGF0aWMgY29uc3RleHByIHN0ZDo6c2l6ZV90IGluZGV4ID0gaTsKCXVzaW5nIHR5cGUgPSBUOwp9OwoKLy8vIGNvbmNhdF90eXBlX2xpc3RzIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCnRlbXBsYXRlPHR5cGVuYW1lLCB0eXBlbmFtZT4gc3RydWN0IGNvbmNhdF90eXBlX2xpc3RzOwoKdGVtcGxhdGU8dHlwZW5hbWUgLi4uIGZpcnN0LAogICAgICAgICB0eXBlbmFtZSAuLi4gc2Vjb25kPgpzdHJ1Y3QgY29uY2F0X3R5cGVfbGlzdHM8dHlwZV9saXN0PGZpcnN0Li4uPiwgdHlwZV9saXN0PHNlY29uZC4uLj4+IDogdHlwZV9saXN0PGZpcnN0Li4uLCBzZWNvbmQuLi4+IHt9OwoKLy8vIHNwbGl0IC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKdGVtcGxhdGU8Y2hhciwgdHlwZW5hbWUsIHR5cGVuYW1lLCB0eXBlbmFtZT4gc3RydWN0IHNwbGl0X29uOwoKdGVtcGxhdGU8Y2hhciB0b2tlbiwKICAgICAgICAgdHlwZW5hbWUgLi4uIHBhaXJzPgpzdHJ1Y3Qgc3BsaXRfb248IHRva2VuLCB0eXBlX2xpc3Q8cGFpcnMuLi4+LCBjb25zdF9zdHJpbmc8PiwgY29uc3Rfc3RyaW5nPD4gPiA6IHR5cGVfbGlzdDxwYWlycy4uLj4ge307CgoKdGVtcGxhdGU8Y2hhciB0b2tlbiwKICAgICAgICAgY2hhciAuLi4gbGFzdCwKICAgICAgICAgdHlwZW5hbWUgLi4uIHBhaXJzPgpzdHJ1Y3Qgc3BsaXRfb248IHRva2VuLCB0eXBlX2xpc3Q8cGFpcnMuLi4+LCBjb25zdF9zdHJpbmc8bGFzdC4uLj4sIGNvbnN0X3N0cmluZzw+ID4gOiB0eXBlX2xpc3Q8IHBhaXJzLi4uLCBpbmRleGVkX3R5cGU8MCwgY29uc3Rfc3RyaW5nPGxhc3QuLi4+PiA+IHt9OwoKLy8gS2VpbiBUb2tlbiB2b3JoYW5kZW46CnRlbXBsYXRlPGNoYXIgdG9rZW4sCiAgICAgICAgIGNoYXIgY3VycmVudCwKICAgICAgICAgY2hhciAuLi4gbGFzdCwKICAgICAgICAgY2hhciAuLi4gdGFpbCwKICAgICAgICAgdHlwZW5hbWUgLi4uIHBhaXJzPgpzdHJ1Y3Qgc3BsaXRfb248IHRva2VuLCB0eXBlX2xpc3Q8cGFpcnMuLi4+LCBjb25zdF9zdHJpbmc8bGFzdC4uLj4sIGNvbnN0X3N0cmluZzxjdXJyZW50LCB0YWlsLi4uPiA+IDogc3BsaXRfb248dG9rZW4sIHR5cGVfbGlzdDxwYWlycy4uLj4sIGNvbnN0X3N0cmluZzxsYXN0Li4uLCBjdXJyZW50PiwgY29uc3Rfc3RyaW5nPHRhaWwuLi4+PiB7fTsKCnRlbXBsYXRlPGNoYXIgQz4Kc3RydWN0IGVuYWJsZV9pZl9kaWdpdAp7CglzdGF0aWNfYXNzZXJ0KCBDID49ICcwJyAmJiBDIDw9ICc5JywgIk5vdCBhIGRpZ2l0ISIgKTsKCglzdGF0aWMgY29uc3RleHByIGNoYXIgY2ggPSBDOwoJc3RhdGljIGNvbnN0ZXhwciBpbnQgbnVtYmVyID0gQyAtICcwJzsKfTsKCnRlbXBsYXRlPGNoYXIgdG9rZW4sCiAgICAgICAgIGNoYXIgZGlnaXQsCiAgICAgICAgIGNoYXIgLi4uIGxhc3QsCiAgICAgICAgIHR5cGVuYW1lIC4uLiBwYWlycz4Kc3RydWN0IHNwbGl0X29uPCB0b2tlbiwgdHlwZV9saXN0PHBhaXJzLi4uPiwgY29uc3Rfc3RyaW5nPGxhc3QuLi4+LCBjb25zdF9zdHJpbmc8dG9rZW4sIGRpZ2l0PiA+IDoKCXR5cGVfbGlzdDxwYWlycy4uLiwgaW5kZXhlZF90eXBlPGVuYWJsZV9pZl9kaWdpdDxkaWdpdD46Om51bWJlciwgY29uc3Rfc3RyaW5nPGxhc3QuLi4+PiwgaW5kZXhlZF90eXBlPDAsIGNvbnN0X3N0cmluZzw+Pj4ge307Cgp0ZW1wbGF0ZTxjaGFyIHRva2VuLAogICAgICAgICBjaGFyIGRpZ2l0LAogICAgICAgICBjaGFyIC4uLiBsYXN0LAogICAgICAgICBjaGFyIC4uLiB0YWlsLAogICAgICAgICB0eXBlbmFtZSAuLi4gcGFpcnM+CnN0cnVjdCBzcGxpdF9vbjwgdG9rZW4sIHR5cGVfbGlzdDxwYWlycy4uLj4sIGNvbnN0X3N0cmluZzxsYXN0Li4uPiwgY29uc3Rfc3RyaW5nPHRva2VuLCBkaWdpdCwgdGFpbC4uLj4gPiA6CglzcGxpdF9vbjx0b2tlbiwgdHlwZV9saXN0PCBwYWlycy4uLiwgaW5kZXhlZF90eXBlPGVuYWJsZV9pZl9kaWdpdDxkaWdpdD46Om51bWJlciwgY29uc3Rfc3RyaW5nPGxhc3QuLi4+PiA+LCBjb25zdF9zdHJpbmc8PiwgY29uc3Rfc3RyaW5nPHRhaWwuLi4+PiB7fTsKCnRlbXBsYXRlPGNoYXIgdG9rZW4sCiAgICAgICAgIGNoYXIgLi4uIGxhc3QsCiAgICAgICAgIGNoYXIgLi4uIHRhaWwsCiAgICAgICAgIHR5cGVuYW1lIC4uLiBwYWlycz4Kc3RydWN0IHNwbGl0X29uPCB0b2tlbiwgdHlwZV9saXN0PHBhaXJzLi4uPiwgY29uc3Rfc3RyaW5nPGxhc3QuLi4+LCBjb25zdF9zdHJpbmc8dG9rZW4sIHRva2VuLCB0YWlsLi4uPiA+IDogc3BsaXRfb248dG9rZW4sIHR5cGVfbGlzdDxwYWlycy4uLj4sIGNvbnN0X3N0cmluZzxsYXN0Li4uLCB0b2tlbiwgdG9rZW4+LCBjb25zdF9zdHJpbmc8dGFpbC4uLj4+IHt9OwoKdGVtcGxhdGU8Y2hhciBjLCB0eXBlbmFtZT4gc3RydWN0IHNwbGl0Owp0ZW1wbGF0ZTxjaGFyIGMsIGNoYXIuLi4gY2hhcnM+IHN0cnVjdCAgc3BsaXQ8YywgY29uc3Rfc3RyaW5nPGNoYXJzLi4uPj4gOiBzcGxpdF9vbjxjLCB0eXBlX2xpc3Q8PiwgY29uc3Rfc3RyaW5nPD4sIGNvbnN0X3N0cmluZzxjaGFycy4uLj4+IHt9OwoKLy8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCgp0ZW1wbGF0ZTxjaGFyLCB0eXBlbmFtZT4gc3RydWN0IHJ0cmltOwp0ZW1wbGF0ZTxjaGFyIHRva2VuLCBjaGFyIGZpcnN0LCBjaGFyIC4uLiBjaD4Kc3RydWN0IHJ0cmltPHRva2VuLCBjb25zdF9zdHJpbmc8Zmlyc3QsIGNoLi4uPj4gOiBjb25jYXRfc3RyaW5nczxjb25zdF9zdHJpbmc8Zmlyc3Q+LCB0eXBlbmFtZSBydHJpbTx0b2tlbiwgY29uc3Rfc3RyaW5nPGNoLi4uPj46OnR5cGU+IHt9Owp0ZW1wbGF0ZTxjaGFyIHRva2VuLCBjaGFyIC4uLiBjaD4Kc3RydWN0IHJ0cmltPHRva2VuLCBjb25zdF9zdHJpbmc8dG9rZW4sIGNoLi4uPj4gOiBjb25zdF9zdHJpbmc8PiB7fTsKdGVtcGxhdGU8Y2hhciB0b2tlbj4Kc3RydWN0IHJ0cmltPHRva2VuLCBjb25zdF9zdHJpbmc8Pj4gOiBjb25zdF9zdHJpbmc8PiB7fTsKCi8vLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKdGVtcGxhdGU8c3RkOjpzaXplX3QgSW5kZXgsIHR5cGVuYW1lIFQ+CnN0cnVjdCByYWNrCnsKCXN0YXRpYyBjb25zdGV4cHIgc3RkOjpzaXplX3QgaW5kZXggPSBJbmRleDsKCglUJiYgYXJnOwoKCXJhY2soIFQmJiBhICk6CgkJYXJnKCBzdGQ6OmZvcndhcmQ8VD4oYSkgKSB7fQp9OwoKLy8vIGluZGV4LWxpc3QgKHYuIGNhbXBlcikKCnRlbXBsYXRlPGludCAuLi4gYXJncz4Kc3RydWN0IGluZGV4X2xpc3QKewogICAgc3RhdGljIGNvbnN0ZXhwciBpbnQgYXJyW117YXJncy4uLn07CiAgICB1c2luZyB0eXBlID0gaW5kZXhfbGlzdDsKfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBVPiBzdHJ1Y3QgY29uY2F0X2xpc3Q7CnRlbXBsYXRlIDxpbnQuLi4gaSwgaW50Li4uIGo+CnN0cnVjdCBjb25jYXRfbGlzdDxpbmRleF9saXN0PGkuLi4+LGluZGV4X2xpc3Q8ai4uLj4+CjogaW5kZXhfbGlzdDxpLi4uLCAoc2l6ZW9mLi4uKGkpK2kpLi4uLCAoMipzaXplb2YuLi4oaSkraikuLi4+IHt9OwoKdGVtcGxhdGUgPGludCBOPiBzdHJ1Y3QgbWFrZV9pbmRleF9saXN0CjogY29uY2F0X2xpc3Q8dHlwZW5hbWUgbWFrZV9pbmRleF9saXN0PE4vMj46OnR5cGUsIHR5cGVuYW1lIG1ha2VfaW5kZXhfbGlzdDxOJTI+Ojp0eXBlPiB7fTsKdGVtcGxhdGUgPD4gc3RydWN0IG1ha2VfaW5kZXhfbGlzdDwxPiA6IGluZGV4X2xpc3Q8MD4ge307CnRlbXBsYXRlIDw+IHN0cnVjdCBtYWtlX2luZGV4X2xpc3Q8MD4gOiBpbmRleF9saXN0PD4ge307CgovLy8gPC9jYW1wZXI+IC8KCnRlbXBsYXRlPHR5cGVuYW1lLCB0eXBlbmFtZS4uLj4gc3RydWN0IEluZGljZXI7Cgp0ZW1wbGF0ZTxpbnQuLi4gaW5kaWNlcywgdHlwZW5hbWUuLi4gQXJncz4Kc3RydWN0IEluZGljZXI8aW5kZXhfbGlzdDxpbmRpY2VzLi4uPiwgQXJncy4uLj4gOiByYWNrPGluZGljZXMsIEFyZ3M+Li4uCnsKCUluZGljZXIoIEFyZ3MmJi4uLiBhcmdzICk6CgkJcmFjazxpbmRpY2VzLCBBcmdzPihzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykpLi4uIHt9Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBmb3JtYXRfc3RyaW5nLAogICAgICAgICB0eXBlbmFtZSBDaGFyVCwKCSAgICAgdHlwZW5hbWUgVHJhaXRzLAoJICAgICB0eXBlbmFtZSBpbmRleF9saXN0PgpzdHJ1Y3QgdHNfcHJpbnRmX2VudjsKCnRlbXBsYXRlPHR5cGVuYW1lIGZvcm1hdF9zdHJpbmcsCiAgICAgICAgIHR5cGVuYW1lIENoYXJULAoJICAgICB0eXBlbmFtZSBUcmFpdHMsCgkgICAgIGludC4uLiBpbmRpY2VzPgpzdHJ1Y3QgdHNfcHJpbnRmX2Vudjxmb3JtYXRfc3RyaW5nLCBDaGFyVCwgVHJhaXRzLCBpbmRleF9saXN0PGluZGljZXMuLi4+Pgp7CglzdGF0aWMgY2hhciBjb25zdGV4cHIgZm9ybWF0X3NpZ24gPSAnJSc7CgoJdXNpbmcgc3RyaW5nX2xpc3QgPSB0eXBlbmFtZSBzcGxpdDxmb3JtYXRfc2lnbiwgZm9ybWF0X3N0cmluZz46OnR5cGU7Cgpwcml2YXRlOgoKCXRlbXBsYXRlPHN0ZDo6c2l6ZV90IHR5cGVfbGlzdF9pbmRleD4KCXN0YXRpYyB2b2lkIHRzX3ByaW50Zl9pbXBsKCBzdGQ6OmJhc2ljX29zdHJlYW08Q2hhclQsIFRyYWl0cz4mIG9zICkKCXsKCQl1c2luZyB0b19wdXQgPSB0eXBlbmFtZSBzdHJpbmdfbGlzdDo6dGVtcGxhdGUgZ2V0PHR5cGVfbGlzdF9pbmRleD46OnR5cGU6OnR5cGU7CgoJCWlmKCBvcy5yZGJ1ZigpLT5zcHV0biggdG9fcHV0OjpudF9hcnIsIHRvX3B1dDo6bGVuZ3RoICkgIT0gdG9fcHV0OjpsZW5ndGggKQoJCQlvcy5zZXRzdGF0ZSggc3RkOjppb3NfYmFzZTo6YmFkYml0ICk7Cgl9CgoJdGVtcGxhdGU8c3RkOjpzaXplX3QgdHlwZV9saXN0X2luZGV4LAoJCQkgdHlwZW5hbWUgRmlyc3RBcmcsCgkJCSB0eXBlbmFtZSAuLi5BcmdzPgoJc3RhdGljIHZvaWQgdHNfcHJpbnRmX2ltcGwoIHN0ZDo6YmFzaWNfb3N0cmVhbTxDaGFyVCwgVHJhaXRzPiYgb3MsCgkJCQkJCQkJRmlyc3RBcmcmJiBmaXJzdCwKCQkJCQkJCQlBcmdzJiYuLi4gdGFpbCkKCXsKCQl0c19wcmludGZfaW1wbDx0eXBlX2xpc3RfaW5kZXg+KCBvcyApOwoKCQlpZiggb3MgPDwgc3RkOjpmb3J3YXJkPEZpcnN0QXJnPihmaXJzdCkgKQoJCQl0c19wcmludGZfaW1wbDx0eXBlX2xpc3RfaW5kZXggKyAxPiggb3MsIHN0ZDo6Zm9yd2FyZDxBcmdzPih0YWlsKS4uLiApOwoJfQoKcHVibGljOgoKCXRlbXBsYXRlPHR5cGVuYW1lIC4uLiBBcmdzPgoJc3RhdGljIHN0ZDo6YmFzaWNfb3N0cmVhbTxDaGFyVCwgVHJhaXRzPiYgdHNfcHJpbnRmKCBzdGQ6OmJhc2ljX29zdHJlYW08Q2hhclQsIFRyYWl0cz4mIG9zLCBBcmdzJiYuLi4gYXJncyApCgl7CgkJc3RhdGljX2Fzc2VydCggc2l6ZW9mLi4uKEFyZ3MpICsgMSA9PSBzdHJpbmdfbGlzdDo6bGVuZ3RoLCAiSW52YWxpZCBmb3JtYXQgc3RyaW5nISIgKTsKCgkJdHlwZW5hbWUgc3RkOjpiYXNpY19vc3RyZWFtPENoYXJULCBUcmFpdHM+OjpzZW50cnkgb2t7b3N9OwoKCQlpZiggb2sgKSB0cnkKCQl7CgkJCUluZGljZXI8dHlwZW5hbWUgbWFrZV9pbmRleF9saXN0PHNpemVvZi4uLihBcmdzKT46OnR5cGUsIEFyZ3MuLi4+IGluZGljZXIoIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLiApOwoKCQkJI2RlZmluZSBpbmRleCBzdHJpbmdfbGlzdDo6dGVtcGxhdGUgZ2V0PGluZGljZXM+Ojp0eXBlOjppbmRleAoJCQl0c19wcmludGZfaW1wbDwwPiggb3MsIGluZGljZXIucmFjazwgaW5kZXgsCgkJCQkJCQkJCQkJCSB0eXBlbmFtZSBhdDxpbmRleCwgQXJncy4uLj46OnR5cGUgPjo6YXJnLi4uICk7CgkJCSN1bmRlZiBpbmRleAoJCX0KCQljYXRjaCggc3RkOjppb3M6OmZhaWx1cmUgY29uc3QmICkKCQl7IHRocm93OyB9CgkJY2F0Y2goLi4uKQoJCXsKCQkJb3MuY2xlYXIoIG9zLnJkc3RhdGUoKSB8IHN0ZDo6aW9zX2Jhc2U6OmJhZGJpdCApOwoJCQlpZiggb3MuZXhjZXB0aW9ucygpICYgc3RkOjppb3NfYmFzZTo6YmFkYml0ICkKCQkJCXRocm93OwoJCX0KCgkJcmV0dXJuIG9zOwoJfQp9OwoKI2RlZmluZSBTUExJVF8xKHN0cixwb3MpICBzdHIgWyBwb3MgPCBzaXplb2Ygc3RyID8gcG9zIDogc2l6ZW9mKHN0cikgLSAxIF0KI2RlZmluZSBTUExJVF8yKHN0cix4KSAgU1BMSVRfMShzdHIseCksIFNQTElUXzEoc3RyLHggKyAxKQojZGVmaW5lIFNQTElUXzQoc3RyLHgpICBTUExJVF8yKHN0cix4KSwgU1BMSVRfMihzdHIseCArIDIpCiNkZWZpbmUgU1BMSVRfOChzdHIseCkgIFNQTElUXzQoc3RyLHgpLCBTUExJVF80KHN0cix4ICsgNCkKI2RlZmluZSBTUExJVF8xNihzdHIseCkgU1BMSVRfOChzdHIseCksIFNQTElUXzgoc3RyLHggKyA4KQojZGVmaW5lIFNQTElUXzMyKHN0cix4KSBTUExJVF8xNihzdHIseCksIFNQTElUXzE2KHN0cix4ICsgMTYpCiNkZWZpbmUgU1BMSVRfNjQoc3RyLHgpIFNQTElUXzMyKHN0cix4KSwgU1BMSVRfMzIoc3RyLHggKyAzMikKI2RlZmluZSBTUExJVF8xMjgoc3RyLHgpIFNQTElUXzY0KHN0cix4KSwgU1BMSVRfNjQoc3RyLHggKyA2NCkKCiNkZWZpbmUgdHNfcHJpbnRmKG9zLCBmb3JtYXQsIC4uLikgdHNfcHJpbnRmX2Vudjx0eXBlbmFtZSBydHJpbTwnXDAnLCBjb25zdF9zdHJpbmc8U1BMSVRfMTI4KGZvcm1hdCwgMCk+Pjo6dHlwZSwgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjbHR5cGUob3MpOjpjaGFyX3R5cGUsIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY2x0eXBlKG9zKTo6dHJhaXRzX3R5cGUsIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ha2VfaW5kZXhfbGlzdDxkZWNsdHlwZShhcmdfdHlwZV9saXN0KF9fVkFfQVJHU19fKSk6Omxlbmd0aD46OnR5cGU+Ojp0c19wcmludGYoIG9zLCBfX1ZBX0FSR1NfXyApCgoKaW50IG1haW4oKQp7Cgl0c19wcmludGYoc3RkOjpjb3V0LCAiJTEgKyAlMiA9ICUwIiwgMTAsIDYsIDQpOwp9Cg==