#ifndef pretty_print_0x57547_sa4884X_0_1_h_guard_
#define pretty_print_0x57547_sa4884X_0_1_h_guard_
#include <string>
#include <iostream>
#include <type_traits>
#include <iterator>
#include <utility>
#define PRETTY_DEFAULT_DECORATION(TYPE, PREFIX, DELIM, POSTFIX, ...) \
namespace pretty { template< __VA_ARGS__ >\
struct defaulted< TYPE > {\
static decor< TYPE > decoration(){\
return { PREFIX, DELIM, POSTFIX };\
} /*decoration*/ }; /*defaulted*/} /*pretty*/
#define PRETTY_DEFAULT_WDECORATION(TYPE, PREFIX, DELIM, POSTFIX, ...) \
namespace pretty { template< __VA_ARGS__ >\
struct defaulted< TYPE, wchar_t, std::char_traits<wchar_t> > {\
static decor< TYPE, wchar_t, std::char_traits<wchar_t> > decoration(){\
return { PREFIX, DELIM, POSTFIX };\
} /*decoration*/ }; /*defaulted*/} /*pretty*/
namespace pretty
{
namespace detail
{
// drag in begin and end overloads
using std::begin;
using std::end;
// helper template
template <int I> using _ol = std::integral_constant<int, I>*;
// SFINAE check whether T is a range with begin/end
template<class T>
class is_range
{
// helper function declarations using expression sfinae
template <class U, _ol<0> = nullptr>
static std::false_type b(...);
template <class U, _ol<1> = nullptr>
static auto b(U &v) -> decltype(begin(v), std::true_type());
template <class U, _ol<0> = nullptr>
static std::false_type e(...);
template <class U, _ol<1> = nullptr>
static auto e(U &v) -> decltype(end(v), std::true_type());
// return types
using b_return = decltype(b<T>(std::declval<T&>()));
using e_return = decltype(e<T>(std::declval<T&>()));
public:
static const bool value = b_return::value && e_return::value;
};
}
// holder class for data
template<class T, class CharT = char,
class TraitT = std::char_traits < CharT >>
struct decor
{
static const int xindex;
std::basic_string<CharT, TraitT> prefix, delimiter, postfix;
decor(std::basic_string<CharT, TraitT> const & pre = "",
std::basic_string<CharT, TraitT> const & delim = "",
std::basic_string<CharT, TraitT> const & post = "")
: prefix(pre), delimiter(delim), postfix(post) {}
};
template<class T, class charT, class traits>
int const decor<T, charT, traits>::xindex = std::ios_base::xalloc();
namespace detail
{
template<class T, class CharT, class TraitT>
void manage_decor(std::ios_base::event evt, std::ios_base &s, int const idx)
{
using deco_type = decor<T, CharT, TraitT>;
if (evt == std::ios_base::erase_event)
{ // erase deco
void const * const p = s.pword(idx);
if (p)
{
delete static_cast<deco_type const * const>(p);
s.pword(idx) = nullptr;
}
}
else if (evt == std::ios_base::copyfmt_event)
{ // copy deco
void const * const p = s.pword(idx);
if (p)
{
auto np = new deco_type{ *static_cast<deco_type const * const>(p) };
s.pword(idx) = static_cast<void*>(np);
}
}
}
template<class T>
struct clearer {};
template<class T, class CharT, class TraitT>
std::basic_ostream<CharT, TraitT>& operator<< (
std::basic_ostream<CharT, TraitT> &s, clearer<T> const &)
{
using deco_type = decor<T, CharT, TraitT>;
void const * const p = s.pword(deco_type::xindex);
if (p)
{ // delete if set
delete static_cast<deco_type const *>(p);
s.pword(deco_type::xindex) = nullptr;
}
return s;
}
template<class CharT, class TraitT = std::char_traits<CharT>>
struct default_data
{
static inline std::basic_string<CharT, TraitT> prefix() { return{ "" }; }
static inline std::basic_string<CharT, TraitT> delimiter() { return{ ", " }; }
static inline std::basic_string<CharT, TraitT> postfix() { return{ "" }; }
};
template<>
struct default_data<wchar_t, std::char_traits<wchar_t>>
{
using CT = std::char_traits<wchar_t>;
static inline std::basic_string<wchar_t, CT> prefix() { return{ L"" }; }
static inline std::basic_string<wchar_t, CT> delimiter() { return{ L", " }; }
static inline std::basic_string<wchar_t, CT> postfix() { return{ L"" }; }
};
}
// Clear decoration for T
template<class T>
detail::clearer<T> clear() { return{}; }
template<class T, class CharT, class TraitT>
void clear(std::basic_ostream<CharT, TraitT> &s) { s << detail::clearer<T>{}; }
// impose decoration on ostream
template<class T, class CharT, class TraitT>
std::basic_ostream<CharT, TraitT>& operator<<(
std::basic_ostream<CharT, TraitT> &s, decor<T, CharT, TraitT> && h)
{
using deco_type = decor<T, CharT, TraitT>;
void const * const p = s.pword(deco_type::xindex);
// delete if already set
if (p) delete static_cast<decor<T, CharT, TraitT> const *>(p);
s.pword(deco_type::xindex) = static_cast<void *>(new deco_type{ std::move(h) });
// check whether we alread have a callback registered
if (s.iword(deco_type::xindex) == 0)
{ // if this is not the case register callback and set iword
s.register_callback(detail::manage_decor<T, CharT, TraitT>, deco_type::xindex);
s.iword(deco_type::xindex) = 1;
}
return s;
}
template<class T, class CharT = char, class TraitT = std::char_traits<CharT>>
struct defaulted
{
static inline decor<T, CharT, TraitT> decoration()
{
return{ detail::default_data<CharT, TraitT>::prefix(),
detail::default_data<CharT, TraitT>::delimiter(),
detail::default_data<CharT, TraitT>::postfix() };
}
};
template<class T, class CharT = char, class TraitT = std::char_traits<CharT>>
decor<T, CharT, TraitT> decoration(std::basic_string<CharT, TraitT> const & prefix,
std::basic_string<CharT, TraitT> const & delimiter,
std::basic_string<CharT, TraitT> const & postfix)
{
return{ prefix, delimiter, postfix };
}
template<class T, class CharT = char,
class TraitT = std::char_traits < CharT >>
decor<T, CharT, TraitT> decoration(std::basic_string<CharT, TraitT> const & delimiter)
{
using str_type = std::basic_string<CharT, TraitT>;
return{ defaulted<T, CharT, TraitT>::decoration().prefix,
delimiter, defaulted<T, CharT, TraitT>::decoration().postfix };
}
template<class T, class CharT = char,
class TraitT = std::char_traits < CharT >>
decor<T, CharT, TraitT> decoration(CharT const * const prefix,
CharT const * const delimiter, CharT const * const postfix)
{
using str_type = std::basic_string<CharT, TraitT>;
return{ str_type{ prefix }, str_type{ delimiter }, str_type{ postfix } };
}
template<class T, class CharT = char,
class TraitT = std::char_traits < CharT >>
decor<T, CharT, TraitT> decoration(CharT const * const delimiter)
{
using str_type = std::basic_string<CharT, TraitT>;
return{ defaulted<T, CharT, TraitT>::decoration().prefix,
str_type{ delimiter }, defaulted<T, CharT, TraitT>::decoration().postfix };
}
template<typename T, std::size_t N, std::size_t L>
struct tuple
{
template<class CharT, class TraitT>
static void print(std::basic_ostream<CharT, TraitT>& s, T const & value,
std::basic_string<CharT, TraitT> const &delimiter)
{
s << std::get<N>(value) << delimiter;
tuple<T, N + 1, L>::print(s, value, delimiter);
}
};
template<typename T, std::size_t N>
struct tuple<T, N, N>
{
template<class CharT, class TraitT>
static void print(std::basic_ostream<CharT, TraitT>& s, T const & value,
std::basic_string<CharT, TraitT> const &) {
s << std::get<N>(value);
}
};
}
template<class CharT, class TraitT>
std::basic_ostream<CharT, TraitT> & operator<< (
std::basic_ostream<CharT, TraitT> &s, std::tuple<> const & v)
{
using deco_type = pretty::decor<std::tuple<void*>, CharT, TraitT>;
using defaulted_type = pretty::defaulted<std::tuple<void*>, CharT, TraitT>;
void const * const p = s.pword(deco_type::xindex);
auto const d = static_cast<deco_type const * const>(p);
s << (d ? d->prefix : defaulted_type::decoration().prefix);
s << (d ? d->postfix : defaulted_type::decoration().postfix);
return s;
}
template<class CharT, class TraitT, class ... T>
std::basic_ostream<CharT, TraitT> & operator<< (
std::basic_ostream<CharT, TraitT> &s, std::tuple<T...> const & v)
{
using deco_type = pretty::decor<std::tuple<void*>, CharT, TraitT>;
using defaulted_type = pretty::defaulted<std::tuple<void*>, CharT, TraitT>;
using pretty_tuple = pretty::tuple<std::tuple<T...>, 0U, sizeof...(T)-1U>;
void const * const p = s.pword(deco_type::xindex);
auto const d = static_cast<deco_type const * const>(p);
s << (d ? d->prefix : defaulted_type::decoration().prefix);
pretty_tuple::print(s, v, d ? d->delimiter : defaulted_type::decoration().delimiter);
s << (d ? d->postfix : defaulted_type::decoration().postfix);
return s;
}
template<class T, class U, class CharT, class TraitT>
std::basic_ostream<CharT, TraitT> & operator<< (
std::basic_ostream<CharT, TraitT> &s, std::pair<T, U> const & v)
{
using deco_type = pretty::decor<std::pair<T, U>, CharT, TraitT>;
using defaulted_type = pretty::defaulted<std::pair<T, U>, CharT, TraitT>;
void const * const p = s.pword(deco_type::xindex);
auto const d = static_cast<deco_type const * const>(p);
s << (d ? d->prefix : defaulted_type::decoration().prefix);
s << v.first;
s << (d ? d->delimiter : defaulted_type::decoration().delimiter);
s << v.second;
s << (d ? d->postfix : defaulted_type::decoration().postfix);
return s;
}
template<class T, class CharT = char,
class TraitT = std::char_traits < CharT >>
typename std::enable_if < pretty::detail::is_range<T>::value,
std::basic_ostream < CharT, TraitT >> ::type & operator<< (
std::basic_ostream<CharT, TraitT> &s, T const & v)
{
bool first(true);
using deco_type = pretty::decor<T, CharT, TraitT>;
using default_type = pretty::defaulted<T, CharT, TraitT>;
void const * const p = s.pword(deco_type::xindex);
auto d = static_cast<pretty::decor<T, CharT, TraitT> const * const>(p);
s << (d ? d->prefix : default_type::decoration().prefix);
for (auto const & e : v)
{ // v is range thus range based for works
if (!first) s << (d ? d->delimiter : default_type::decoration().delimiter);
s << e;
first = false;
}
s << (d ? d->postfix : default_type::decoration().postfix);
return s;
}
#endif // pretty_print_0x57547_sa4884X_0_1_h_guard_
#include <vector>
#include <map>
#include <set>
#include <sstream>
#include <list>
#include <exception>
#include <utility>
PRETTY_DEFAULT_DECORATION(T[N], "[", ";", "]", class T, std::size_t N)
#define COMMA ,
PRETTY_DEFAULT_DECORATION(std::pair<T COMMA U>, "(", ", ", ")", class T, class U)
int main(int argc, char ** argv)
{
#ifndef _DROP_EXCEPTIONS
try
{
#endif
float e[5] = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f };
std::vector<std::vector<int>> m{ { 1,2,3 },{ 4,5,6 },{ 7,8,9 } };
std::cout << pretty::decoration<std::vector<std::vector<int>>>("\n");
std::cout << m;
std::stringstream u, v;
// apply different decoration to u and v
u << pretty::decoration<float[5]>("{", "; ", "}");
v << pretty::decoration<float[5]>("[", ", ", "]");
std::cout << e << '\n'; // using specialized decoration above
u << e << '\n';
v << e << '\n';
std::cout << u.str() << v.str();
std::set<int> ms{ 1, 5, 3, 2, 9, 6, 7 };
std::cout << ms << '\n';
std::map<int, int> mm{ std::make_pair<const int, int>(1,1),
std::make_pair<const int, int>(2,4),
std::make_pair<const int, int>(3,7) };
std::cout << mm << '\n';
std::list<int> ml{ 12, 12, 15, 8, 2, 1, 4 };
std::cout << ml << '\n';
std::vector<int> mv{ 155, 32, 26, 0 };
std::cout << mv << '\n';
std::vector<int> a{ 2, 3, 4, 1 }, b{ 4, 6, 1, 2 };
std::vector<std::vector<int>> c{ a, b, b, a };
std::vector<double> d{ 4.,5.,8.,124.4 };
std::cout << pretty::decoration<std::vector<int>>("[[ ", " :: ", " ]]");
std::cout << a << '\n';
std::cout << b << '\n';
std::cout << pretty::clear<std::vector<int>>();
std::cout << c << '\n';
std::cout << d << '\n';
#ifndef _DROP_EXCEPTIONS
}
catch (std::exception & e)
{
std::cout << e.what();
}
#endif
return 0;
}
ICAgICNpZm5kZWYgcHJldHR5X3ByaW50XzB4NTc1NDdfc2E0ODg0WF8wXzFfaF9ndWFyZF8KICAgICNkZWZpbmUgcHJldHR5X3ByaW50XzB4NTc1NDdfc2E0ODg0WF8wXzFfaF9ndWFyZF8KCiAgICAjaW5jbHVkZSA8c3RyaW5nPgogICAgI2luY2x1ZGUgPGlvc3RyZWFtPgogICAgI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgogICAgI2luY2x1ZGUgPGl0ZXJhdG9yPgogICAgI2luY2x1ZGUgPHV0aWxpdHk+CgogICAgI2RlZmluZSBQUkVUVFlfREVGQVVMVF9ERUNPUkFUSU9OKFRZUEUsIFBSRUZJWCwgREVMSU0sIFBPU1RGSVgsIC4uLikgXAogICAgICAgIG5hbWVzcGFjZSBwcmV0dHkgeyB0ZW1wbGF0ZTwgX19WQV9BUkdTX18gPlwKICAgICAgICBzdHJ1Y3QgZGVmYXVsdGVkPCBUWVBFID4ge1wKICAgICAgICBzdGF0aWMgZGVjb3I8IFRZUEUgPiBkZWNvcmF0aW9uKCl7XAogICAgICAgICAgcmV0dXJuIHsgUFJFRklYLCBERUxJTSwgUE9TVEZJWCB9O1wKICAgICAgICB9IC8qZGVjb3JhdGlvbiovIH07IC8qZGVmYXVsdGVkKi99IC8qcHJldHR5Ki8KCiAgICAjZGVmaW5lIFBSRVRUWV9ERUZBVUxUX1dERUNPUkFUSU9OKFRZUEUsIFBSRUZJWCwgREVMSU0sIFBPU1RGSVgsIC4uLikgXAogICAgICAgIG5hbWVzcGFjZSBwcmV0dHkgeyB0ZW1wbGF0ZTwgX19WQV9BUkdTX18gPlwKICAgICAgICBzdHJ1Y3QgZGVmYXVsdGVkPCBUWVBFLCB3Y2hhcl90LCBzdGQ6OmNoYXJfdHJhaXRzPHdjaGFyX3Q+ID4ge1wKICAgICAgICBzdGF0aWMgZGVjb3I8IFRZUEUsIHdjaGFyX3QsIHN0ZDo6Y2hhcl90cmFpdHM8d2NoYXJfdD4gPiBkZWNvcmF0aW9uKCl7XAogICAgICAgICAgcmV0dXJuIHsgUFJFRklYLCBERUxJTSwgUE9TVEZJWCB9O1wKICAgICAgICB9IC8qZGVjb3JhdGlvbiovIH07IC8qZGVmYXVsdGVkKi99IC8qcHJldHR5Ki8KCiAgICBuYW1lc3BhY2UgcHJldHR5CiAgICB7CgogICAgICBuYW1lc3BhY2UgZGV0YWlsCiAgICAgIHsKICAgICAgICAvLyBkcmFnIGluIGJlZ2luIGFuZCBlbmQgb3ZlcmxvYWRzCiAgICAgICAgdXNpbmcgc3RkOjpiZWdpbjsKICAgICAgICB1c2luZyBzdGQ6OmVuZDsKICAgICAgICAvLyBoZWxwZXIgdGVtcGxhdGUKICAgICAgICB0ZW1wbGF0ZSA8aW50IEk+IHVzaW5nIF9vbCA9IHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8aW50LCBJPio7CiAgICAgICAgLy8gU0ZJTkFFIGNoZWNrIHdoZXRoZXIgVCBpcyBhIHJhbmdlIHdpdGggYmVnaW4vZW5kCiAgICAgICAgdGVtcGxhdGU8Y2xhc3MgVD4KICAgICAgICBjbGFzcyBpc19yYW5nZQogICAgICAgIHsKICAgICAgICAgIC8vIGhlbHBlciBmdW5jdGlvbiBkZWNsYXJhdGlvbnMgdXNpbmcgZXhwcmVzc2lvbiBzZmluYWUKICAgICAgICAgIHRlbXBsYXRlIDxjbGFzcyBVLCBfb2w8MD4gPSBudWxscHRyPgogICAgICAgICAgc3RhdGljIHN0ZDo6ZmFsc2VfdHlwZSBiKC4uLik7CiAgICAgICAgICB0ZW1wbGF0ZSA8Y2xhc3MgVSwgX29sPDE+ID0gbnVsbHB0cj4KICAgICAgICAgIHN0YXRpYyBhdXRvIGIoVSAmdikgLT4gZGVjbHR5cGUoYmVnaW4odiksIHN0ZDo6dHJ1ZV90eXBlKCkpOwogICAgICAgICAgdGVtcGxhdGUgPGNsYXNzIFUsIF9vbDwwPiA9IG51bGxwdHI+CiAgICAgICAgICBzdGF0aWMgc3RkOjpmYWxzZV90eXBlIGUoLi4uKTsKICAgICAgICAgIHRlbXBsYXRlIDxjbGFzcyBVLCBfb2w8MT4gPSBudWxscHRyPgogICAgICAgICAgc3RhdGljIGF1dG8gZShVICZ2KSAtPiBkZWNsdHlwZShlbmQodiksIHN0ZDo6dHJ1ZV90eXBlKCkpOwogICAgICAgICAgLy8gcmV0dXJuIHR5cGVzCiAgICAgICAgICB1c2luZyBiX3JldHVybiA9IGRlY2x0eXBlKGI8VD4oc3RkOjpkZWNsdmFsPFQmPigpKSk7CiAgICAgICAgICB1c2luZyBlX3JldHVybiA9IGRlY2x0eXBlKGU8VD4oc3RkOjpkZWNsdmFsPFQmPigpKSk7CiAgICAgICAgcHVibGljOgogICAgICAgICAgc3RhdGljIGNvbnN0IGJvb2wgdmFsdWUgPSBiX3JldHVybjo6dmFsdWUgJiYgZV9yZXR1cm46OnZhbHVlOwogICAgICAgIH07CiAgICAgIH0KCiAgICAgIC8vIGhvbGRlciBjbGFzcyBmb3IgZGF0YQogICAgICB0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcyBDaGFyVCA9IGNoYXIsCiAgICAgIGNsYXNzIFRyYWl0VCA9IHN0ZDo6Y2hhcl90cmFpdHMgPCBDaGFyVCA+PgogICAgICBzdHJ1Y3QgZGVjb3IKICAgICAgewogICAgICAgIHN0YXRpYyBjb25zdCBpbnQgeGluZGV4OwogICAgICAgIHN0ZDo6YmFzaWNfc3RyaW5nPENoYXJULCBUcmFpdFQ+IHByZWZpeCwgZGVsaW1pdGVyLCBwb3N0Zml4OwogICAgICAgIGRlY29yKHN0ZDo6YmFzaWNfc3RyaW5nPENoYXJULCBUcmFpdFQ+IGNvbnN0ICYgcHJlID0gIiIsCiAgICAgICAgICBzdGQ6OmJhc2ljX3N0cmluZzxDaGFyVCwgVHJhaXRUPiBjb25zdCAmIGRlbGltID0gIiIsCiAgICAgICAgICBzdGQ6OmJhc2ljX3N0cmluZzxDaGFyVCwgVHJhaXRUPiBjb25zdCAmIHBvc3QgPSAiIikKICAgICAgICAgIDogcHJlZml4KHByZSksIGRlbGltaXRlcihkZWxpbSksIHBvc3RmaXgocG9zdCkge30KICAgICAgfTsKCiAgICAgIHRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIGNoYXJULCBjbGFzcyB0cmFpdHM+CiAgICAgIGludCBjb25zdCBkZWNvcjxULCBjaGFyVCwgdHJhaXRzPjo6eGluZGV4ID0gc3RkOjppb3NfYmFzZTo6eGFsbG9jKCk7CgogICAgICBuYW1lc3BhY2UgZGV0YWlsCiAgICAgIHsKCiAgICAgICAgdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgQ2hhclQsIGNsYXNzIFRyYWl0VD4KICAgICAgICB2b2lkIG1hbmFnZV9kZWNvcihzdGQ6Omlvc19iYXNlOjpldmVudCBldnQsIHN0ZDo6aW9zX2Jhc2UgJnMsIGludCBjb25zdCBpZHgpCiAgICAgICAgewogICAgICAgICAgdXNpbmcgZGVjb190eXBlID0gZGVjb3I8VCwgQ2hhclQsIFRyYWl0VD47CiAgICAgICAgICBpZiAoZXZ0ID09IHN0ZDo6aW9zX2Jhc2U6OmVyYXNlX2V2ZW50KQogICAgICAgICAgeyAvLyBlcmFzZSBkZWNvCiAgICAgICAgICAgIHZvaWQgY29uc3QgKiBjb25zdCBwID0gcy5wd29yZChpZHgpOwogICAgICAgICAgICBpZiAocCkKICAgICAgICAgICAgewogICAgICAgICAgICAgIGRlbGV0ZSBzdGF0aWNfY2FzdDxkZWNvX3R5cGUgY29uc3QgKiBjb25zdD4ocCk7CiAgICAgICAgICAgICAgcy5wd29yZChpZHgpID0gbnVsbHB0cjsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZWxzZSBpZiAoZXZ0ID09IHN0ZDo6aW9zX2Jhc2U6OmNvcHlmbXRfZXZlbnQpCiAgICAgICAgICB7IC8vIGNvcHkgZGVjbwogICAgICAgICAgICB2b2lkIGNvbnN0ICogY29uc3QgcCA9IHMucHdvcmQoaWR4KTsKICAgICAgICAgICAgaWYgKHApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBhdXRvIG5wID0gbmV3IGRlY29fdHlwZXsgKnN0YXRpY19jYXN0PGRlY29fdHlwZSBjb25zdCAqIGNvbnN0PihwKSB9OwogICAgICAgICAgICAgIHMucHdvcmQoaWR4KSA9IHN0YXRpY19jYXN0PHZvaWQqPihucCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHRlbXBsYXRlPGNsYXNzIFQ+CiAgICAgICAgc3RydWN0IGNsZWFyZXIge307CgogICAgICAgIHRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIENoYXJULCBjbGFzcyBUcmFpdFQ+CiAgICAgICAgc3RkOjpiYXNpY19vc3RyZWFtPENoYXJULCBUcmFpdFQ+JiBvcGVyYXRvcjw8ICgKICAgICAgICAgIHN0ZDo6YmFzaWNfb3N0cmVhbTxDaGFyVCwgVHJhaXRUPiAmcywgY2xlYXJlcjxUPiBjb25zdCAmKQogICAgICAgIHsKICAgICAgICAgIHVzaW5nIGRlY29fdHlwZSA9IGRlY29yPFQsIENoYXJULCBUcmFpdFQ+OwogICAgICAgICAgdm9pZCBjb25zdCAqIGNvbnN0IHAgPSBzLnB3b3JkKGRlY29fdHlwZTo6eGluZGV4KTsKICAgICAgICAgIGlmIChwKQogICAgICAgICAgeyAvLyBkZWxldGUgaWYgc2V0CiAgICAgICAgICAgIGRlbGV0ZSBzdGF0aWNfY2FzdDxkZWNvX3R5cGUgY29uc3QgKj4ocCk7CiAgICAgICAgICAgIHMucHdvcmQoZGVjb190eXBlOjp4aW5kZXgpID0gbnVsbHB0cjsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzOwogICAgICAgIH0KCiAgICAgICAgdGVtcGxhdGU8Y2xhc3MgQ2hhclQsIGNsYXNzIFRyYWl0VCA9IHN0ZDo6Y2hhcl90cmFpdHM8Q2hhclQ+PgogICAgICAgIHN0cnVjdCBkZWZhdWx0X2RhdGEKICAgICAgICB7CiAgICAgICAgICBzdGF0aWMgaW5saW5lIHN0ZDo6YmFzaWNfc3RyaW5nPENoYXJULCBUcmFpdFQ+IHByZWZpeCgpIHsgcmV0dXJueyAiIiB9OyB9CiAgICAgICAgICBzdGF0aWMgaW5saW5lIHN0ZDo6YmFzaWNfc3RyaW5nPENoYXJULCBUcmFpdFQ+IGRlbGltaXRlcigpIHsgcmV0dXJueyAiLCAiIH07IH0KICAgICAgICAgIHN0YXRpYyBpbmxpbmUgc3RkOjpiYXNpY19zdHJpbmc8Q2hhclQsIFRyYWl0VD4gcG9zdGZpeCgpIHsgcmV0dXJueyAiIiB9OyB9CiAgICAgICAgfTsKCiAgICAgICAgdGVtcGxhdGU8PgogICAgICAgIHN0cnVjdCBkZWZhdWx0X2RhdGE8d2NoYXJfdCwgc3RkOjpjaGFyX3RyYWl0czx3Y2hhcl90Pj4KICAgICAgICB7CiAgICAgICAgICB1c2luZyBDVCA9IHN0ZDo6Y2hhcl90cmFpdHM8d2NoYXJfdD47CiAgICAgICAgICBzdGF0aWMgaW5saW5lIHN0ZDo6YmFzaWNfc3RyaW5nPHdjaGFyX3QsIENUPiBwcmVmaXgoKSB7IHJldHVybnsgTCIiIH07IH0KICAgICAgICAgIHN0YXRpYyBpbmxpbmUgc3RkOjpiYXNpY19zdHJpbmc8d2NoYXJfdCwgQ1Q+IGRlbGltaXRlcigpIHsgcmV0dXJueyBMIiwgIiB9OyB9CiAgICAgICAgICBzdGF0aWMgaW5saW5lIHN0ZDo6YmFzaWNfc3RyaW5nPHdjaGFyX3QsIENUPiBwb3N0Zml4KCkgeyByZXR1cm57IEwiIiB9OyB9CiAgICAgICAgfTsKCiAgICAgIH0KCiAgICAgIC8vIENsZWFyIGRlY29yYXRpb24gZm9yIFQKICAgICAgdGVtcGxhdGU8Y2xhc3MgVD4KICAgICAgZGV0YWlsOjpjbGVhcmVyPFQ+IGNsZWFyKCkgeyByZXR1cm57fTsgfQogICAgICB0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcyBDaGFyVCwgY2xhc3MgVHJhaXRUPgogICAgICB2b2lkIGNsZWFyKHN0ZDo6YmFzaWNfb3N0cmVhbTxDaGFyVCwgVHJhaXRUPiAmcykgeyBzIDw8IGRldGFpbDo6Y2xlYXJlcjxUPnt9OyB9CgogICAgICAvLyBpbXBvc2UgZGVjb3JhdGlvbiBvbiBvc3RyZWFtCiAgICAgIHRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIENoYXJULCBjbGFzcyBUcmFpdFQ+CiAgICAgIHN0ZDo6YmFzaWNfb3N0cmVhbTxDaGFyVCwgVHJhaXRUPiYgb3BlcmF0b3I8PCgKICAgICAgICBzdGQ6OmJhc2ljX29zdHJlYW08Q2hhclQsIFRyYWl0VD4gJnMsIGRlY29yPFQsIENoYXJULCBUcmFpdFQ+ICYmIGgpCiAgICAgIHsKICAgICAgICB1c2luZyBkZWNvX3R5cGUgPSBkZWNvcjxULCBDaGFyVCwgVHJhaXRUPjsKICAgICAgICB2b2lkIGNvbnN0ICogY29uc3QgcCA9IHMucHdvcmQoZGVjb190eXBlOjp4aW5kZXgpOwogICAgICAgIC8vIGRlbGV0ZSBpZiBhbHJlYWR5IHNldAogICAgICAgIGlmIChwKSBkZWxldGUgc3RhdGljX2Nhc3Q8ZGVjb3I8VCwgQ2hhclQsIFRyYWl0VD4gY29uc3QgKj4ocCk7CiAgICAgICAgcy5wd29yZChkZWNvX3R5cGU6OnhpbmRleCkgPSBzdGF0aWNfY2FzdDx2b2lkICo+KG5ldyBkZWNvX3R5cGV7IHN0ZDo6bW92ZShoKSB9KTsKICAgICAgICAvLyBjaGVjayB3aGV0aGVyIHdlIGFscmVhZCBoYXZlIGEgY2FsbGJhY2sgcmVnaXN0ZXJlZAogICAgICAgIGlmIChzLml3b3JkKGRlY29fdHlwZTo6eGluZGV4KSA9PSAwKQogICAgICAgIHsgLy8gaWYgdGhpcyBpcyBub3QgdGhlIGNhc2UgcmVnaXN0ZXIgY2FsbGJhY2sgYW5kIHNldCBpd29yZAogICAgICAgICAgcy5yZWdpc3Rlcl9jYWxsYmFjayhkZXRhaWw6Om1hbmFnZV9kZWNvcjxULCBDaGFyVCwgVHJhaXRUPiwgZGVjb190eXBlOjp4aW5kZXgpOwogICAgICAgICAgcy5pd29yZChkZWNvX3R5cGU6OnhpbmRleCkgPSAxOwogICAgICAgIH0KICAgICAgICByZXR1cm4gczsKICAgICAgfQoKICAgICAgdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgQ2hhclQgPSBjaGFyLCBjbGFzcyBUcmFpdFQgPSBzdGQ6OmNoYXJfdHJhaXRzPENoYXJUPj4KICAgICAgc3RydWN0IGRlZmF1bHRlZAogICAgICB7CiAgICAgICAgc3RhdGljIGlubGluZSBkZWNvcjxULCBDaGFyVCwgVHJhaXRUPiBkZWNvcmF0aW9uKCkKICAgICAgICB7CiAgICAgICAgICByZXR1cm57IGRldGFpbDo6ZGVmYXVsdF9kYXRhPENoYXJULCBUcmFpdFQ+OjpwcmVmaXgoKSwKICAgICAgICAgICAgZGV0YWlsOjpkZWZhdWx0X2RhdGE8Q2hhclQsIFRyYWl0VD46OmRlbGltaXRlcigpLAogICAgICAgICAgICBkZXRhaWw6OmRlZmF1bHRfZGF0YTxDaGFyVCwgVHJhaXRUPjo6cG9zdGZpeCgpIH07CiAgICAgICAgfQogICAgICB9OwoKICAgICAgdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgQ2hhclQgPSBjaGFyLCBjbGFzcyBUcmFpdFQgPSBzdGQ6OmNoYXJfdHJhaXRzPENoYXJUPj4KICAgICAgZGVjb3I8VCwgQ2hhclQsIFRyYWl0VD4gZGVjb3JhdGlvbihzdGQ6OmJhc2ljX3N0cmluZzxDaGFyVCwgVHJhaXRUPiBjb25zdCAmIHByZWZpeCwKICAgICAgICBzdGQ6OmJhc2ljX3N0cmluZzxDaGFyVCwgVHJhaXRUPiBjb25zdCAmIGRlbGltaXRlciwKICAgICAgICBzdGQ6OmJhc2ljX3N0cmluZzxDaGFyVCwgVHJhaXRUPiBjb25zdCAmIHBvc3RmaXgpCiAgICAgIHsKICAgICAgICByZXR1cm57IHByZWZpeCwgZGVsaW1pdGVyLCBwb3N0Zml4IH07CiAgICAgIH0KCiAgICAgIHRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIENoYXJUID0gY2hhciwKICAgICAgY2xhc3MgVHJhaXRUID0gc3RkOjpjaGFyX3RyYWl0cyA8IENoYXJUID4+CiAgICAgICAgZGVjb3I8VCwgQ2hhclQsIFRyYWl0VD4gZGVjb3JhdGlvbihzdGQ6OmJhc2ljX3N0cmluZzxDaGFyVCwgVHJhaXRUPiBjb25zdCAmIGRlbGltaXRlcikKICAgICAgewogICAgICAgIHVzaW5nIHN0cl90eXBlID0gc3RkOjpiYXNpY19zdHJpbmc8Q2hhclQsIFRyYWl0VD47CiAgICAgICAgcmV0dXJueyBkZWZhdWx0ZWQ8VCwgQ2hhclQsIFRyYWl0VD46OmRlY29yYXRpb24oKS5wcmVmaXgsCiAgICAgICAgICBkZWxpbWl0ZXIsIGRlZmF1bHRlZDxULCBDaGFyVCwgVHJhaXRUPjo6ZGVjb3JhdGlvbigpLnBvc3RmaXggfTsKICAgICAgfQoKICAgICAgdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgQ2hhclQgPSBjaGFyLAogICAgICBjbGFzcyBUcmFpdFQgPSBzdGQ6OmNoYXJfdHJhaXRzIDwgQ2hhclQgPj4KICAgICAgICBkZWNvcjxULCBDaGFyVCwgVHJhaXRUPiBkZWNvcmF0aW9uKENoYXJUIGNvbnN0ICogY29uc3QgcHJlZml4LAogICAgICAgICAgQ2hhclQgY29uc3QgKiBjb25zdCBkZWxpbWl0ZXIsIENoYXJUIGNvbnN0ICogY29uc3QgcG9zdGZpeCkKICAgICAgewogICAgICAgIHVzaW5nIHN0cl90eXBlID0gc3RkOjpiYXNpY19zdHJpbmc8Q2hhclQsIFRyYWl0VD47CiAgICAgICAgcmV0dXJueyBzdHJfdHlwZXsgcHJlZml4IH0sIHN0cl90eXBleyBkZWxpbWl0ZXIgfSwgc3RyX3R5cGV7IHBvc3RmaXggfSB9OwogICAgICB9CgogICAgICB0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcyBDaGFyVCA9IGNoYXIsCiAgICAgIGNsYXNzIFRyYWl0VCA9IHN0ZDo6Y2hhcl90cmFpdHMgPCBDaGFyVCA+PgogICAgICAgIGRlY29yPFQsIENoYXJULCBUcmFpdFQ+IGRlY29yYXRpb24oQ2hhclQgY29uc3QgKiBjb25zdCBkZWxpbWl0ZXIpCiAgICAgIHsKICAgICAgICB1c2luZyBzdHJfdHlwZSA9IHN0ZDo6YmFzaWNfc3RyaW5nPENoYXJULCBUcmFpdFQ+OwogICAgICAgIHJldHVybnsgZGVmYXVsdGVkPFQsIENoYXJULCBUcmFpdFQ+OjpkZWNvcmF0aW9uKCkucHJlZml4LAogICAgICAgICAgc3RyX3R5cGV7IGRlbGltaXRlciB9LCBkZWZhdWx0ZWQ8VCwgQ2hhclQsIFRyYWl0VD46OmRlY29yYXRpb24oKS5wb3N0Zml4IH07CiAgICAgIH0KCiAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQsIHN0ZDo6c2l6ZV90IE4sIHN0ZDo6c2l6ZV90IEw+CiAgICAgIHN0cnVjdCB0dXBsZQogICAgICB7CiAgICAgICAgdGVtcGxhdGU8Y2xhc3MgQ2hhclQsIGNsYXNzIFRyYWl0VD4KICAgICAgICBzdGF0aWMgdm9pZCBwcmludChzdGQ6OmJhc2ljX29zdHJlYW08Q2hhclQsIFRyYWl0VD4mIHMsIFQgY29uc3QgJiB2YWx1ZSwKICAgICAgICAgIHN0ZDo6YmFzaWNfc3RyaW5nPENoYXJULCBUcmFpdFQ+IGNvbnN0ICZkZWxpbWl0ZXIpCiAgICAgICAgewogICAgICAgICAgcyA8PCBzdGQ6OmdldDxOPih2YWx1ZSkgPDwgZGVsaW1pdGVyOwogICAgICAgICAgdHVwbGU8VCwgTiArIDEsIEw+OjpwcmludChzLCB2YWx1ZSwgZGVsaW1pdGVyKTsKICAgICAgICB9CiAgICAgIH07CgogICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBULCBzdGQ6OnNpemVfdCBOPgogICAgICBzdHJ1Y3QgdHVwbGU8VCwgTiwgTj4KICAgICAgewogICAgICAgIHRlbXBsYXRlPGNsYXNzIENoYXJULCBjbGFzcyBUcmFpdFQ+CiAgICAgICAgc3RhdGljIHZvaWQgcHJpbnQoc3RkOjpiYXNpY19vc3RyZWFtPENoYXJULCBUcmFpdFQ+JiBzLCBUIGNvbnN0ICYgdmFsdWUsCiAgICAgICAgICBzdGQ6OmJhc2ljX3N0cmluZzxDaGFyVCwgVHJhaXRUPiBjb25zdCAmKSB7CiAgICAgICAgICBzIDw8IHN0ZDo6Z2V0PE4+KHZhbHVlKTsKICAgICAgICB9CiAgICAgIH07CgogICAgfQoKICAgIHRlbXBsYXRlPGNsYXNzIENoYXJULCBjbGFzcyBUcmFpdFQ+CiAgICBzdGQ6OmJhc2ljX29zdHJlYW08Q2hhclQsIFRyYWl0VD4gJiBvcGVyYXRvcjw8ICgKICAgICAgc3RkOjpiYXNpY19vc3RyZWFtPENoYXJULCBUcmFpdFQ+ICZzLCBzdGQ6OnR1cGxlPD4gY29uc3QgJiB2KQogICAgewogICAgICB1c2luZyBkZWNvX3R5cGUgPSBwcmV0dHk6OmRlY29yPHN0ZDo6dHVwbGU8dm9pZCo+LCBDaGFyVCwgVHJhaXRUPjsKICAgICAgdXNpbmcgZGVmYXVsdGVkX3R5cGUgPSBwcmV0dHk6OmRlZmF1bHRlZDxzdGQ6OnR1cGxlPHZvaWQqPiwgQ2hhclQsIFRyYWl0VD47CiAgICAgIHZvaWQgY29uc3QgKiBjb25zdCBwID0gcy5wd29yZChkZWNvX3R5cGU6OnhpbmRleCk7CiAgICAgIGF1dG8gY29uc3QgZCA9IHN0YXRpY19jYXN0PGRlY29fdHlwZSBjb25zdCAqIGNvbnN0PihwKTsKICAgICAgcyA8PCAoZCA/IGQtPnByZWZpeCA6IGRlZmF1bHRlZF90eXBlOjpkZWNvcmF0aW9uKCkucHJlZml4KTsKICAgICAgcyA8PCAoZCA/IGQtPnBvc3RmaXggOiBkZWZhdWx0ZWRfdHlwZTo6ZGVjb3JhdGlvbigpLnBvc3RmaXgpOwogICAgICByZXR1cm4gczsKICAgIH0KCiAgICB0ZW1wbGF0ZTxjbGFzcyBDaGFyVCwgY2xhc3MgVHJhaXRULCBjbGFzcyAuLi4gVD4KICAgIHN0ZDo6YmFzaWNfb3N0cmVhbTxDaGFyVCwgVHJhaXRUPiAmIG9wZXJhdG9yPDwgKAogICAgICBzdGQ6OmJhc2ljX29zdHJlYW08Q2hhclQsIFRyYWl0VD4gJnMsIHN0ZDo6dHVwbGU8VC4uLj4gY29uc3QgJiB2KQogICAgewogICAgICB1c2luZyBkZWNvX3R5cGUgPSBwcmV0dHk6OmRlY29yPHN0ZDo6dHVwbGU8dm9pZCo+LCBDaGFyVCwgVHJhaXRUPjsKICAgICAgdXNpbmcgZGVmYXVsdGVkX3R5cGUgPSBwcmV0dHk6OmRlZmF1bHRlZDxzdGQ6OnR1cGxlPHZvaWQqPiwgQ2hhclQsIFRyYWl0VD47CiAgICAgIHVzaW5nIHByZXR0eV90dXBsZSA9IHByZXR0eTo6dHVwbGU8c3RkOjp0dXBsZTxULi4uPiwgMFUsIHNpemVvZi4uLihUKS0xVT47CiAgICAgIHZvaWQgY29uc3QgKiBjb25zdCBwID0gcy5wd29yZChkZWNvX3R5cGU6OnhpbmRleCk7CiAgICAgIGF1dG8gY29uc3QgZCA9IHN0YXRpY19jYXN0PGRlY29fdHlwZSBjb25zdCAqIGNvbnN0PihwKTsKICAgICAgcyA8PCAoZCA/IGQtPnByZWZpeCA6IGRlZmF1bHRlZF90eXBlOjpkZWNvcmF0aW9uKCkucHJlZml4KTsKICAgICAgcHJldHR5X3R1cGxlOjpwcmludChzLCB2LCBkID8gZC0+ZGVsaW1pdGVyIDogZGVmYXVsdGVkX3R5cGU6OmRlY29yYXRpb24oKS5kZWxpbWl0ZXIpOwogICAgICBzIDw8IChkID8gZC0+cG9zdGZpeCA6IGRlZmF1bHRlZF90eXBlOjpkZWNvcmF0aW9uKCkucG9zdGZpeCk7CiAgICAgIHJldHVybiBzOwogICAgfQoKICAgIHRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFUsIGNsYXNzIENoYXJULCBjbGFzcyBUcmFpdFQ+CiAgICBzdGQ6OmJhc2ljX29zdHJlYW08Q2hhclQsIFRyYWl0VD4gJiBvcGVyYXRvcjw8ICgKICAgICAgc3RkOjpiYXNpY19vc3RyZWFtPENoYXJULCBUcmFpdFQ+ICZzLCBzdGQ6OnBhaXI8VCwgVT4gY29uc3QgJiB2KQogICAgewogICAgICB1c2luZyBkZWNvX3R5cGUgPSBwcmV0dHk6OmRlY29yPHN0ZDo6cGFpcjxULCBVPiwgQ2hhclQsIFRyYWl0VD47CiAgICAgIHVzaW5nIGRlZmF1bHRlZF90eXBlID0gcHJldHR5OjpkZWZhdWx0ZWQ8c3RkOjpwYWlyPFQsIFU+LCBDaGFyVCwgVHJhaXRUPjsKICAgICAgdm9pZCBjb25zdCAqIGNvbnN0IHAgPSBzLnB3b3JkKGRlY29fdHlwZTo6eGluZGV4KTsKICAgICAgYXV0byBjb25zdCBkID0gc3RhdGljX2Nhc3Q8ZGVjb190eXBlIGNvbnN0ICogY29uc3Q+KHApOwogICAgICBzIDw8IChkID8gZC0+cHJlZml4IDogZGVmYXVsdGVkX3R5cGU6OmRlY29yYXRpb24oKS5wcmVmaXgpOwogICAgICBzIDw8IHYuZmlyc3Q7CiAgICAgIHMgPDwgKGQgPyBkLT5kZWxpbWl0ZXIgOiBkZWZhdWx0ZWRfdHlwZTo6ZGVjb3JhdGlvbigpLmRlbGltaXRlcik7CiAgICAgIHMgPDwgdi5zZWNvbmQ7CiAgICAgIHMgPDwgKGQgPyBkLT5wb3N0Zml4IDogZGVmYXVsdGVkX3R5cGU6OmRlY29yYXRpb24oKS5wb3N0Zml4KTsKICAgICAgcmV0dXJuIHM7CiAgICB9CgoKICAgIHRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIENoYXJUID0gY2hhciwKICAgIGNsYXNzIFRyYWl0VCA9IHN0ZDo6Y2hhcl90cmFpdHMgPCBDaGFyVCA+PgogICAgICB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZiA8IHByZXR0eTo6ZGV0YWlsOjppc19yYW5nZTxUPjo6dmFsdWUsCiAgICAgIHN0ZDo6YmFzaWNfb3N0cmVhbSA8IENoYXJULCBUcmFpdFQgPj4gOjp0eXBlICYgb3BlcmF0b3I8PCAoCiAgICAgICAgc3RkOjpiYXNpY19vc3RyZWFtPENoYXJULCBUcmFpdFQ+ICZzLCBUIGNvbnN0ICYgdikKICAgIHsKICAgICAgYm9vbCBmaXJzdCh0cnVlKTsKICAgICAgdXNpbmcgZGVjb190eXBlID0gcHJldHR5OjpkZWNvcjxULCBDaGFyVCwgVHJhaXRUPjsKICAgICAgdXNpbmcgZGVmYXVsdF90eXBlID0gcHJldHR5OjpkZWZhdWx0ZWQ8VCwgQ2hhclQsIFRyYWl0VD47CiAgICAgIHZvaWQgY29uc3QgKiBjb25zdCBwID0gcy5wd29yZChkZWNvX3R5cGU6OnhpbmRleCk7CiAgICAgIGF1dG8gZCA9IHN0YXRpY19jYXN0PHByZXR0eTo6ZGVjb3I8VCwgQ2hhclQsIFRyYWl0VD4gY29uc3QgKiBjb25zdD4ocCk7CiAgICAgIHMgPDwgKGQgPyBkLT5wcmVmaXggOiBkZWZhdWx0X3R5cGU6OmRlY29yYXRpb24oKS5wcmVmaXgpOwogICAgICBmb3IgKGF1dG8gY29uc3QgJiBlIDogdikKICAgICAgeyAvLyB2IGlzIHJhbmdlIHRodXMgcmFuZ2UgYmFzZWQgZm9yIHdvcmtzCiAgICAgICAgaWYgKCFmaXJzdCkgcyA8PCAoZCA/IGQtPmRlbGltaXRlciA6IGRlZmF1bHRfdHlwZTo6ZGVjb3JhdGlvbigpLmRlbGltaXRlcik7CiAgICAgICAgcyA8PCBlOwogICAgICAgIGZpcnN0ID0gZmFsc2U7CiAgICAgIH0KICAgICAgcyA8PCAoZCA/IGQtPnBvc3RmaXggOiBkZWZhdWx0X3R5cGU6OmRlY29yYXRpb24oKS5wb3N0Zml4KTsKICAgICAgcmV0dXJuIHM7CiAgICB9CgogICAgI2VuZGlmIC8vIHByZXR0eV9wcmludF8weDU3NTQ3X3NhNDg4NFhfMF8xX2hfZ3VhcmRfCgoKI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPG1hcD4KI2luY2x1ZGUgPHNldD4KI2luY2x1ZGUgPHNzdHJlYW0+CiNpbmNsdWRlIDxsaXN0PgojaW5jbHVkZSA8ZXhjZXB0aW9uPgojaW5jbHVkZSA8dXRpbGl0eT4KClBSRVRUWV9ERUZBVUxUX0RFQ09SQVRJT04oVFtOXSwgIlsiLCAiOyIsICJdIiwgY2xhc3MgVCwgc3RkOjpzaXplX3QgTikKI2RlZmluZSBDT01NQSAsClBSRVRUWV9ERUZBVUxUX0RFQ09SQVRJT04oc3RkOjpwYWlyPFQgQ09NTUEgVT4sICIoIiwgIiwgIiwgIikiLCBjbGFzcyBULCBjbGFzcyBVKQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKiogYXJndikKewoKI2lmbmRlZiBfRFJPUF9FWENFUFRJT05TCiAgdHJ5CiAgewojZW5kaWYKCiAgICBmbG9hdCBlWzVdID0geyAxLjFmLCAyLjJmLCAzLjNmLCA0LjRmLCA1LjVmIH07CgogICAgc3RkOjp2ZWN0b3I8c3RkOjp2ZWN0b3I8aW50Pj4gbXsgeyAxLDIsMyB9LHsgNCw1LDYgfSx7IDcsOCw5IH0gfTsKICAgIHN0ZDo6Y291dCA8PCBwcmV0dHk6OmRlY29yYXRpb248c3RkOjp2ZWN0b3I8c3RkOjp2ZWN0b3I8aW50Pj4+KCJcbiIpOwogICAgc3RkOjpjb3V0IDw8IG07CiAgICBzdGQ6OnN0cmluZ3N0cmVhbSB1LCB2OwogICAgLy8gYXBwbHkgZGlmZmVyZW50IGRlY29yYXRpb24gdG8gdSBhbmQgdgogICAgdSA8PCBwcmV0dHk6OmRlY29yYXRpb248ZmxvYXRbNV0+KCJ7IiwgIjsgIiwgIn0iKTsKICAgIHYgPDwgcHJldHR5OjpkZWNvcmF0aW9uPGZsb2F0WzVdPigiWyIsICIsICIsICJdIik7CiAgICBzdGQ6OmNvdXQgPDwgZSA8PCAnXG4nOyAvLyB1c2luZyBzcGVjaWFsaXplZCBkZWNvcmF0aW9uIGFib3ZlCiAgICB1IDw8IGUgPDwgJ1xuJzsKICAgIHYgPDwgZSA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IHUuc3RyKCkgPDwgdi5zdHIoKTsKCiAgICBzdGQ6OnNldDxpbnQ+IG1zeyAxLCA1LCAzLCAyLCA5LCA2LCA3IH07CiAgICBzdGQ6OmNvdXQgPDwgbXMgPDwgJ1xuJzsKCiAgICBzdGQ6Om1hcDxpbnQsIGludD4gbW17IHN0ZDo6bWFrZV9wYWlyPGNvbnN0IGludCwgaW50PigxLDEpLCAKICAgICAgc3RkOjptYWtlX3BhaXI8Y29uc3QgaW50LCBpbnQ+KDIsNCksIAogICAgICBzdGQ6Om1ha2VfcGFpcjxjb25zdCBpbnQsIGludD4oMyw3KSB9OwogICAgc3RkOjpjb3V0IDw8IG1tIDw8ICdcbic7CgogICAgc3RkOjpsaXN0PGludD4gbWx7IDEyLCAxMiwgMTUsIDgsIDIsIDEsIDQgfTsKICAgIHN0ZDo6Y291dCA8PCBtbCA8PCAnXG4nOwoKICAgIHN0ZDo6dmVjdG9yPGludD4gbXZ7IDE1NSwgMzIsIDI2LCAwIH07CiAgICBzdGQ6OmNvdXQgPDwgbXYgPDwgJ1xuJzsKCiAgICBzdGQ6OnZlY3RvcjxpbnQ+IGF7IDIsIDMsIDQsIDEgfSwgYnsgNCwgNiwgMSwgMiB9OwogICAgc3RkOjp2ZWN0b3I8c3RkOjp2ZWN0b3I8aW50Pj4gY3sgYSwgYiwgYiwgYSB9OwogICAgc3RkOjp2ZWN0b3I8ZG91YmxlPiBkeyA0Liw1Liw4LiwxMjQuNCB9OwoKICAgIHN0ZDo6Y291dCA8PCBwcmV0dHk6OmRlY29yYXRpb248c3RkOjp2ZWN0b3I8aW50Pj4oIltbICAiLCAiIDo6ICIsICIgIF1dIik7CiAgICBzdGQ6OmNvdXQgPDwgYSA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IGIgPDwgJ1xuJzsKICAgIHN0ZDo6Y291dCA8PCBwcmV0dHk6OmNsZWFyPHN0ZDo6dmVjdG9yPGludD4+KCk7CiAgICBzdGQ6OmNvdXQgPDwgYyA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IGQgPDwgJ1xuJzsKCgojaWZuZGVmIF9EUk9QX0VYQ0VQVElPTlMKICB9CiAgY2F0Y2ggKHN0ZDo6ZXhjZXB0aW9uICYgZSkKICB7CiAgICBzdGQ6OmNvdXQgPDwgZS53aGF0KCk7CiAgfQojZW5kaWYKCiAgcmV0dXJuIDA7Cn0K