#include <iostream>
#include <string>
#include <type_traits>
namespace mu
{
namespace index_list
{
template<size_t... Indices>
struct index_list
{
template<size_t N>
using append = index_list<Indices..., N>;
static constexpr size_t size()
{
return sizeof...(Indices);
}
};
template<size_t Size>
struct make_index_list
{
typedef typename make_index_list<Size-1>::type::template append<Size-1> type;
};
template<>
struct make_index_list<0u>
{
typedef index_list<> type;
};
template<typename... Ts>
using to_index_list = typename make_index_list<sizeof...(Ts)>::type;
}
namespace il = index_list;
}
struct empty_result
{
static const std::string value;
};
const std::string empty_result::value;
template<size_t Width, size_t Height>
struct result_size
{
static constexpr size_t width = Width;
static constexpr size_t height = Height;
static constexpr size_t square = Width * Height;
};
template<char Foreground, char Background>
struct render_rule
{
static constexpr char background = Background;
static constexpr char foreground = Foreground;
};
template<size_t Idx, unsigned char Block>
struct get_element
{
static constexpr size_t value = ((Block & ((Idx < 4) ? 0xF0 : 0x0F)) >> (7 - Idx)) & 1;
};
template<size_t Id, size_t Idx, class Size, class Rule, size_t Element>
struct process_one
{
static constexpr bool in_render_zone = Idx < Size::square;
static constexpr bool new_line = Idx > 0 && (Idx % Size::width == 0);
static const std::string value;
};
template<size_t Id, size_t Idx, class Size, class Rule, size_t Element>
const std::string process_one<Id, Idx, Size, Rule, Element>::value = (in_render_zone) ? (((new_line) ? (std::string() + '\n') : std::string()) +
((Element != 0) ? Rule::foreground : Rule::background)) : std::string();
/*
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Block>
struct process_block
{
static const std::string value;
};
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Block>
const std::string process_block<Id, Idx, Size, Rule, Block>::value =
process_one<Id, Idx, Size, Rule, get_element<0, Block>::value>::value +
process_one<Id, Idx + 1, Size, Rule, get_element<1, Block>::value>::value +
process_one<Id, Idx + 2, Size, Rule, get_element<2, Block>::value>::value +
process_one<Id, Idx + 3, Size, Rule, get_element<3, Block>::value>::value +
process_one<Id, Idx + 4, Size, Rule, get_element<4, Block>::value>::value +
process_one<Id, Idx + 5, Size, Rule, get_element<5, Block>::value>::value +
process_one<Id, Idx + 6, Size, Rule, get_element<6, Block>::value>::value +
process_one<Id, Idx + 7, Size, Rule, get_element<7, Block>::value>::value;
*/
template<template <size_t> class T, size_t... Indices> struct summa;
template<template <size_t> class T, size_t Index, size_t... Indices>
struct summa<T, Index, Indices...>
{
static const decltype(T<Index>::value) value;
};
template<template <size_t> class T, size_t Index, size_t... Indices>
const decltype(T<Index>::value) summa<T, Index, Indices...>::value = T<Index>::value + summa<T, Indices...>::value;
template<template <size_t> class T, size_t Index>
struct summa<T, Index>
{
static const decltype(T<Index>::value) value;
};
template<template <size_t> class T, size_t Index>
const decltype(T<Index>::value) summa<T, Index>::value = T<Index>::value;
/*
template<Signature>
struct summa
{
static switch (template Signature)
{
case template <size_t> class T, size_t Index, size_t... Indices:
static constexpr auto value = T<Index>::value + summa<T, Indices...>::value;
break;
case template <size_t> class T, size_t Index:
static constexpr auto value = T<Index>::value;
break;
default:;
}
};
template<template <size_t> class T, size_t Index, size_t... Indices>
struct summa<T, Index, Indices...>
{
static if (sizeof...(Indices) > 0)
static constexpr auto value = T<Index>::value + summa<T, Indices...>::value;
else
static constexpr auto value = T<Index>::value;
};
*/
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Block>
struct process_block_
{
template<size_t N>
using process_one_ = process_one<Id, Idx + N, Size, Rule, get_element<N, Block>::value>;
template<size_t... Indices>
static constexpr auto run(const mu::il::index_list<Indices...>&) -> decltype(summa<process_one_, Indices...>::value)
{
return summa<process_one_, Indices...>::value;
}
static const std::string value;
};
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Block>
const std::string process_block_<Id, Idx, Size, Rule, Block>::value = process_block_<Id, Idx, Size, Rule, Block>::template run(mu::il::make_index_list<8>::type());
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char... Data> struct render;
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char First, unsigned char... Data>
struct render<Id, Idx, Size, Rule, First, Data...>
{
static const std::string value;
};
/*
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char First, unsigned char... Data>
const std::string render<Id, Idx, Size, Rule, First, Data...>::value = process_block<Id, Idx, Size, Rule, First>::value +
render<Id, Idx + 8, Size, Rule, Data...>::value;
*/
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char First, unsigned char... Data>
const std::string render<Id, Idx, Size, Rule, First, Data...>::value = process_block_<Id, Idx, Size, Rule, First>::value +
render<Id, Idx + 8, Size, Rule, Data...>::value;
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Last>
struct render<Id, Idx, Size, Rule, Last>
{
static const std::string value;
};
/*
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Last>
const std::string render<Id, Idx, Size, Rule, Last>::value = process_block<Id, Idx, Size, Rule, Last>::value;
*/
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Last>
const std::string render<Id, Idx, Size, Rule, Last>::value = process_block_<Id, Idx, Size, Rule, Last>::value;
template<size_t Id, size_t Width, class Rule, unsigned char... Data>
struct silly_img
{
static constexpr size_t width = Width;
static constexpr size_t height = (Width > 0) ? (sizeof...(Data) * 8 / Width) : 0;
static constexpr bool is_valid = width > 0 && height > 0;
static const std::string data;
static void show_me()
{
std::cout << "(" << Id << ") Size: " << width << " x " << height << "\n\n";
std::cout << data;
}
};
template<size_t Id, size_t Width, class Rule, unsigned char... Data>
const std::string silly_img<Id, Width, Rule, Data...>::data = std::string() +
std::conditional< is_valid, render<Id, 0, result_size<width, height>, Rule, Data...>, empty_result>::type::value;
int main()
{
silly_img<0, 11, render_rule<'$', ' '>, 0x31, 0x8F, 0x7B, 0xFF, 0xFF, 0xF3, 0xF8, 0x1C, 0x01, 0x00>::show_me();
std::cout << "\n\n";
silly_img<1, 15, render_rule<'#', '.'>, 0x31, 0x84, 0xF7, 0x9F, 0xFF, 0x97, 0xFF, 0x03, 0xF8, 0x81, 0xC3, 0x81, 0x02, 0x00>::show_me();
std::cout << "\n\n";
silly_img<2, 15, render_rule<'*', ' '>, 0x3F, 0xE4, 0xFF, 0x9F, 0xC0, 0x17, 0x80, 0x0F, 0x00, 0x8F, 0xF3, 0x8F, 0xF2, 0x00>::show_me();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgpuYW1lc3BhY2UgbXUKewogICAgbmFtZXNwYWNlIGluZGV4X2xpc3QKICAgIHsKICAgICAgICB0ZW1wbGF0ZTxzaXplX3QuLi4gSW5kaWNlcz4KICAgICAgICBzdHJ1Y3QgaW5kZXhfbGlzdAogICAgICAgIHsKICAgICAgICAgICAgdGVtcGxhdGU8c2l6ZV90IE4+CiAgICAgICAgICAgIHVzaW5nIGFwcGVuZCA9IGluZGV4X2xpc3Q8SW5kaWNlcy4uLiwgTj47CiAgICAgICAgICAgIAogICAgICAgICAgICBzdGF0aWMgY29uc3RleHByIHNpemVfdCBzaXplKCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmV0dXJuIHNpemVvZi4uLihJbmRpY2VzKTsKICAgICAgICAgICAgfQogICAgICAgIH07CgogICAgICAgIHRlbXBsYXRlPHNpemVfdCBTaXplPgogICAgICAgIHN0cnVjdCBtYWtlX2luZGV4X2xpc3QKICAgICAgICB7CiAgICAgICAgICAgIHR5cGVkZWYgdHlwZW5hbWUgbWFrZV9pbmRleF9saXN0PFNpemUtMT46OnR5cGU6OnRlbXBsYXRlIGFwcGVuZDxTaXplLTE+IHR5cGU7CiAgICAgICAgfTsKCiAgICAgICAgdGVtcGxhdGU8PgogICAgICAgIHN0cnVjdCBtYWtlX2luZGV4X2xpc3Q8MHU+CiAgICAgICAgewogICAgICAgICAgICB0eXBlZGVmIGluZGV4X2xpc3Q8PiB0eXBlOwogICAgICAgIH07CgogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lLi4uIFRzPgogICAgICAgIHVzaW5nIHRvX2luZGV4X2xpc3QgPSB0eXBlbmFtZSBtYWtlX2luZGV4X2xpc3Q8c2l6ZW9mLi4uKFRzKT46OnR5cGU7CiAgICB9CiAgICAKICAgIG5hbWVzcGFjZSBpbCA9IGluZGV4X2xpc3Q7Cn0KCnN0cnVjdCBlbXB0eV9yZXN1bHQKewogICAgc3RhdGljIGNvbnN0IHN0ZDo6c3RyaW5nIHZhbHVlOwp9OwoKY29uc3Qgc3RkOjpzdHJpbmcgZW1wdHlfcmVzdWx0Ojp2YWx1ZTsKCgp0ZW1wbGF0ZTxzaXplX3QgV2lkdGgsIHNpemVfdCBIZWlnaHQ+CnN0cnVjdCByZXN1bHRfc2l6ZQp7CiAgICBzdGF0aWMgY29uc3RleHByIHNpemVfdCB3aWR0aCA9IFdpZHRoOwogICAgc3RhdGljIGNvbnN0ZXhwciBzaXplX3QgaGVpZ2h0ID0gSGVpZ2h0OwogICAgc3RhdGljIGNvbnN0ZXhwciBzaXplX3Qgc3F1YXJlID0gV2lkdGggKiBIZWlnaHQ7Cn07Cgp0ZW1wbGF0ZTxjaGFyIEZvcmVncm91bmQsIGNoYXIgQmFja2dyb3VuZD4Kc3RydWN0IHJlbmRlcl9ydWxlCnsKICAgIHN0YXRpYyBjb25zdGV4cHIgY2hhciBiYWNrZ3JvdW5kID0gQmFja2dyb3VuZDsKICAgIHN0YXRpYyBjb25zdGV4cHIgY2hhciBmb3JlZ3JvdW5kID0gRm9yZWdyb3VuZDsKfTsKCnRlbXBsYXRlPHNpemVfdCBJZHgsIHVuc2lnbmVkIGNoYXIgQmxvY2s+CnN0cnVjdCBnZXRfZWxlbWVudAp7CiAgICBzdGF0aWMgY29uc3RleHByIHNpemVfdCB2YWx1ZSA9ICgoQmxvY2sgJiAoKElkeCA8IDQpID8gMHhGMCA6IDB4MEYpKSA+PiAoNyAtIElkeCkpICYgMTsKfTsKCnRlbXBsYXRlPHNpemVfdCBJZCwgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgc2l6ZV90IEVsZW1lbnQ+CnN0cnVjdCBwcm9jZXNzX29uZQp7CiAgICBzdGF0aWMgY29uc3RleHByIGJvb2wgaW5fcmVuZGVyX3pvbmUgPSBJZHggPCBTaXplOjpzcXVhcmU7CiAgICBzdGF0aWMgY29uc3RleHByIGJvb2wgbmV3X2xpbmUgPSBJZHggPiAwICYmIChJZHggJSBTaXplOjp3aWR0aCA9PSAwKTsKICAgIHN0YXRpYyBjb25zdCBzdGQ6OnN0cmluZyB2YWx1ZTsKfTsKCnRlbXBsYXRlPHNpemVfdCBJZCwgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgc2l6ZV90IEVsZW1lbnQ+CmNvbnN0IHN0ZDo6c3RyaW5nIHByb2Nlc3Nfb25lPElkLCBJZHgsIFNpemUsIFJ1bGUsIEVsZW1lbnQ+Ojp2YWx1ZSA9IChpbl9yZW5kZXJfem9uZSkgPyAoKChuZXdfbGluZSkgPyAoc3RkOjpzdHJpbmcoKSArICdcbicpIDogc3RkOjpzdHJpbmcoKSkgKwogICAgKChFbGVtZW50ICE9IDApID8gUnVsZTo6Zm9yZWdyb3VuZCA6IFJ1bGU6OmJhY2tncm91bmQpKSA6IHN0ZDo6c3RyaW5nKCk7CgogICAgCi8qCnRlbXBsYXRlPHNpemVfdCBJZCwgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhciBCbG9jaz4Kc3RydWN0IHByb2Nlc3NfYmxvY2sKewogICAgc3RhdGljIGNvbnN0IHN0ZDo6c3RyaW5nIHZhbHVlOwp9OwoKdGVtcGxhdGU8c2l6ZV90IElkLCBzaXplX3QgSWR4LCBjbGFzcyBTaXplLCBjbGFzcyBSdWxlLCB1bnNpZ25lZCBjaGFyIEJsb2NrPgpjb25zdCBzdGQ6OnN0cmluZyBwcm9jZXNzX2Jsb2NrPElkLCBJZHgsIFNpemUsIFJ1bGUsIEJsb2NrPjo6dmFsdWUgPQogICAgcHJvY2Vzc19vbmU8SWQsIElkeCwgU2l6ZSwgUnVsZSwgZ2V0X2VsZW1lbnQ8MCwgQmxvY2s+Ojp2YWx1ZT46OnZhbHVlICsKICAgIHByb2Nlc3Nfb25lPElkLCBJZHggKyAxLCBTaXplLCBSdWxlLCBnZXRfZWxlbWVudDwxLCBCbG9jaz46OnZhbHVlPjo6dmFsdWUgKwogICAgcHJvY2Vzc19vbmU8SWQsIElkeCArIDIsIFNpemUsIFJ1bGUsIGdldF9lbGVtZW50PDIsIEJsb2NrPjo6dmFsdWU+Ojp2YWx1ZSArCiAgICBwcm9jZXNzX29uZTxJZCwgSWR4ICsgMywgU2l6ZSwgUnVsZSwgZ2V0X2VsZW1lbnQ8MywgQmxvY2s+Ojp2YWx1ZT46OnZhbHVlICsKICAgIHByb2Nlc3Nfb25lPElkLCBJZHggKyA0LCBTaXplLCBSdWxlLCBnZXRfZWxlbWVudDw0LCBCbG9jaz46OnZhbHVlPjo6dmFsdWUgKwogICAgcHJvY2Vzc19vbmU8SWQsIElkeCArIDUsIFNpemUsIFJ1bGUsIGdldF9lbGVtZW50PDUsIEJsb2NrPjo6dmFsdWU+Ojp2YWx1ZSArCiAgICBwcm9jZXNzX29uZTxJZCwgSWR4ICsgNiwgU2l6ZSwgUnVsZSwgZ2V0X2VsZW1lbnQ8NiwgQmxvY2s+Ojp2YWx1ZT46OnZhbHVlICsKICAgIHByb2Nlc3Nfb25lPElkLCBJZHggKyA3LCBTaXplLCBSdWxlLCBnZXRfZWxlbWVudDw3LCBCbG9jaz46OnZhbHVlPjo6dmFsdWU7CiovCgp0ZW1wbGF0ZTx0ZW1wbGF0ZSA8c2l6ZV90PiBjbGFzcyBULCBzaXplX3QuLi4gSW5kaWNlcz4gc3RydWN0IHN1bW1hOwogICAgCnRlbXBsYXRlPHRlbXBsYXRlIDxzaXplX3Q+IGNsYXNzIFQsIHNpemVfdCBJbmRleCwgc2l6ZV90Li4uIEluZGljZXM+CnN0cnVjdCBzdW1tYTxULCBJbmRleCwgSW5kaWNlcy4uLj4KewogICAgc3RhdGljIGNvbnN0IGRlY2x0eXBlKFQ8SW5kZXg+Ojp2YWx1ZSkgdmFsdWU7Cn07Cgp0ZW1wbGF0ZTx0ZW1wbGF0ZSA8c2l6ZV90PiBjbGFzcyBULCBzaXplX3QgSW5kZXgsIHNpemVfdC4uLiBJbmRpY2VzPgpjb25zdCBkZWNsdHlwZShUPEluZGV4Pjo6dmFsdWUpIHN1bW1hPFQsIEluZGV4LCBJbmRpY2VzLi4uPjo6dmFsdWUgPSBUPEluZGV4Pjo6dmFsdWUgKyBzdW1tYTxULCBJbmRpY2VzLi4uPjo6dmFsdWU7Cgp0ZW1wbGF0ZTx0ZW1wbGF0ZSA8c2l6ZV90PiBjbGFzcyBULCBzaXplX3QgSW5kZXg+CnN0cnVjdCBzdW1tYTxULCBJbmRleD4KewogICAgc3RhdGljIGNvbnN0IGRlY2x0eXBlKFQ8SW5kZXg+Ojp2YWx1ZSkgdmFsdWU7Cn07Cgp0ZW1wbGF0ZTx0ZW1wbGF0ZSA8c2l6ZV90PiBjbGFzcyBULCBzaXplX3QgSW5kZXg+CmNvbnN0IGRlY2x0eXBlKFQ8SW5kZXg+Ojp2YWx1ZSkgc3VtbWE8VCwgSW5kZXg+Ojp2YWx1ZSA9IFQ8SW5kZXg+Ojp2YWx1ZTsKCi8qCgp0ZW1wbGF0ZTxTaWduYXR1cmU+CnN0cnVjdCBzdW1tYQp7CiAgICBzdGF0aWMgc3dpdGNoICh0ZW1wbGF0ZSBTaWduYXR1cmUpCiAgICB7CiAgICBjYXNlIHRlbXBsYXRlIDxzaXplX3Q+IGNsYXNzIFQsIHNpemVfdCBJbmRleCwgc2l6ZV90Li4uIEluZGljZXM6CiAgICAgICAgc3RhdGljIGNvbnN0ZXhwciBhdXRvIHZhbHVlID0gVDxJbmRleD46OnZhbHVlICsgc3VtbWE8VCwgSW5kaWNlcy4uLj46OnZhbHVlOwogICAgICAgIGJyZWFrOwogICAgY2FzZSB0ZW1wbGF0ZSA8c2l6ZV90PiBjbGFzcyBULCBzaXplX3QgSW5kZXg6CiAgICAgICAgc3RhdGljIGNvbnN0ZXhwciBhdXRvIHZhbHVlID0gVDxJbmRleD46OnZhbHVlOwogICAgICAgIGJyZWFrOwogICAgZGVmYXVsdDo7CiAgICB9Cn07Cgp0ZW1wbGF0ZTx0ZW1wbGF0ZSA8c2l6ZV90PiBjbGFzcyBULCBzaXplX3QgSW5kZXgsIHNpemVfdC4uLiBJbmRpY2VzPgpzdHJ1Y3Qgc3VtbWE8VCwgSW5kZXgsIEluZGljZXMuLi4+CnsKICAgIHN0YXRpYyBpZiAoc2l6ZW9mLi4uKEluZGljZXMpID4gMCkKICAgICAgICBzdGF0aWMgY29uc3RleHByIGF1dG8gdmFsdWUgPSBUPEluZGV4Pjo6dmFsdWUgKyBzdW1tYTxULCBJbmRpY2VzLi4uPjo6dmFsdWU7CiAgICBlbHNlCiAgICAgICAgc3RhdGljIGNvbnN0ZXhwciBhdXRvIHZhbHVlID0gVDxJbmRleD46OnZhbHVlOwp9OwoKKi8KdGVtcGxhdGU8c2l6ZV90IElkLCBzaXplX3QgSWR4LCBjbGFzcyBTaXplLCBjbGFzcyBSdWxlLCB1bnNpZ25lZCBjaGFyIEJsb2NrPgpzdHJ1Y3QgcHJvY2Vzc19ibG9ja18KewogICAgdGVtcGxhdGU8c2l6ZV90IE4+CiAgICB1c2luZyBwcm9jZXNzX29uZV8gPSBwcm9jZXNzX29uZTxJZCwgSWR4ICsgTiwgU2l6ZSwgUnVsZSwgZ2V0X2VsZW1lbnQ8TiwgQmxvY2s+Ojp2YWx1ZT47CgogICAgdGVtcGxhdGU8c2l6ZV90Li4uIEluZGljZXM+CiAgICBzdGF0aWMgY29uc3RleHByIGF1dG8gcnVuKGNvbnN0IG11OjppbDo6aW5kZXhfbGlzdDxJbmRpY2VzLi4uPiYpIC0+IGRlY2x0eXBlKHN1bW1hPHByb2Nlc3Nfb25lXywgSW5kaWNlcy4uLj46OnZhbHVlKQogICAgewogICAgICAgIHJldHVybiBzdW1tYTxwcm9jZXNzX29uZV8sIEluZGljZXMuLi4+Ojp2YWx1ZTsKICAgIH0KICAgIAogICAgc3RhdGljIGNvbnN0IHN0ZDo6c3RyaW5nIHZhbHVlOwp9OyAgICAKCnRlbXBsYXRlPHNpemVfdCBJZCwgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhciBCbG9jaz4KY29uc3Qgc3RkOjpzdHJpbmcgcHJvY2Vzc19ibG9ja188SWQsIElkeCwgU2l6ZSwgUnVsZSwgQmxvY2s+Ojp2YWx1ZSA9ICBwcm9jZXNzX2Jsb2NrXzxJZCwgSWR4LCBTaXplLCBSdWxlLCBCbG9jaz46OnRlbXBsYXRlIHJ1bihtdTo6aWw6Om1ha2VfaW5kZXhfbGlzdDw4Pjo6dHlwZSgpKTsKICAgIAp0ZW1wbGF0ZTxzaXplX3QgSWQsIHNpemVfdCBJZHgsIGNsYXNzIFNpemUsIGNsYXNzIFJ1bGUsIHVuc2lnbmVkIGNoYXIuLi4gRGF0YT4gc3RydWN0IHJlbmRlcjsKCnRlbXBsYXRlPHNpemVfdCBJZCwgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhciBGaXJzdCwgdW5zaWduZWQgY2hhci4uLiBEYXRhPgpzdHJ1Y3QgcmVuZGVyPElkLCBJZHgsIFNpemUsIFJ1bGUsIEZpcnN0LCBEYXRhLi4uPgp7CiAgICBzdGF0aWMgY29uc3Qgc3RkOjpzdHJpbmcgdmFsdWU7Cn07CgovKgp0ZW1wbGF0ZTxzaXplX3QgSWQsIHNpemVfdCBJZHgsIGNsYXNzIFNpemUsIGNsYXNzIFJ1bGUsIHVuc2lnbmVkIGNoYXIgRmlyc3QsIHVuc2lnbmVkIGNoYXIuLi4gRGF0YT4KY29uc3Qgc3RkOjpzdHJpbmcgcmVuZGVyPElkLCBJZHgsIFNpemUsIFJ1bGUsIEZpcnN0LCBEYXRhLi4uPjo6dmFsdWUgPSBwcm9jZXNzX2Jsb2NrPElkLCBJZHgsIFNpemUsIFJ1bGUsIEZpcnN0Pjo6dmFsdWUgKwogICAgcmVuZGVyPElkLCBJZHggKyA4LCBTaXplLCBSdWxlLCBEYXRhLi4uPjo6dmFsdWU7CiovCgp0ZW1wbGF0ZTxzaXplX3QgSWQsIHNpemVfdCBJZHgsIGNsYXNzIFNpemUsIGNsYXNzIFJ1bGUsIHVuc2lnbmVkIGNoYXIgRmlyc3QsIHVuc2lnbmVkIGNoYXIuLi4gRGF0YT4KY29uc3Qgc3RkOjpzdHJpbmcgcmVuZGVyPElkLCBJZHgsIFNpemUsIFJ1bGUsIEZpcnN0LCBEYXRhLi4uPjo6dmFsdWUgPSBwcm9jZXNzX2Jsb2NrXzxJZCwgSWR4LCBTaXplLCBSdWxlLCBGaXJzdD46OnZhbHVlICsKICAgIHJlbmRlcjxJZCwgSWR4ICsgOCwgU2l6ZSwgUnVsZSwgRGF0YS4uLj46OnZhbHVlOwoKdGVtcGxhdGU8c2l6ZV90IElkLCAgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhciBMYXN0PgpzdHJ1Y3QgcmVuZGVyPElkLCBJZHgsIFNpemUsIFJ1bGUsIExhc3Q+CnsKICAgIHN0YXRpYyBjb25zdCBzdGQ6OnN0cmluZyB2YWx1ZTsKfTsKCi8qCnRlbXBsYXRlPHNpemVfdCBJZCwgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhciBMYXN0Pgpjb25zdCBzdGQ6OnN0cmluZyByZW5kZXI8SWQsIElkeCwgU2l6ZSwgUnVsZSwgTGFzdD46OnZhbHVlID0gcHJvY2Vzc19ibG9jazxJZCwgSWR4LCBTaXplLCBSdWxlLCBMYXN0Pjo6dmFsdWU7CiovCgp0ZW1wbGF0ZTxzaXplX3QgSWQsIHNpemVfdCBJZHgsIGNsYXNzIFNpemUsIGNsYXNzIFJ1bGUsIHVuc2lnbmVkIGNoYXIgTGFzdD4KY29uc3Qgc3RkOjpzdHJpbmcgcmVuZGVyPElkLCBJZHgsIFNpemUsIFJ1bGUsIExhc3Q+Ojp2YWx1ZSA9IHByb2Nlc3NfYmxvY2tfPElkLCBJZHgsIFNpemUsIFJ1bGUsIExhc3Q+Ojp2YWx1ZTsKCgp0ZW1wbGF0ZTxzaXplX3QgSWQsIHNpemVfdCBXaWR0aCwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhci4uLiBEYXRhPgpzdHJ1Y3Qgc2lsbHlfaW1nCnsKICAgIHN0YXRpYyBjb25zdGV4cHIgc2l6ZV90IHdpZHRoID0gV2lkdGg7CiAgICBzdGF0aWMgY29uc3RleHByIHNpemVfdCBoZWlnaHQgPSAoV2lkdGggPiAwKSA/IChzaXplb2YuLi4oRGF0YSkgKiA4IC8gV2lkdGgpIDogMDsKICAgIHN0YXRpYyBjb25zdGV4cHIgYm9vbCBpc192YWxpZCA9IHdpZHRoID4gMCAmJiBoZWlnaHQgPiAwOwogICAgc3RhdGljIGNvbnN0IHN0ZDo6c3RyaW5nIGRhdGE7CgogICAgc3RhdGljIHZvaWQgc2hvd19tZSgpCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8ICIoIiA8PCBJZCA8PCAiKSBTaXplOiAiIDw8IHdpZHRoIDw8ICIgeCAiIDw8IGhlaWdodCA8PCAiXG5cbiI7CiAgICAgICAgc3RkOjpjb3V0IDw8IGRhdGE7CiAgICB9Cn07Cgp0ZW1wbGF0ZTxzaXplX3QgSWQsIHNpemVfdCBXaWR0aCwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhci4uLiBEYXRhPgpjb25zdCBzdGQ6OnN0cmluZyBzaWxseV9pbWc8SWQsIFdpZHRoLCBSdWxlLCBEYXRhLi4uPjo6ZGF0YSA9IHN0ZDo6c3RyaW5nKCkgKwogICAgc3RkOjpjb25kaXRpb25hbDwgaXNfdmFsaWQsIHJlbmRlcjxJZCwgMCwgcmVzdWx0X3NpemU8d2lkdGgsIGhlaWdodD4sIFJ1bGUsIERhdGEuLi4+LCBlbXB0eV9yZXN1bHQ+Ojp0eXBlOjp2YWx1ZTsKCmludCBtYWluKCkKewogICAgc2lsbHlfaW1nPDAsIDExLCByZW5kZXJfcnVsZTwnJCcsICcgJz4sIDB4MzEsIDB4OEYsIDB4N0IsIDB4RkYsIDB4RkYsIDB4RjMsIDB4RjgsIDB4MUMsIDB4MDEsIDB4MDA+OjpzaG93X21lKCk7CiAgICBzdGQ6OmNvdXQgPDwgIlxuXG4iOwogICAgc2lsbHlfaW1nPDEsIDE1LCByZW5kZXJfcnVsZTwnIycsICcuJz4sIDB4MzEsIDB4ODQsIDB4RjcsIDB4OUYsIDB4RkYsIDB4OTcsIDB4RkYsIDB4MDMsIDB4RjgsIDB4ODEsIDB4QzMsIDB4ODEsIDB4MDIsIDB4MDA+OjpzaG93X21lKCk7CiAgICBzdGQ6OmNvdXQgPDwgIlxuXG4iOwogICAgc2lsbHlfaW1nPDIsIDE1LCByZW5kZXJfcnVsZTwnKicsICcgJz4sIDB4M0YsIDB4RTQsIDB4RkYsIDB4OUYsIDB4QzAsIDB4MTcsIDB4ODAsIDB4MEYsIDB4MDAsIDB4OEYsIDB4RjMsIDB4OEYsIDB4RjIsIDB4MDA+OjpzaG93X21lKCk7Cn0K