#import<arpa/inet.h>
using u=uint8_t;using U=uint32_t;U i,o,x,b,m,z=65536;U R(u*&p){if(m=i)x=i<3?*p++<<8|*p++:i<4?*p++|*p++<<8:(x=*(U*)p,p+=4,i<6?htonl(x):x);else{for(x=*p++;128>>m&x;)++m;if(m>1)for(x&=127>>m;--m;)x=(*p&192)-128?~0:*p++&63|x<<6;m?x=~0:0;}return x;}U r(u*&p){U y=R(p);x=i&&i<4&x>>10==54?R(p)>>10==55?y*1024+x-56613888:~0:x;b++?:x-65279?x==z-2&i==1?i=3,r(p):x+z+z|i-4||(i=6,r(p)):i&&i%3-1?x=~0:r(p);return x<z*17&x>>11!=27?x:~0;}void w(U x,u*&p){if(o)o<4?x/z?x-=z,w(55296|x>>10,p),w(56320|x&1023,p),0:o<3?*p++=x>>8,*p++=x:(*p++=x,*p++=x>>8):*(*(U*)p=o<6?htonl(x):x,p+=4);else if(x<128)*p++=x;else{for(m=0;~63<<m&x;m+=6);for(*p++=~127>>m/6|x>>m;m;*p++=128|x>>m&63)m-=6;}}U t(u*p,u*&q){for(b=0,x=1;x;)w(r(p),q);return x;}
#include <vector>
#include <iostream>
std::ostream& operator<<(std::ostream& out, const std::vector<u>& v)
{
out << "{ ";
for (int i: v) out << i << " ";
out << "}";
return out;
}
int test_read(int encoding, std::vector<u> input, U expected)
{
b = 0;
i = encoding;
auto d = input.data();
U actual = r(d);
if (actual == expected) return 0;
std::cerr << std::hex << "Decoding " << encoding << "; " << input << " gave " << actual
<< " instead of " << expected << std::endl;
return 1;
}
int test_write(int encoding, U input, std::vector<u> expected)
{
o = encoding;
u buf[20], *p = buf;
w(input, p);
std::vector<u> actual(buf,p);
if (expected == actual) return 0;
std::cerr << std::hex << "Encoding " << encoding << "; " << input << " gave " << actual
<< " instead of " << expected << std::endl;
return 1;
}
int test_transcode(int ienc, std::vector<u> input, int oenc, std::vector<u> expected)
{
b = 0;
i = ienc; o = oenc;
u buf[200], *p = buf, *d = input.data();
int result = t(d, p);
std::vector<u> actual(buf,p);
if (result ? expected.empty() : expected == actual) return 0;
std::cerr << std::hex << "Encoding " << ienc << " to " << oenc << "; " << input << " gave " << actual
<< " instead of " << expected << std::endl;
return 1;
}
static const U FAIL = ~0;
int main() {
int e = 0; // error count
// UTF-8
e += test_read(0, { 128 }, FAIL); // unexpected continuation
e += test_read(0, { 128, 1 }, FAIL);
e += test_read(0, { 128, 128 }, FAIL);
e += test_read(0, { 192, 192 }, FAIL); // start without continuation
e += test_read(0, { 192, 0 }, FAIL);
e += test_read(0, { 224, 0 }, FAIL);
e += test_read(0, { 224, 192 }, FAIL);
e += test_read(0, { 0xf4, 0x90, 128, 128 }, FAIL); // Unicode maximum+1
e += test_read(0, { 127 }, 127);
e += test_read(0, { 192, 129 }, 1); // We accept overlong UTF-8
e += test_read(0, { 0xc2, 128 }, 128);
e += test_read(0, { 224, 128, 129 }, 1);
e += test_read(0, { 0xef, 128, 128 }, 0xF000);
e += test_read(0, { 0xef, 191, 191 }, 0xFFFF);
e += test_read(0, { 0xf4, 128, 128, 128 }, 0x100000);
e += test_read(0, { 0xf4, 0x8f, 191, 191 }, 0x10FFFF); // Unicode maximum
e += test_read(0, { 0xEF, 0xBB, 0xBF, 127 }, 127); // byte-order mark
e += test_write(0, 0, { 0 });
e += test_write(0, 127, { 127 });
e += test_write(0, 128, { 0xc2, 128 });
e += test_write(0, 255, { 0xc3, 191 });
e += test_write(0, 0xFFFF, { 0xef, 191, 191 });
e += test_write(0, 0x10FFFF, { 0xf4, 0x8f, 191, 191 });
// UTF-16
e += test_read(1, { 0, 1 }, 1);
e += test_read(1, { 0xd8, 0, 0xdc, 1 }, 0x10001);
e += test_read(1, { 0xdb, 0xff, 0xdf, 0xff }, 0x10ffff);
e += test_read(1, { 0xd8, 0, 0xd8, 1 }, FAIL); // mismatched surrogate
e += test_read(1, { 0xd8, 0, 0, 1 }, FAIL); // mismatched surrogate
e += test_read(1, { 0xdc, 0 }, FAIL);
e += test_write(1, 1, { 0, 1 });
e += test_write(1, 256, { 1, 0 });
e += test_write(1, 0xffff, { 255, 255 });
e += test_write(1, 0x10001, { 0xd8, 0, 0xdc, 1 });
e += test_write(1, 0x10ffff, { 0xdb, 0xff, 0xdf, 0xff });
// UTF-16LE
e += test_write(3, 1, { 1, 0 });
e += test_write(3, 256, { 0, 1 });
e += test_write(3, 0x10001, { 0, 0xd8, 1, 0xdc });
e += test_write(3, 0x10fffe, { 0xff, 0xdb, 0xfe, 0xdf });
// UTF-16 byte-order mark
e += test_read(1, { 0xFE, 0xFF, 0x0, 1 }, 1); // byte-order mark
e += test_read(1, { 0xFF, 0xFE, 1, 0x0 }, 1); // reversed byte-order mark
// disallowed byte-order marks
e += test_read(2, { 0xFE, 0xFF }, FAIL);
e += test_read(3, { 0xFF, 0xFE }, FAIL);
// reversed byte-order mark is an unassigned character - to be treated like regular character, according to question
e += test_read(2, { 0xFF, 0xFE }, 0xfffe);
e += test_read(3, { 0xFE, 0xFF }, 0xfffe);
// UTF-32
e += test_read(4, { 0, 0, 0, 1 }, 1);
e += test_read(4, { 1, 0, 0, 0 }, FAIL);
e += test_write(4, 1, { 0, 0, 0, 1 });
e += test_write(4, 0x10203, { 0, 1, 2, 3 });
// UTF-32LE
e += test_read(6, { 0, 0, 0, 1 }, FAIL);
e += test_read(6, { 1, 0, 0, 0 }, 1);
// UTF-32 byte-order mark
e += test_read(4, { 0, 0, 0xFE, 0xFF, 0, 0, 0, 1 }, 1); // byte-order mark
e += test_read(4, { 0xFF, 0xFE, 0, 0, 1, 0, 0, 0 }, 1); // reversed byte-order mark
// disallowed byte-order marks
e += test_read(5, { 0, 0, 0xFE, 0xFF }, FAIL);
e += test_read(5, { 0xFF, 0xFE, 0, 0 }, FAIL);
e += test_read(6, { 0, 0, 0xFE, 0xFF }, FAIL);
e += test_read(6, { 0xFF, 0xFE, 0, 0 }, FAIL);
e += test_transcode(1, { 1, 2, 0xFE, 0xFF, 0, 0 }, // That's not a BOM; it's a zwnj when not the first char
1, { 1, 2, 0xFE, 0xFF, 0, 0 });
e += test_transcode(1, { 0xFF, 0xFE, 1, 2, 0, 0 }, // reversed byte-order mark implies little-endian
1, { 2, 1, 0, 0 });
e += test_transcode(4, { 0xFF, 0xFE, 0, 0, 1, 2, 0, 0, 0, 0 }, // reversed BOM means little-endian
4, { 0, 0, 2, 1, 0, 0, 0, 0 });
e += test_transcode(1, { 0xdb, 0xff, 0xdf, 0xff, 0, 0 }, // U+10ffff UTF-16 to UTF-8
0, { 0xf4, 0x8f, 191, 191, 0 });
return e;
}
I2ltcG9ydDxhcnBhL2luZXQuaD4KdXNpbmcgdT11aW50OF90O3VzaW5nIFU9dWludDMyX3Q7VSBpLG8seCxiLG0sej02NTUzNjtVIFIodSomcCl7aWYobT1pKXg9aTwzPypwKys8PDh8KnArKzppPDQ/KnArK3wqcCsrPDw4Oih4PSooVSopcCxwKz00LGk8Nj9odG9ubCh4KTp4KTtlbHNle2Zvcih4PSpwKys7MTI4Pj5tJng7KSsrbTtpZihtPjEpZm9yKHgmPTEyNz4+bTstLW07KXg9KCpwJjE5MiktMTI4P34wOipwKysmNjN8eDw8NjttP3g9fjA6MDt9cmV0dXJuIHg7fVUgcih1KiZwKXtVIHk9UihwKTt4PWkmJmk8NCZ4Pj4xMD09NTQ/UihwKT4+MTA9PTU1P3kqMTAyNCt4LTU2NjEzODg4On4wOng7YisrPzp4LTY1Mjc5P3g9PXotMiZpPT0xP2k9MyxyKHApOngreit6fGktNHx8KGk9NixyKHApKTppJiZpJTMtMT94PX4wOnIocCk7cmV0dXJuIHg8eioxNyZ4Pj4xMSE9Mjc/eDp+MDt9dm9pZCB3KFUgeCx1KiZwKXtpZihvKW88ND94L3o/eC09eix3KDU1Mjk2fHg+PjEwLHApLHcoNTYzMjB8eCYxMDIzLHApLDA6bzwzPypwKys9eD4+OCwqcCsrPXg6KCpwKys9eCwqcCsrPXg+PjgpOiooKihVKilwPW88Nj9odG9ubCh4KTp4LHArPTQpO2Vsc2UgaWYoeDwxMjgpKnArKz14O2Vsc2V7Zm9yKG09MDt+NjM8PG0meDttKz02KTtmb3IoKnArKz1+MTI3Pj5tLzZ8eD4+bTttOypwKys9MTI4fHg+Pm0mNjMpbS09Njt9fVUgdCh1KnAsdSomcSl7Zm9yKGI9MCx4PTE7eDspdyhyKHApLHEpO3JldHVybiB4O30KCiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnN0ZDo6b3N0cmVhbSYgb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0mIG91dCwgY29uc3Qgc3RkOjp2ZWN0b3I8dT4mIHYpCnsKICAgIG91dCA8PCAieyAiOwogICAgZm9yIChpbnQgaTogdikgb3V0IDw8IGkgPDwgIiAiOwogICAgb3V0IDw8ICJ9IjsKICAgIHJldHVybiBvdXQ7Cn0KCmludCB0ZXN0X3JlYWQoaW50IGVuY29kaW5nLCBzdGQ6OnZlY3Rvcjx1PiBpbnB1dCwgVSBleHBlY3RlZCkKewogICAgYiA9IDA7CiAgICBpID0gZW5jb2Rpbmc7CiAgICBhdXRvIGQgPSBpbnB1dC5kYXRhKCk7CiAgICBVIGFjdHVhbCA9IHIoZCk7CiAgICBpZiAoYWN0dWFsID09IGV4cGVjdGVkKSByZXR1cm4gMDsKICAgIHN0ZDo6Y2VyciA8PCBzdGQ6OmhleCA8PCAiRGVjb2RpbmcgIiA8PCBlbmNvZGluZyA8PCAiOyAiIDw8IGlucHV0IDw8ICIgZ2F2ZSAiIDw8IGFjdHVhbAogICAgICAgICAgICAgIDw8ICIgaW5zdGVhZCBvZiAiIDw8IGV4cGVjdGVkIDw8IHN0ZDo6ZW5kbDsKICAgIHJldHVybiAxOwp9CgppbnQgdGVzdF93cml0ZShpbnQgZW5jb2RpbmcsIFUgaW5wdXQsIHN0ZDo6dmVjdG9yPHU+IGV4cGVjdGVkKQp7CiAgICBvID0gZW5jb2Rpbmc7CiAgICB1IGJ1ZlsyMF0sICpwID0gYnVmOwogICAgdyhpbnB1dCwgcCk7CiAgICBzdGQ6OnZlY3Rvcjx1PiBhY3R1YWwoYnVmLHApOwogICAgaWYgKGV4cGVjdGVkID09IGFjdHVhbCkgcmV0dXJuIDA7CiAgICBzdGQ6OmNlcnIgPDwgc3RkOjpoZXggPDwgIkVuY29kaW5nICIgPDwgZW5jb2RpbmcgPDwgIjsgIiA8PCBpbnB1dCA8PCAiIGdhdmUgIiA8PCBhY3R1YWwKICAgICAgICAgICAgICA8PCAiIGluc3RlYWQgb2YgIiA8PCBleHBlY3RlZCA8PCBzdGQ6OmVuZGw7CiAgICByZXR1cm4gMTsKfQoKaW50IHRlc3RfdHJhbnNjb2RlKGludCBpZW5jLCBzdGQ6OnZlY3Rvcjx1PiBpbnB1dCwgaW50IG9lbmMsIHN0ZDo6dmVjdG9yPHU+IGV4cGVjdGVkKQp7CiAgICBiID0gMDsKICAgIGkgPSBpZW5jOyBvID0gb2VuYzsKICAgIHUgYnVmWzIwMF0sICpwID0gYnVmLCAqZCA9IGlucHV0LmRhdGEoKTsKICAgIGludCByZXN1bHQgPSB0KGQsIHApOwogICAgc3RkOjp2ZWN0b3I8dT4gYWN0dWFsKGJ1ZixwKTsKICAgIGlmIChyZXN1bHQgPyBleHBlY3RlZC5lbXB0eSgpIDogZXhwZWN0ZWQgPT0gYWN0dWFsKSByZXR1cm4gMDsKICAgIHN0ZDo6Y2VyciA8PCBzdGQ6OmhleCA8PCAiRW5jb2RpbmcgIiA8PCBpZW5jIDw8ICIgdG8gIiA8PCBvZW5jIDw8ICI7ICIgPDwgaW5wdXQgPDwgIiBnYXZlICIgPDwgYWN0dWFsCiAgICAgICAgICAgICAgPDwgIiBpbnN0ZWFkIG9mICIgPDwgZXhwZWN0ZWQgPDwgc3RkOjplbmRsOwogICAgcmV0dXJuIDE7Cn0KCnN0YXRpYyBjb25zdCBVIEZBSUwgPSB+MDsKaW50IG1haW4oKSB7CiAgICBpbnQgZSA9IDA7ICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXJyb3IgY291bnQKICAgIC8vIFVURi04CiAgICBlICs9IHRlc3RfcmVhZCgwLCB7IDEyOCB9LCBGQUlMKTsgLy8gdW5leHBlY3RlZCBjb250aW51YXRpb24KICAgIGUgKz0gdGVzdF9yZWFkKDAsIHsgMTI4LCAxIH0sIEZBSUwpOwogICAgZSArPSB0ZXN0X3JlYWQoMCwgeyAxMjgsIDEyOCB9LCBGQUlMKTsKICAgIGUgKz0gdGVzdF9yZWFkKDAsIHsgMTkyLCAxOTIgfSwgRkFJTCk7IC8vIHN0YXJ0IHdpdGhvdXQgY29udGludWF0aW9uCiAgICBlICs9IHRlc3RfcmVhZCgwLCB7IDE5MiwgMCB9LCBGQUlMKTsKICAgIGUgKz0gdGVzdF9yZWFkKDAsIHsgMjI0LCAwIH0sIEZBSUwpOwogICAgZSArPSB0ZXN0X3JlYWQoMCwgeyAyMjQsIDE5MiB9LCBGQUlMKTsKICAgIGUgKz0gdGVzdF9yZWFkKDAsIHsgMHhmNCwgMHg5MCwgMTI4LCAxMjggfSwgRkFJTCk7IC8vIFVuaWNvZGUgbWF4aW11bSsxCgogICAgZSArPSB0ZXN0X3JlYWQoMCwgeyAxMjcgfSwgMTI3KTsKICAgIGUgKz0gdGVzdF9yZWFkKDAsIHsgMTkyLCAxMjkgfSwgMSk7IC8vIFdlIGFjY2VwdCBvdmVybG9uZyBVVEYtOAogICAgZSArPSB0ZXN0X3JlYWQoMCwgeyAweGMyLCAxMjggfSwgMTI4KTsKICAgIGUgKz0gdGVzdF9yZWFkKDAsIHsgMjI0LCAxMjgsIDEyOSB9LCAxKTsKICAgIGUgKz0gdGVzdF9yZWFkKDAsIHsgMHhlZiwgMTI4LCAxMjggfSwgMHhGMDAwKTsKICAgIGUgKz0gdGVzdF9yZWFkKDAsIHsgMHhlZiwgMTkxLCAxOTEgfSwgMHhGRkZGKTsKICAgIGUgKz0gdGVzdF9yZWFkKDAsIHsgMHhmNCwgMTI4LCAxMjgsIDEyOCB9LCAweDEwMDAwMCk7CiAgICBlICs9IHRlc3RfcmVhZCgwLCB7IDB4ZjQsIDB4OGYsIDE5MSwgMTkxIH0sIDB4MTBGRkZGKTsgLy8gVW5pY29kZSBtYXhpbXVtCgogICAgZSArPSB0ZXN0X3JlYWQoMCwgeyAweEVGLCAweEJCLCAweEJGLCAxMjcgfSwgMTI3KTsgLy8gYnl0ZS1vcmRlciBtYXJrCgogICAgZSArPSB0ZXN0X3dyaXRlKDAsIDAsIHsgMCB9KTsKICAgIGUgKz0gdGVzdF93cml0ZSgwLCAxMjcsIHsgMTI3IH0pOwogICAgZSArPSB0ZXN0X3dyaXRlKDAsIDEyOCwgeyAweGMyLCAxMjggfSk7CiAgICBlICs9IHRlc3Rfd3JpdGUoMCwgMjU1LCB7IDB4YzMsIDE5MSB9KTsKICAgIGUgKz0gdGVzdF93cml0ZSgwLCAweEZGRkYsIHsgMHhlZiwgMTkxLCAxOTEgfSk7CiAgICBlICs9IHRlc3Rfd3JpdGUoMCwgMHgxMEZGRkYsIHsgMHhmNCwgMHg4ZiwgMTkxLCAxOTEgfSk7CgogICAgLy8gVVRGLTE2CiAgICBlICs9IHRlc3RfcmVhZCgxLCB7IDAsIDEgfSwgMSk7CiAgICBlICs9IHRlc3RfcmVhZCgxLCB7IDB4ZDgsIDAsIDB4ZGMsIDEgfSwgMHgxMDAwMSk7CiAgICBlICs9IHRlc3RfcmVhZCgxLCB7IDB4ZGIsIDB4ZmYsIDB4ZGYsIDB4ZmYgfSwgMHgxMGZmZmYpOwoKICAgIGUgKz0gdGVzdF9yZWFkKDEsIHsgMHhkOCwgMCwgMHhkOCwgMSB9LCBGQUlMKTsgLy8gbWlzbWF0Y2hlZCBzdXJyb2dhdGUKICAgIGUgKz0gdGVzdF9yZWFkKDEsIHsgMHhkOCwgMCwgMCwgMSB9LCBGQUlMKTsgLy8gbWlzbWF0Y2hlZCBzdXJyb2dhdGUKICAgIGUgKz0gdGVzdF9yZWFkKDEsIHsgMHhkYywgMCB9LCBGQUlMKTsKCiAgICBlICs9IHRlc3Rfd3JpdGUoMSwgMSwgeyAwLCAxIH0pOwogICAgZSArPSB0ZXN0X3dyaXRlKDEsIDI1NiwgeyAxLCAwIH0pOwogICAgZSArPSB0ZXN0X3dyaXRlKDEsIDB4ZmZmZiwgeyAyNTUsIDI1NSB9KTsKICAgIGUgKz0gdGVzdF93cml0ZSgxLCAweDEwMDAxLCB7IDB4ZDgsIDAsIDB4ZGMsIDEgfSk7CiAgICBlICs9IHRlc3Rfd3JpdGUoMSwgMHgxMGZmZmYsIHsgMHhkYiwgMHhmZiwgMHhkZiwgMHhmZiB9KTsKCiAgICAvLyBVVEYtMTZMRQogICAgZSArPSB0ZXN0X3dyaXRlKDMsIDEsIHsgMSwgMCB9KTsKICAgIGUgKz0gdGVzdF93cml0ZSgzLCAyNTYsIHsgMCwgMSB9KTsKICAgIGUgKz0gdGVzdF93cml0ZSgzLCAweDEwMDAxLCB7IDAsIDB4ZDgsIDEsIDB4ZGMgfSk7CiAgICBlICs9IHRlc3Rfd3JpdGUoMywgMHgxMGZmZmUsIHsgMHhmZiwgMHhkYiwgMHhmZSwgMHhkZiB9KTsKCiAgICAvLyBVVEYtMTYgYnl0ZS1vcmRlciBtYXJrCiAgICBlICs9IHRlc3RfcmVhZCgxLCB7IDB4RkUsIDB4RkYsIDB4MCwgMSB9LCAxKTsgLy8gYnl0ZS1vcmRlciBtYXJrCiAgICBlICs9IHRlc3RfcmVhZCgxLCB7IDB4RkYsIDB4RkUsIDEsIDB4MCB9LCAxKTsgLy8gcmV2ZXJzZWQgYnl0ZS1vcmRlciBtYXJrCiAgICAvLyBkaXNhbGxvd2VkIGJ5dGUtb3JkZXIgbWFya3MKICAgIGUgKz0gdGVzdF9yZWFkKDIsIHsgMHhGRSwgMHhGRiB9LCBGQUlMKTsKICAgIGUgKz0gdGVzdF9yZWFkKDMsIHsgMHhGRiwgMHhGRSB9LCBGQUlMKTsKICAgIC8vIHJldmVyc2VkIGJ5dGUtb3JkZXIgbWFyayBpcyBhbiB1bmFzc2lnbmVkIGNoYXJhY3RlciAtIHRvIGJlIHRyZWF0ZWQgbGlrZSByZWd1bGFyIGNoYXJhY3RlciwgYWNjb3JkaW5nIHRvIHF1ZXN0aW9uCiAgICBlICs9IHRlc3RfcmVhZCgyLCB7IDB4RkYsIDB4RkUgfSwgMHhmZmZlKTsKICAgIGUgKz0gdGVzdF9yZWFkKDMsIHsgMHhGRSwgMHhGRiB9LCAweGZmZmUpOwoKICAgIC8vIFVURi0zMgogICAgZSArPSB0ZXN0X3JlYWQoNCwgeyAwLCAwLCAwLCAxIH0sIDEpOwogICAgZSArPSB0ZXN0X3JlYWQoNCwgeyAxLCAwLCAwLCAwIH0sIEZBSUwpOwogICAgZSArPSB0ZXN0X3dyaXRlKDQsIDEsIHsgMCwgMCwgMCwgMSB9KTsKICAgIGUgKz0gdGVzdF93cml0ZSg0LCAweDEwMjAzLCB7IDAsIDEsIDIsIDMgfSk7CgogICAgLy8gVVRGLTMyTEUKICAgIGUgKz0gdGVzdF9yZWFkKDYsIHsgMCwgMCwgMCwgMSB9LCBGQUlMKTsKICAgIGUgKz0gdGVzdF9yZWFkKDYsIHsgMSwgMCwgMCwgMCB9LCAxKTsKCiAgICAvLyBVVEYtMzIgYnl0ZS1vcmRlciBtYXJrCiAgICBlICs9IHRlc3RfcmVhZCg0LCB7IDAsIDAsIDB4RkUsIDB4RkYsICAwLCAwLCAwLCAxIH0sIDEpOyAvLyBieXRlLW9yZGVyIG1hcmsKICAgIGUgKz0gdGVzdF9yZWFkKDQsIHsgMHhGRiwgMHhGRSwgMCwgMCwgIDEsIDAsIDAsIDAgfSwgMSk7IC8vIHJldmVyc2VkIGJ5dGUtb3JkZXIgbWFyawogICAgLy8gZGlzYWxsb3dlZCBieXRlLW9yZGVyIG1hcmtzCiAgICBlICs9IHRlc3RfcmVhZCg1LCB7IDAsIDAsIDB4RkUsIDB4RkYgfSwgRkFJTCk7CiAgICBlICs9IHRlc3RfcmVhZCg1LCB7IDB4RkYsIDB4RkUsIDAsIDAgfSwgRkFJTCk7CiAgICBlICs9IHRlc3RfcmVhZCg2LCB7IDAsIDAsIDB4RkUsIDB4RkYgfSwgRkFJTCk7CiAgICBlICs9IHRlc3RfcmVhZCg2LCB7IDB4RkYsIDB4RkUsIDAsIDAgfSwgRkFJTCk7CgogICAgZSArPSB0ZXN0X3RyYW5zY29kZSgxLCB7IDEsIDIsIDB4RkUsIDB4RkYsIDAsIDAgfSwgLy8gVGhhdCdzIG5vdCBhIEJPTTsgaXQncyBhIHp3bmogd2hlbiBub3QgdGhlIGZpcnN0IGNoYXIKICAgICAgICAgICAgICAgICAgICAgICAgMSwgeyAxLCAyLCAweEZFLCAweEZGLCAwLCAwIH0pOwogICAgZSArPSB0ZXN0X3RyYW5zY29kZSgxLCB7IDB4RkYsIDB4RkUsIDEsIDIsIDAsIDAgfSwgLy8gcmV2ZXJzZWQgYnl0ZS1vcmRlciBtYXJrIGltcGxpZXMgbGl0dGxlLWVuZGlhbgogICAgICAgICAgICAgICAgICAgICAgICAxLCB7IDIsIDEsIDAsIDAgfSk7CiAgICBlICs9IHRlc3RfdHJhbnNjb2RlKDQsIHsgMHhGRiwgMHhGRSwgMCwgMCwgMSwgMiwgMCwgMCwgMCwgMCB9LCAvLyByZXZlcnNlZCBCT00gbWVhbnMgbGl0dGxlLWVuZGlhbgogICAgICAgICAgICAgICAgICAgICAgICA0LCB7IDAsIDAsIDIsIDEsIDAsIDAsIDAsIDAgfSk7CiAgICBlICs9IHRlc3RfdHJhbnNjb2RlKDEsIHsgMHhkYiwgMHhmZiwgMHhkZiwgMHhmZiwgMCwgMCB9LCAvLyBVKzEwZmZmZiBVVEYtMTYgdG8gVVRGLTgKICAgICAgICAgICAgICAgICAgICAgICAgMCwgeyAweGY0LCAweDhmLCAxOTEsIDE5MSwgMCB9KTsKCiAgICByZXR1cm4gZTsKfQ==