// Type Functions in C++
// Todd Fleming
// 2014/12/01
#include <assert.h>
#include <iostream>
#include <type_traits>
#include <typeinfo>
#include <utility>
using namespace std;
// C++ metafunctions normally don't look like functions. What if
// this changed with C++11/C++14? What if metafunctions can be
// C++ functions? I decided to try it out.
//
// I decided to begin with type functions. We want functions
// which take types as arguments and return types. Here's a type
// container for these functions to operate on.
template<class T>
struct Type
{
using type = T;
};
// Let's try something easy. ptr() turns a T into a T*.
template<class T>
auto ptr(Type<T>)
{
return Type<T*>{};
}
// Let's use this to declare an int**.
void testPtr1()
{
int i{};
int* p{&i};
decltype(ptr(ptr(Type<int>{})))::type pp{&p};
assert(typeid(pp) == typeid(int**));
}
// We only "call" ptr() within decltype(); this prevents it from
// generating any runtime code, even in debug builds. This isn't
// very readable, so let's simplify the interface a bit.
static const Type<int> IntType;
#define EXTRACT_TYPE(e) decltype(e)::type
void testPtr2()
{
int i{};
int* p{&i};
EXTRACT_TYPE(ptr(ptr(IntType))) pp{&p};
assert(typeid(pp) == typeid(int**));
}
// We established an approach for defining and using a type
// function; let's see how well this works with pattern
// matching.
template<class T>
auto removeCV(Type<T>)
{
return Type<T>{};
}
template<class T>
auto removeCV(Type<const T>)
{
return Type<T>{};
}
template<class T>
auto removeCV(Type<volatile T>)
{
return Type<T>{};
}
template<class T>
auto removeCV(Type<const volatile T>)
{
return Type<T>{};
}
void testRemoveCV1()
{
EXTRACT_TYPE(ptr(removeCV(Type<int>{})))
p1{};
EXTRACT_TYPE(ptr(removeCV(Type<const int>{})))
p2{};
EXTRACT_TYPE(ptr(removeCV(Type<volatile int>{})))
p3{};
EXTRACT_TYPE(ptr(removeCV(Type<const volatile int>{})))
p4{};
EXTRACT_TYPE(ptr(Type<const volatile int>{}))
p5{};
assert(typeid(p1) == typeid(int*));
assert(typeid(p2) == typeid(int*));
assert(typeid(p3) == typeid(int*));
assert(typeid(p4) == typeid(int*));
assert(typeid(p5) == typeid(const volatile int*));
}
// That works. Let's simplify our test case a bit.
#define ASSERT_EXTRACT_TYPE(a, b) \
assert(typeid(EXTRACT_TYPE(a)) == typeid(b))
void testRemoveCV2()
{
ASSERT_EXTRACT_TYPE(
ptr(removeCV(Type<int>{})),
int*);
ASSERT_EXTRACT_TYPE(
ptr(removeCV(Type<const int>{})),
int*);
ASSERT_EXTRACT_TYPE(
ptr(removeCV(Type<volatile int>{})),
int*);
ASSERT_EXTRACT_TYPE(
ptr(removeCV(Type<const volatile int>{})),
int*);
ASSERT_EXTRACT_TYPE(
ptr(Type<const volatile int>{}),
const volatile int*);
}
// Let's try recursion. We want a function which retrieves the
// nth argument type from a function type.
template<int i>
using int_ = integral_constant<int, i>;
// Found it
template<class R, class A0, class... A>
auto argn(int_<0>, Type<R(A0, A...)>)
{
return Type<A0>{};
}
// Continue search
template<int n, class R, class A0, class... A>
auto argn(int_<n>, Type<R(A0, A...)>)
{
return argn(int_<n - 1>{}, Type<R(A...)>{});
}
void testArgn1()
{
ASSERT_EXTRACT_TYPE(
argn(int_<0>{}, Type<void(int, double, float)>{}),
int);
ASSERT_EXTRACT_TYPE(
argn(int_<1>{}, Type<void(int, double, float)>{}),
double);
ASSERT_EXTRACT_TYPE(
argn(int_<2>{}, Type<void(int, double, float)>{}),
float);
}
// argn(int_<n>{}, ...) seems a little silly; let's give it a
// nicer interface.
template<int n, class T>
auto argn(Type<T> t)
{
return argn(int_<n>{}, t);
}
void testArgn2()
{
ASSERT_EXTRACT_TYPE(
argn<0>(Type<double(int, double, float)>{}),
int);
ASSERT_EXTRACT_TYPE(
argn<1>(Type<double(int, double, float)>{}),
double);
ASSERT_EXTRACT_TYPE(
argn<2>(Type<double(int, double, float)>{}),
float);
}
// Let's try conditionals.
template<class T, class F>
auto if_(true_type, T t, F)
{
return t;
}
template<class T, class F>
auto if_(false_type, T, F f)
{
return f;
}
// demoIf's return type depends on Cond
template<class Cond>
auto demoIf(Cond c)
{
return if_(c, Type<int>{}, Type<double**>{});
}
// Let's give the compiler more work to do
template<class Cond1, class Cond2>
auto demoNestedIf(Cond1 c1, Cond2 c2)
{
return if_(c1,
if_(c2,
Type<char>{},
Type<short>{}),
if_(c2,
Type<int>{},
Type<long>{}));
}
void testIf()
{
ASSERT_EXTRACT_TYPE(demoIf(true_type{}), int);
ASSERT_EXTRACT_TYPE(demoIf(false_type{}), double**);
ASSERT_EXTRACT_TYPE(
demoNestedIf(true_type{}, true_type{}),
char);
ASSERT_EXTRACT_TYPE(
demoNestedIf(true_type{}, false_type{}),
short);
ASSERT_EXTRACT_TYPE(
demoNestedIf(false_type{}, true_type{}),
int);
ASSERT_EXTRACT_TYPE(
demoNestedIf(false_type{}, false_type{}),
long);
}
// We could try a type list at this point, but I'm feeling a bit
// ambitious. Let's try a type map.
// Each KV must be a pair. first_type and second_type must be
// default-constructable and copyable. Type<...> works well as a
// key or a value.
template<class... KV>
struct Map
{
};
// Match found
template<class K0, class V0, class... KV>
auto at(Map<pair<K0, V0>, KV...>, K0)
{
return V0{};
}
// Continue search. Generates a compiler error if K is not
// found.
template<class KV0, class... KV, class K>
auto at(Map<KV0, KV...>, K k)
{
return at(Map<KV...>{}, k);
}
void testMapAt()
{
using M = Map<
pair<int_<4>, Type<double>>,
pair<Type<int*>, Type<int>>,
pair<Type<int>, Type<int*>>>;
ASSERT_EXTRACT_TYPE(at(M{}, int_<4>{}), double);
ASSERT_EXTRACT_TYPE(at(M{}, Type<int*>{}), int);
ASSERT_EXTRACT_TYPE(at(M{}, Type<int>{}), int*);
}
// erase() takes a bit more work.
template<class KV0, class... KV1>
auto prepend(KV0, Map<KV1...>)
{
return Map<KV0, KV1...>{};
}
// Key found
template<class K0, class V0, class... KV>
auto erase(Map<pair<K0, V0>, KV...>, K0)
{
return Map<KV...>{};
}
// Continue search
template<class KV0, class... KV, class K>
auto erase(Map<KV0, KV...>, K k)
{
return prepend(KV0{}, erase(Map<KV...>{}, k));
}
// End of map
template<class K>
auto erase(Map<>, K)
{
return Map<>{};
}
void testMapErase()
{
using M = Map<
pair<int_<4>, Type<double>>,
pair<Type<int*>, Type<int>>,
pair<Type<int>, Type<int*>>>;
// key not found
assert(
typeid(erase(M{}, int_<2>{})) ==
typeid(M));
// remove row 0, 1
assert(
typeid(erase(erase(M{}, int_<4>{}), Type<int*>{})) ==
typeid(Map<pair<Type<int>, Type<int*>>>));
// remove row 0, 2
assert(
typeid(erase(erase(M{}, int_<4>{}), Type<int>{})) ==
typeid(Map<pair<Type<int*>, Type<int>>>));
// remove row 2, 1
assert(
typeid(erase(erase(M{}, Type<int>{}), Type<int*>{})) ==
typeid(Map<pair<int_<4>, Type<double>>>));
}
// I'll leave insert() as an exercise.
//
// I like how these type functions turned out; they seem a
// little less messy than the template struct approach. There's
// a lot more to template metaprogramming than just manipulating
// types; I plan to keep exploring.
int main()
{
testPtr1();
testPtr2();
testRemoveCV1();
testRemoveCV2();
testArgn1();
testArgn2();
testIf();
testMapAt();
testMapErase();
cout << "Tests passed" << endl;
}
Ly8gVHlwZSBGdW5jdGlvbnMgaW4gQysrCi8vIFRvZGQgRmxlbWluZwovLyAyMDE0LzEyLzAxCgojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8dHlwZWluZm8+CiNpbmNsdWRlIDx1dGlsaXR5PgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCi8vIEMrKyBtZXRhZnVuY3Rpb25zIG5vcm1hbGx5IGRvbid0IGxvb2sgbGlrZSBmdW5jdGlvbnMuIFdoYXQgaWYKLy8gdGhpcyBjaGFuZ2VkIHdpdGggQysrMTEvQysrMTQ/IFdoYXQgaWYgbWV0YWZ1bmN0aW9ucyBjYW4gYmUgCi8vIEMrKyBmdW5jdGlvbnM/IEkgZGVjaWRlZCB0byB0cnkgaXQgb3V0LgovLwovLyBJIGRlY2lkZWQgdG8gYmVnaW4gd2l0aCB0eXBlIGZ1bmN0aW9ucy4gV2Ugd2FudCBmdW5jdGlvbnMKLy8gd2hpY2ggdGFrZSB0eXBlcyBhcyBhcmd1bWVudHMgYW5kIHJldHVybiB0eXBlcy4gSGVyZSdzIGEgdHlwZQovLyBjb250YWluZXIgZm9yIHRoZXNlIGZ1bmN0aW9ucyB0byBvcGVyYXRlIG9uLgoKdGVtcGxhdGU8Y2xhc3MgVD4Kc3RydWN0IFR5cGUKewogICAgdXNpbmcgdHlwZSA9IFQ7Cn07CgovLyBMZXQncyB0cnkgc29tZXRoaW5nIGVhc3kuIHB0cigpIHR1cm5zIGEgVCBpbnRvIGEgVCouCgp0ZW1wbGF0ZTxjbGFzcyBUPgphdXRvIHB0cihUeXBlPFQ+KQp7CiAgICByZXR1cm4gVHlwZTxUKj57fTsKfQoKLy8gTGV0J3MgdXNlIHRoaXMgdG8gZGVjbGFyZSBhbiBpbnQqKi4KCnZvaWQgdGVzdFB0cjEoKQp7CiAgICBpbnQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl7fTsKICAgIGludCogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHsmaX07CiAgICBkZWNsdHlwZShwdHIocHRyKFR5cGU8aW50Pnt9KSkpOjp0eXBlIHBweyZwfTsKCiAgICBhc3NlcnQodHlwZWlkKHBwKSA9PSB0eXBlaWQoaW50KiopKTsKfQoKLy8gV2Ugb25seSAiY2FsbCIgcHRyKCkgd2l0aGluIGRlY2x0eXBlKCk7IHRoaXMgcHJldmVudHMgaXQgZnJvbQovLyBnZW5lcmF0aW5nIGFueSBydW50aW1lIGNvZGUsIGV2ZW4gaW4gZGVidWcgYnVpbGRzLiBUaGlzIGlzbid0Ci8vIHZlcnkgcmVhZGFibGUsIHNvIGxldCdzIHNpbXBsaWZ5IHRoZSBpbnRlcmZhY2UgYSBiaXQuCgpzdGF0aWMgY29uc3QgVHlwZTxpbnQ+IEludFR5cGU7CgojZGVmaW5lIEVYVFJBQ1RfVFlQRShlKSBkZWNsdHlwZShlKTo6dHlwZQoKdm9pZCB0ZXN0UHRyMigpCnsKICAgIGludCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXt9OwogICAgaW50KiAgICAgICAgICAgICAgICAgICAgICAgICAgICBweyZpfTsKICAgIEVYVFJBQ1RfVFlQRShwdHIocHRyKEludFR5cGUpKSkgcHB7JnB9OwoKICAgIGFzc2VydCh0eXBlaWQocHApID09IHR5cGVpZChpbnQqKikpOwp9CgovLyBXZSBlc3RhYmxpc2hlZCBhbiBhcHByb2FjaCBmb3IgZGVmaW5pbmcgYW5kIHVzaW5nIGEgdHlwZQovLyBmdW5jdGlvbjsgbGV0J3Mgc2VlIGhvdyB3ZWxsIHRoaXMgd29ya3Mgd2l0aCBwYXR0ZXJuCi8vIG1hdGNoaW5nLgoKdGVtcGxhdGU8Y2xhc3MgVD4KYXV0byByZW1vdmVDVihUeXBlPFQ+KQp7CiAgICByZXR1cm4gVHlwZTxUPnt9Owp9Cgp0ZW1wbGF0ZTxjbGFzcyBUPgphdXRvIHJlbW92ZUNWKFR5cGU8Y29uc3QgVD4pCnsKICAgIHJldHVybiBUeXBlPFQ+e307Cn0KCnRlbXBsYXRlPGNsYXNzIFQ+CmF1dG8gcmVtb3ZlQ1YoVHlwZTx2b2xhdGlsZSBUPikKewogICAgcmV0dXJuIFR5cGU8VD57fTsKfQoKdGVtcGxhdGU8Y2xhc3MgVD4KYXV0byByZW1vdmVDVihUeXBlPGNvbnN0IHZvbGF0aWxlIFQ+KQp7CiAgICByZXR1cm4gVHlwZTxUPnt9Owp9Cgp2b2lkIHRlc3RSZW1vdmVDVjEoKQp7CiAgICBFWFRSQUNUX1RZUEUocHRyKHJlbW92ZUNWKFR5cGU8aW50Pnt9KSkpCiAgICAgICAgcDF7fTsKICAgIEVYVFJBQ1RfVFlQRShwdHIocmVtb3ZlQ1YoVHlwZTxjb25zdCBpbnQ+e30pKSkKICAgICAgICBwMnt9OwogICAgRVhUUkFDVF9UWVBFKHB0cihyZW1vdmVDVihUeXBlPHZvbGF0aWxlIGludD57fSkpKQogICAgICAgIHAze307CiAgICBFWFRSQUNUX1RZUEUocHRyKHJlbW92ZUNWKFR5cGU8Y29uc3Qgdm9sYXRpbGUgaW50Pnt9KSkpCiAgICAgICAgcDR7fTsKICAgIEVYVFJBQ1RfVFlQRShwdHIoVHlwZTxjb25zdCB2b2xhdGlsZSBpbnQ+e30pKQogICAgICAgIHA1e307CgogICAgYXNzZXJ0KHR5cGVpZChwMSkgPT0gdHlwZWlkKGludCopKTsKICAgIGFzc2VydCh0eXBlaWQocDIpID09IHR5cGVpZChpbnQqKSk7CiAgICBhc3NlcnQodHlwZWlkKHAzKSA9PSB0eXBlaWQoaW50KikpOwogICAgYXNzZXJ0KHR5cGVpZChwNCkgPT0gdHlwZWlkKGludCopKTsKICAgIGFzc2VydCh0eXBlaWQocDUpID09IHR5cGVpZChjb25zdCB2b2xhdGlsZSBpbnQqKSk7Cn0KCi8vIFRoYXQgd29ya3MuIExldCdzIHNpbXBsaWZ5IG91ciB0ZXN0IGNhc2UgYSBiaXQuCgojZGVmaW5lIEFTU0VSVF9FWFRSQUNUX1RZUEUoYSwgYikgXAogICAgYXNzZXJ0KHR5cGVpZChFWFRSQUNUX1RZUEUoYSkpID09IHR5cGVpZChiKSkKCnZvaWQgdGVzdFJlbW92ZUNWMigpCnsKICAgIEFTU0VSVF9FWFRSQUNUX1RZUEUoCiAgICAgICAgcHRyKHJlbW92ZUNWKFR5cGU8aW50Pnt9KSksCiAgICAgICAgaW50Kik7CiAgICBBU1NFUlRfRVhUUkFDVF9UWVBFKAogICAgICAgIHB0cihyZW1vdmVDVihUeXBlPGNvbnN0IGludD57fSkpLAogICAgICAgIGludCopOwogICAgQVNTRVJUX0VYVFJBQ1RfVFlQRSgKICAgICAgICBwdHIocmVtb3ZlQ1YoVHlwZTx2b2xhdGlsZSBpbnQ+e30pKSwKICAgICAgICBpbnQqKTsKICAgIEFTU0VSVF9FWFRSQUNUX1RZUEUoCiAgICAgICAgcHRyKHJlbW92ZUNWKFR5cGU8Y29uc3Qgdm9sYXRpbGUgaW50Pnt9KSksCiAgICAgICAgaW50Kik7CiAgICBBU1NFUlRfRVhUUkFDVF9UWVBFKAogICAgICAgIHB0cihUeXBlPGNvbnN0IHZvbGF0aWxlIGludD57fSksCiAgICAgICAgY29uc3Qgdm9sYXRpbGUgaW50Kik7Cn0KCi8vIExldCdzIHRyeSByZWN1cnNpb24uIFdlIHdhbnQgYSBmdW5jdGlvbiB3aGljaCByZXRyaWV2ZXMgdGhlCi8vIG50aCBhcmd1bWVudCB0eXBlIGZyb20gYSBmdW5jdGlvbiB0eXBlLgoKdGVtcGxhdGU8aW50IGk+CnVzaW5nIGludF8gPSBpbnRlZ3JhbF9jb25zdGFudDxpbnQsIGk+OwoKLy8gRm91bmQgaXQKdGVtcGxhdGU8Y2xhc3MgUiwgY2xhc3MgQTAsIGNsYXNzLi4uIEE+CmF1dG8gYXJnbihpbnRfPDA+LCBUeXBlPFIoQTAsIEEuLi4pPikKewogICAgcmV0dXJuIFR5cGU8QTA+e307Cn0KCi8vIENvbnRpbnVlIHNlYXJjaAp0ZW1wbGF0ZTxpbnQgbiwgY2xhc3MgUiwgY2xhc3MgQTAsIGNsYXNzLi4uIEE+CmF1dG8gYXJnbihpbnRfPG4+LCBUeXBlPFIoQTAsIEEuLi4pPikKewogICAgcmV0dXJuIGFyZ24oaW50XzxuIC0gMT57fSwgVHlwZTxSKEEuLi4pPnt9KTsKfQoKdm9pZCB0ZXN0QXJnbjEoKQp7CiAgICBBU1NFUlRfRVhUUkFDVF9UWVBFKAogICAgICAgIGFyZ24oaW50XzwwPnt9LCBUeXBlPHZvaWQoaW50LCBkb3VibGUsIGZsb2F0KT57fSksCiAgICAgICAgaW50KTsKICAgIEFTU0VSVF9FWFRSQUNUX1RZUEUoCiAgICAgICAgYXJnbihpbnRfPDE+e30sIFR5cGU8dm9pZChpbnQsIGRvdWJsZSwgZmxvYXQpPnt9KSwKICAgICAgICBkb3VibGUpOwogICAgQVNTRVJUX0VYVFJBQ1RfVFlQRSgKICAgICAgICBhcmduKGludF88Mj57fSwgVHlwZTx2b2lkKGludCwgZG91YmxlLCBmbG9hdCk+e30pLAogICAgICAgIGZsb2F0KTsKfQoKLy8gYXJnbihpbnRfPG4+e30sIC4uLikgc2VlbXMgYSBsaXR0bGUgc2lsbHk7IGxldCdzIGdpdmUgaXQgYQovLyBuaWNlciBpbnRlcmZhY2UuCgp0ZW1wbGF0ZTxpbnQgbiwgY2xhc3MgVD4KYXV0byBhcmduKFR5cGU8VD4gdCkKewogICAgcmV0dXJuIGFyZ24oaW50XzxuPnt9LCB0KTsKfQoKdm9pZCB0ZXN0QXJnbjIoKQp7CiAgICBBU1NFUlRfRVhUUkFDVF9UWVBFKAogICAgICAgIGFyZ248MD4oVHlwZTxkb3VibGUoaW50LCBkb3VibGUsIGZsb2F0KT57fSksIAogICAgICAgIGludCk7CiAgICBBU1NFUlRfRVhUUkFDVF9UWVBFKAogICAgICAgIGFyZ248MT4oVHlwZTxkb3VibGUoaW50LCBkb3VibGUsIGZsb2F0KT57fSksIAogICAgICAgIGRvdWJsZSk7CiAgICBBU1NFUlRfRVhUUkFDVF9UWVBFKAogICAgICAgIGFyZ248Mj4oVHlwZTxkb3VibGUoaW50LCBkb3VibGUsIGZsb2F0KT57fSksIAogICAgICAgIGZsb2F0KTsKfQoKLy8gTGV0J3MgdHJ5IGNvbmRpdGlvbmFscy4KCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIEY+CmF1dG8gaWZfKHRydWVfdHlwZSwgVCB0LCBGKQp7CiAgICByZXR1cm4gdDsKfQoKdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgRj4KYXV0byBpZl8oZmFsc2VfdHlwZSwgVCwgRiBmKQp7CiAgICByZXR1cm4gZjsKfQoKLy8gZGVtb0lmJ3MgcmV0dXJuIHR5cGUgZGVwZW5kcyBvbiBDb25kCnRlbXBsYXRlPGNsYXNzIENvbmQ+CmF1dG8gZGVtb0lmKENvbmQgYykKewogICAgcmV0dXJuIGlmXyhjLCBUeXBlPGludD57fSwgVHlwZTxkb3VibGUqKj57fSk7Cn0KCi8vIExldCdzIGdpdmUgdGhlIGNvbXBpbGVyIG1vcmUgd29yayB0byBkbwp0ZW1wbGF0ZTxjbGFzcyBDb25kMSwgY2xhc3MgQ29uZDI+CmF1dG8gZGVtb05lc3RlZElmKENvbmQxIGMxLCBDb25kMiBjMikKewogICAgcmV0dXJuIGlmXyhjMSwKICAgICAgICBpZl8oYzIsCiAgICAgICAgICAgIFR5cGU8Y2hhcj57fSwKICAgICAgICAgICAgVHlwZTxzaG9ydD57fSksCiAgICAgICAgaWZfKGMyLAogICAgICAgICAgICBUeXBlPGludD57fSwKICAgICAgICAgICAgVHlwZTxsb25nPnt9KSk7Cn0KCnZvaWQgdGVzdElmKCkKewogICAgQVNTRVJUX0VYVFJBQ1RfVFlQRShkZW1vSWYodHJ1ZV90eXBle30pLCAgaW50KTsKICAgIEFTU0VSVF9FWFRSQUNUX1RZUEUoZGVtb0lmKGZhbHNlX3R5cGV7fSksIGRvdWJsZSoqKTsKCiAgICBBU1NFUlRfRVhUUkFDVF9UWVBFKAogICAgICAgIGRlbW9OZXN0ZWRJZih0cnVlX3R5cGV7fSwgIHRydWVfdHlwZXt9KSwKICAgICAgICBjaGFyKTsKICAgIEFTU0VSVF9FWFRSQUNUX1RZUEUoCiAgICAgICAgZGVtb05lc3RlZElmKHRydWVfdHlwZXt9LCAgZmFsc2VfdHlwZXt9KSwKICAgICAgICBzaG9ydCk7CiAgICBBU1NFUlRfRVhUUkFDVF9UWVBFKAogICAgICAgIGRlbW9OZXN0ZWRJZihmYWxzZV90eXBle30sIHRydWVfdHlwZXt9KSwKICAgICAgICBpbnQpOwogICAgQVNTRVJUX0VYVFJBQ1RfVFlQRSgKICAgICAgICBkZW1vTmVzdGVkSWYoZmFsc2VfdHlwZXt9LCBmYWxzZV90eXBle30pLAogICAgICAgIGxvbmcpOwp9CgovLyBXZSBjb3VsZCB0cnkgYSB0eXBlIGxpc3QgYXQgdGhpcyBwb2ludCwgYnV0IEknbSBmZWVsaW5nIGEgYml0Ci8vIGFtYml0aW91cy4gTGV0J3MgdHJ5IGEgdHlwZSBtYXAuCgovLyBFYWNoIEtWIG11c3QgYmUgYSBwYWlyLiBmaXJzdF90eXBlIGFuZCBzZWNvbmRfdHlwZSBtdXN0IGJlCi8vIGRlZmF1bHQtY29uc3RydWN0YWJsZSBhbmQgY29weWFibGUuIFR5cGU8Li4uPiB3b3JrcyB3ZWxsIGFzIGEKLy8ga2V5IG9yIGEgdmFsdWUuCnRlbXBsYXRlPGNsYXNzLi4uIEtWPgpzdHJ1Y3QgTWFwCnsKfTsKCi8vIE1hdGNoIGZvdW5kCnRlbXBsYXRlPGNsYXNzIEswLCBjbGFzcyBWMCwgY2xhc3MuLi4gS1Y+CmF1dG8gYXQoTWFwPHBhaXI8SzAsIFYwPiwgS1YuLi4+LCBLMCkKewogICAgcmV0dXJuIFYwe307Cn0KCi8vIENvbnRpbnVlIHNlYXJjaC4gR2VuZXJhdGVzIGEgY29tcGlsZXIgZXJyb3IgaWYgSyBpcyBub3QKLy8gZm91bmQuCnRlbXBsYXRlPGNsYXNzIEtWMCwgY2xhc3MuLi4gS1YsIGNsYXNzIEs+CmF1dG8gYXQoTWFwPEtWMCwgS1YuLi4+LCBLIGspCnsKICAgIHJldHVybiBhdChNYXA8S1YuLi4+e30sIGspOwp9Cgp2b2lkIHRlc3RNYXBBdCgpCnsKICAgIHVzaW5nIE0gPSBNYXA8CiAgICAgICAgcGFpcjxpbnRfPDQ+LCAgICBUeXBlPGRvdWJsZT4+LAogICAgICAgIHBhaXI8VHlwZTxpbnQqPiwgVHlwZTxpbnQ+PiwKICAgICAgICBwYWlyPFR5cGU8aW50PiwgIFR5cGU8aW50Kj4+PjsKCiAgICBBU1NFUlRfRVhUUkFDVF9UWVBFKGF0KE17fSwgaW50Xzw0Pnt9KSwgICAgZG91YmxlKTsKICAgIEFTU0VSVF9FWFRSQUNUX1RZUEUoYXQoTXt9LCBUeXBlPGludCo+e30pLCBpbnQpOwogICAgQVNTRVJUX0VYVFJBQ1RfVFlQRShhdChNe30sIFR5cGU8aW50Pnt9KSwgIGludCopOwp9CgovLyBlcmFzZSgpIHRha2VzIGEgYml0IG1vcmUgd29yay4KCnRlbXBsYXRlPGNsYXNzIEtWMCwgY2xhc3MuLi4gS1YxPgphdXRvIHByZXBlbmQoS1YwLCBNYXA8S1YxLi4uPikKewogICAgcmV0dXJuIE1hcDxLVjAsIEtWMS4uLj57fTsKfQoKLy8gS2V5IGZvdW5kCnRlbXBsYXRlPGNsYXNzIEswLCBjbGFzcyBWMCwgY2xhc3MuLi4gS1Y+CmF1dG8gZXJhc2UoTWFwPHBhaXI8SzAsIFYwPiwgS1YuLi4+LCBLMCkKewogICAgcmV0dXJuIE1hcDxLVi4uLj57fTsKfQoKLy8gQ29udGludWUgc2VhcmNoCnRlbXBsYXRlPGNsYXNzIEtWMCwgY2xhc3MuLi4gS1YsIGNsYXNzIEs+CmF1dG8gZXJhc2UoTWFwPEtWMCwgS1YuLi4+LCBLIGspCnsKICAgIHJldHVybiBwcmVwZW5kKEtWMHt9LCBlcmFzZShNYXA8S1YuLi4+e30sIGspKTsKfQoKLy8gRW5kIG9mIG1hcAp0ZW1wbGF0ZTxjbGFzcyBLPgphdXRvIGVyYXNlKE1hcDw+LCBLKQp7CiAgICByZXR1cm4gTWFwPD57fTsKfQoKdm9pZCB0ZXN0TWFwRXJhc2UoKQp7CiAgICB1c2luZyBNID0gTWFwPAogICAgICAgIHBhaXI8aW50Xzw0PiwgVHlwZTxkb3VibGU+PiwKICAgICAgICBwYWlyPFR5cGU8aW50Kj4sIFR5cGU8aW50Pj4sCiAgICAgICAgcGFpcjxUeXBlPGludD4sIFR5cGU8aW50Kj4+PjsKCiAgICAvLyBrZXkgbm90IGZvdW5kCiAgICBhc3NlcnQoCiAgICAgICAgdHlwZWlkKGVyYXNlKE17fSwgaW50XzwyPnt9KSkgPT0KICAgICAgICB0eXBlaWQoTSkpOwoKICAgIC8vIHJlbW92ZSByb3cgMCwgMQogICAgYXNzZXJ0KAogICAgICAgIHR5cGVpZChlcmFzZShlcmFzZShNe30sIGludF88ND57fSksIFR5cGU8aW50Kj57fSkpID09CiAgICAgICAgdHlwZWlkKE1hcDxwYWlyPFR5cGU8aW50PiwgVHlwZTxpbnQqPj4+KSk7CgogICAgLy8gcmVtb3ZlIHJvdyAwLCAyCiAgICBhc3NlcnQoCiAgICAgICAgdHlwZWlkKGVyYXNlKGVyYXNlKE17fSwgaW50Xzw0Pnt9KSwgVHlwZTxpbnQ+e30pKSA9PQogICAgICAgIHR5cGVpZChNYXA8cGFpcjxUeXBlPGludCo+LCBUeXBlPGludD4+PikpOwoKICAgIC8vIHJlbW92ZSByb3cgMiwgMQogICAgYXNzZXJ0KAogICAgICAgIHR5cGVpZChlcmFzZShlcmFzZShNe30sIFR5cGU8aW50Pnt9KSwgVHlwZTxpbnQqPnt9KSkgPT0KICAgICAgICB0eXBlaWQoTWFwPHBhaXI8aW50Xzw0PiwgVHlwZTxkb3VibGU+Pj4pKTsKfQoKLy8gSSdsbCBsZWF2ZSBpbnNlcnQoKSBhcyBhbiBleGVyY2lzZS4KLy8KLy8gSSBsaWtlIGhvdyB0aGVzZSB0eXBlIGZ1bmN0aW9ucyB0dXJuZWQgb3V0OyB0aGV5IHNlZW0gYQovLyBsaXR0bGUgbGVzcyBtZXNzeSB0aGFuIHRoZSB0ZW1wbGF0ZSBzdHJ1Y3QgYXBwcm9hY2guIFRoZXJlJ3MgCi8vIGEgbG90IG1vcmUgdG8gdGVtcGxhdGUgbWV0YXByb2dyYW1taW5nIHRoYW4ganVzdCBtYW5pcHVsYXRpbmcKLy8gdHlwZXM7IEkgcGxhbiB0byBrZWVwIGV4cGxvcmluZy4KCmludCBtYWluKCkKewogICAgdGVzdFB0cjEoKTsKICAgIHRlc3RQdHIyKCk7CiAgICB0ZXN0UmVtb3ZlQ1YxKCk7CiAgICB0ZXN0UmVtb3ZlQ1YyKCk7CiAgICB0ZXN0QXJnbjEoKTsKICAgIHRlc3RBcmduMigpOwogICAgdGVzdElmKCk7CiAgICB0ZXN0TWFwQXQoKTsKICAgIHRlc3RNYXBFcmFzZSgpOwoKICAgIGNvdXQgPDwgIlRlc3RzIHBhc3NlZCIgPDwgZW5kbDsKfQo=