// Hidden header style array. (2.20)
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// Utility.
#define MAX(a, b) \
({ __auto_type _x = (a); __auto_type _y = (b); \
(_y > _x) ? _y : _x; })
void *memfill(void *base, size_t n, size_t size, const void *fill)
{
if (n != 0 && size != 0)
{
size_t i = 1;
for (; i <= n/2; i *= 2)
memcpy((char*)base
+ i
*size
, base
, i
*size
); memcpy((char*)base
+ i
*size
, base
, (n
-i
)*size
); }
return base;
}
// Interface.
#define ar_size(a) _ar_size(a)
#define ar_capacity(a) _ar_capacity(a)
#define ar_reserve(a, n) ((a) = _ar_reserve(a, n, sizeof *(a)))
#define ar_resize(a, n, v) ((a) = _ar_resize(a, n, (__typeof__(*(a))[]){v}, sizeof *(a)))
#define ar_free(a) (_ar_free(a), (a) = 0)
#define ar_init(a) ((a) = _ar_init())
#define ar_init_size(a, n, v) ((a) = _ar_init_size(n, (__typeof__(*(a))[]){v}, sizeof *(a)))
#define ar_init_copy(a, b) ((a) = _ar_init_copy(b, sizeof *(a)))
#define ar_at(a, i) (ar_at_p(a, i)[0])
#define ar_at_c(a, i) (ar_at_c_p(a, i)[0])
#define ar_at_p(a, i) ((__typeof__(*(a))*)_ar_at(a, i, sizeof *(a)))
#define ar_at_c_p(a, i) ((const __typeof__(*(a))*)_ar_at_c(a, i, sizeof *(a)))
#define ar_remove(a, i, n) _ar_remove(a, i, n, sizeof *(a))
#define ar_insert(a, i, s, n) ((a) = _ar_insert(a, i, s, n, sizeof *(a)))
#define ar_push(a, v) ((a) = _ar_push(a, (__typeof__(*(a))[]){v}, sizeof *(a)))
#define ar_pop(a) _ar_pop(a, sizeof *(a))
#define ar_clear(a) _ar_clear(a, sizeof *(a))
size_t _ar_size(const void *p);
size_t _ar_capacity(const void *p);
void *_ar_reserve(void *p, size_t capacity, size_t itemsize);
void *_ar_resize(void *p, size_t size, const void *fill, size_t itemsize);
void _ar_free(void *p);
void *_ar_init(void);
void *_ar_init_size(size_t size, const void *fill, size_t itemsize);
void *_ar_init_copy(const void *p, size_t itemsize);
const void *_ar_at_c(const void *p, ptrdiff_t i, size_t itemsize);
void *_ar_at(void *p, ptrdiff_t i, size_t itemsize);
void _ar_remove(void *p, size_t i, size_t n, size_t itemsize);
void *_ar_insert(void *p, size_t i, const void *first, size_t n, size_t itemsize);
void *_ar_push(void *p, const void *item, size_t itemsize);
void _ar_pop(void *p, size_t itemsize);
void _ar_clear(void *p, size_t itemsize);
// Implementation.
typedef struct {
size_t size, capacity;
} _Header;
#define _PTR_TO_HDR(p) ((_Header*)((char*)p - sizeof(_Header)))
#define _HDR_TO_PTR(p) ((void*)((char*)p + sizeof(_Header)))
size_t _ar_size(const void *p)
{
return _PTR_TO_HDR(p)->size;
}
size_t _ar_capacity(const void *p)
{
return _PTR_TO_HDR(p)->capacity;
}
void *_ar_reserve(void *p, size_t capacity, size_t itemsize)
{
_Header *self = _PTR_TO_HDR(p);
if (capacity > self->capacity)
{
self
= realloc(self
, sizeof *self
+ capacity
*itemsize
); self->capacity = capacity;
}
return _HDR_TO_PTR(self);
}
void *_ar_resize(void *p, size_t size, const void *fill, size_t itemsize)
{
p = _ar_reserve(p, size, itemsize);
_Header *self = _PTR_TO_HDR(p);
size_t oldsize = self->size;
self->size = size;
if (fill != 0 && size > oldsize)
memfill(_ar_at(p, oldsize, itemsize), size - oldsize, itemsize, fill);
return p;
}
void _ar_free(void *p)
{
if (p != 0)
}
void *_ar_init(void)
{
_Header
*self
= malloc(sizeof *self
); self->size = 0;
self->capacity = 0;
return _HDR_TO_PTR(self);
}
void *_ar_init_size(size_t size, const void *fill, size_t itemsize)
{
return _ar_resize(_ar_init(), size, fill, itemsize);
}
void *_ar_init_copy(const void *p, size_t itemsize)
{
return _ar_insert(_ar_init(), 0, p, _ar_size(p), itemsize);
}
const void *_ar_at_c(const void *p, ptrdiff_t i, size_t itemsize)
{
size_t size = _ar_size(p);
size_t j = (i < 0) ? i + size : (size_t)i;
return (const char*)p + j*itemsize;
}
void *_ar_at(void *p, ptrdiff_t i, size_t itemsize)
{
return (void*)_ar_at_c(p, i, itemsize);
}
void _ar_remove(void *p, size_t i, size_t n, size_t itemsize)
{
_Header *self = _PTR_TO_HDR(p);
size_t oldsize = self->size;
if (n != 0)
{
size_t j;
if (__builtin_add_overflow(i, n, &j))
assert(0 && "integer overflow");
if (oldsize > j)
memmove(_ar_at
(p
, i
, itemsize
), _ar_at
(p
, j
, itemsize
), (oldsize
- j
)*itemsize
); self->size = oldsize - n;
}
}
void *_ar_insert(void *p, size_t i, const void *first, size_t n, size_t itemsize)
{
_Header *self = _PTR_TO_HDR(p);
size_t oldsize = self->size;
if (n != 0)
{
size_t newsize;
if (__builtin_add_overflow(oldsize, n, &newsize))
assert(0 && "integer overflow");
if (newsize > self->capacity)
{
p = _ar_reserve(p, MAX(2*self->capacity, newsize), itemsize);
self = _PTR_TO_HDR(p);
}
self->size = newsize;
void *ip = _ar_at(p, i, itemsize);
if (oldsize > i)
memmove(_ar_at
(p
, i
+ n
, itemsize
), ip
, (oldsize
- i
)*itemsize
); memcpy(ip
, first
, n
*itemsize
); }
return p;
}
void *_ar_push(void *p, const void *item, size_t itemsize)
{
return _ar_insert(p, _ar_size(p), item, 1, itemsize);
}
void _ar_pop(void *p, size_t itemsize)
{
_ar_remove(p, _ar_size(p)-1, 1, itemsize);
}
void _ar_clear(void *p, size_t itemsize)
{
_ar_resize(p, 0, 0, itemsize);
}
// Main.
void ar_print(const int *p)
{
printf("size/capacity: %zu/%zu [", ar_size
(p
), ar_capacity
(p
)); for (size_t i = 0; i < ar_size(p); i++)
{
printf(i
? ", %d" : "%d", p
[i
]); }
}
void test_init_free(void)
{
// Init.
int *p = 0;
ar_init(p);
ar_free(p);
// Init size.
ar_init_size(p, 3, 123);
for (size_t i = 0; i < 3; i++)
// Init copy.
int *q = 0;
ar_init_copy(q, p);
ar_free(p);
for (size_t i = 0; i < 3; i++)
ar_free(q);
printf("%s: Okay.\n", __func__
); }
void test_push_pop(void)
{
int *p = 0;
ar_init(p);
// Push (back).
for (int i = 0; i < 8; i++)
{
int cp2 = i ? 1<<(31 - __builtin_clz(2*i-1)) : 0;
assert(ar_capacity
(p
) == cp2
); ar_push(p, i);
}
// Pop (back).
for (int i = 7; i >= 0; i--)
{
ar_pop(p);
}
ar_free(p);
printf("%s: Okay.\n", __func__
); }
void test_insert_remove(void)
{
int *p = 0;
ar_init(p);
// Insert even (bulk).
ar_insert(p, 0, ((int[]){0, 2, 4}), 3);
for (int i = 0; i < 3; i++)
// Insert odd (single).
for (int i = 0; i < 3; i++)
ar_insert(p, 2*i+1, (int[]){2*i+1}, 1);
for (int i = 0; i < 6; i++)
// Remove even (single).
for (int i = 2; i >= 0; i--)
ar_remove(p, 2*i, 1);
for (int i = 0; i < 3; i++)
// Remove odd (bulk).
ar_remove(p, 0, 3);
ar_free(p);
printf("%s: Okay.\n", __func__
); }
int main(void)
{
test_init_free();
test_push_pop();
test_insert_remove();
int *p = 0;
ar_init(p);
int n = 5;
// Push/Pop (back).
for (int i = 0; i < n; i++)
{
ar_push(p, i);
ar_print(p);
}
while (ar_size(p) != 0)
{
ar_pop(p);
ar_print(p);
}
// Insert/Erase.
for (int i = 0; i < n; i++)
{
ar_insert(p, i, ((int[]){i+1, i+1+n}), 2);
ar_print(p);
}
for (int i = n-1; i >= 0; i--)
{
ar_remove(p, i, 2);
ar_print(p);
}
// Resize (fill).
for (int i = 1; i < n; i++)
{
ar_clear(p);
ar_resize(p, i, -i);
ar_print(p);
}
ar_free(p);
return 0;
}
Ly8gSGlkZGVuIGhlYWRlciBzdHlsZSBhcnJheS4gKDIuMjApCgojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxzdGRkZWYuaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDxzdGRpby5oPgoKLy8gVXRpbGl0eS4KCiNkZWZpbmUgTUFYKGEsIGIpIFwKKHsgX19hdXRvX3R5cGUgX3ggPSAoYSk7IF9fYXV0b190eXBlIF95ID0gKGIpOyBcCiAgIChfeSA+IF94KSA/IF95IDogX3g7IH0pCgp2b2lkICptZW1maWxsKHZvaWQgKmJhc2UsIHNpemVfdCBuLCBzaXplX3Qgc2l6ZSwgY29uc3Qgdm9pZCAqZmlsbCkKewogICAgaWYgKG4gIT0gMCAmJiBzaXplICE9IDApCiAgICB7CiAgICAgICAgbWVtbW92ZShiYXNlLCBmaWxsLCBzaXplKTsKICAgICAgICBzaXplX3QgaSA9IDE7CiAgICAgICAgZm9yICg7IGkgPD0gbi8yOyBpICo9IDIpCiAgICAgICAgICAgIG1lbWNweSgoY2hhciopYmFzZSArIGkqc2l6ZSwgYmFzZSwgaSpzaXplKTsKICAgICAgICBtZW1jcHkoKGNoYXIqKWJhc2UgKyBpKnNpemUsIGJhc2UsIChuLWkpKnNpemUpOwogICAgfQogICAgcmV0dXJuIGJhc2U7Cn0KCi8vIEludGVyZmFjZS4KCiNkZWZpbmUgYXJfc2l6ZShhKSBfYXJfc2l6ZShhKQojZGVmaW5lIGFyX2NhcGFjaXR5KGEpIF9hcl9jYXBhY2l0eShhKQojZGVmaW5lIGFyX3Jlc2VydmUoYSwgbikgKChhKSA9IF9hcl9yZXNlcnZlKGEsIG4sIHNpemVvZiAqKGEpKSkKI2RlZmluZSBhcl9yZXNpemUoYSwgbiwgdikgKChhKSA9IF9hcl9yZXNpemUoYSwgbiwgKF9fdHlwZW9mX18oKihhKSlbXSl7dn0sIHNpemVvZiAqKGEpKSkKI2RlZmluZSBhcl9mcmVlKGEpIChfYXJfZnJlZShhKSwgKGEpID0gMCkKI2RlZmluZSBhcl9pbml0KGEpICgoYSkgPSBfYXJfaW5pdCgpKQojZGVmaW5lIGFyX2luaXRfc2l6ZShhLCBuLCB2KSAoKGEpID0gX2FyX2luaXRfc2l6ZShuLCAoX190eXBlb2ZfXygqKGEpKVtdKXt2fSwgc2l6ZW9mICooYSkpKQojZGVmaW5lIGFyX2luaXRfY29weShhLCBiKSAoKGEpID0gX2FyX2luaXRfY29weShiLCBzaXplb2YgKihhKSkpCiNkZWZpbmUgYXJfYXQoYSwgaSkgKGFyX2F0X3AoYSwgaSlbMF0pCiNkZWZpbmUgYXJfYXRfYyhhLCBpKSAoYXJfYXRfY19wKGEsIGkpWzBdKQojZGVmaW5lIGFyX2F0X3AoYSwgaSkgKChfX3R5cGVvZl9fKCooYSkpKilfYXJfYXQoYSwgaSwgc2l6ZW9mICooYSkpKQojZGVmaW5lIGFyX2F0X2NfcChhLCBpKSAoKGNvbnN0IF9fdHlwZW9mX18oKihhKSkqKV9hcl9hdF9jKGEsIGksIHNpemVvZiAqKGEpKSkKI2RlZmluZSBhcl9yZW1vdmUoYSwgaSwgbikgX2FyX3JlbW92ZShhLCBpLCBuLCBzaXplb2YgKihhKSkKI2RlZmluZSBhcl9pbnNlcnQoYSwgaSwgcywgbikgKChhKSA9IF9hcl9pbnNlcnQoYSwgaSwgcywgbiwgc2l6ZW9mICooYSkpKQojZGVmaW5lIGFyX3B1c2goYSwgdikgKChhKSA9IF9hcl9wdXNoKGEsIChfX3R5cGVvZl9fKCooYSkpW10pe3Z9LCBzaXplb2YgKihhKSkpCiNkZWZpbmUgYXJfcG9wKGEpIF9hcl9wb3AoYSwgc2l6ZW9mICooYSkpCiNkZWZpbmUgYXJfY2xlYXIoYSkgX2FyX2NsZWFyKGEsIHNpemVvZiAqKGEpKQoKc2l6ZV90IF9hcl9zaXplKGNvbnN0IHZvaWQgKnApOwpzaXplX3QgX2FyX2NhcGFjaXR5KGNvbnN0IHZvaWQgKnApOwp2b2lkICpfYXJfcmVzZXJ2ZSh2b2lkICpwLCBzaXplX3QgY2FwYWNpdHksIHNpemVfdCBpdGVtc2l6ZSk7CnZvaWQgKl9hcl9yZXNpemUodm9pZCAqcCwgc2l6ZV90IHNpemUsIGNvbnN0IHZvaWQgKmZpbGwsIHNpemVfdCBpdGVtc2l6ZSk7CnZvaWQgX2FyX2ZyZWUodm9pZCAqcCk7CnZvaWQgKl9hcl9pbml0KHZvaWQpOwp2b2lkICpfYXJfaW5pdF9zaXplKHNpemVfdCBzaXplLCBjb25zdCB2b2lkICpmaWxsLCBzaXplX3QgaXRlbXNpemUpOwp2b2lkICpfYXJfaW5pdF9jb3B5KGNvbnN0IHZvaWQgKnAsIHNpemVfdCBpdGVtc2l6ZSk7CmNvbnN0IHZvaWQgKl9hcl9hdF9jKGNvbnN0IHZvaWQgKnAsIHB0cmRpZmZfdCBpLCBzaXplX3QgaXRlbXNpemUpOwp2b2lkICpfYXJfYXQodm9pZCAqcCwgcHRyZGlmZl90IGksIHNpemVfdCBpdGVtc2l6ZSk7CnZvaWQgX2FyX3JlbW92ZSh2b2lkICpwLCBzaXplX3QgaSwgc2l6ZV90IG4sIHNpemVfdCBpdGVtc2l6ZSk7CnZvaWQgKl9hcl9pbnNlcnQodm9pZCAqcCwgc2l6ZV90IGksIGNvbnN0IHZvaWQgKmZpcnN0LCBzaXplX3Qgbiwgc2l6ZV90IGl0ZW1zaXplKTsKdm9pZCAqX2FyX3B1c2godm9pZCAqcCwgY29uc3Qgdm9pZCAqaXRlbSwgc2l6ZV90IGl0ZW1zaXplKTsKdm9pZCBfYXJfcG9wKHZvaWQgKnAsIHNpemVfdCBpdGVtc2l6ZSk7CnZvaWQgX2FyX2NsZWFyKHZvaWQgKnAsIHNpemVfdCBpdGVtc2l6ZSk7CgovLyBJbXBsZW1lbnRhdGlvbi4KCnR5cGVkZWYgc3RydWN0IHsKICAgIHNpemVfdCBzaXplLCBjYXBhY2l0eTsKfSBfSGVhZGVyOwoKI2RlZmluZSBfUFRSX1RPX0hEUihwKSAoKF9IZWFkZXIqKSgoY2hhciopcCAtIHNpemVvZihfSGVhZGVyKSkpCiNkZWZpbmUgX0hEUl9UT19QVFIocCkgKCh2b2lkKikoKGNoYXIqKXAgKyBzaXplb2YoX0hlYWRlcikpKQoKc2l6ZV90IF9hcl9zaXplKGNvbnN0IHZvaWQgKnApCnsKICAgIGFzc2VydChwICE9IDApOwogICAgcmV0dXJuIF9QVFJfVE9fSERSKHApLT5zaXplOwp9CgpzaXplX3QgX2FyX2NhcGFjaXR5KGNvbnN0IHZvaWQgKnApCnsKICAgIGFzc2VydChwICE9IDApOwogICAgcmV0dXJuIF9QVFJfVE9fSERSKHApLT5jYXBhY2l0eTsKfQoKdm9pZCAqX2FyX3Jlc2VydmUodm9pZCAqcCwgc2l6ZV90IGNhcGFjaXR5LCBzaXplX3QgaXRlbXNpemUpCnsKICAgIGFzc2VydChwICE9IDApOwogICAgX0hlYWRlciAqc2VsZiA9IF9QVFJfVE9fSERSKHApOwoKICAgIGlmIChjYXBhY2l0eSA+IHNlbGYtPmNhcGFjaXR5KQogICAgewogICAgICAgIHNlbGYgPSByZWFsbG9jKHNlbGYsIHNpemVvZiAqc2VsZiArIGNhcGFjaXR5Kml0ZW1zaXplKTsKICAgICAgICBhc3NlcnQoc2VsZiAhPSAwKTsKICAgICAgICBzZWxmLT5jYXBhY2l0eSA9IGNhcGFjaXR5OwogICAgfQogICAgcmV0dXJuIF9IRFJfVE9fUFRSKHNlbGYpOwp9Cgp2b2lkICpfYXJfcmVzaXplKHZvaWQgKnAsIHNpemVfdCBzaXplLCBjb25zdCB2b2lkICpmaWxsLCBzaXplX3QgaXRlbXNpemUpCnsKICAgIGFzc2VydChwICE9IDApOwogICAgcCA9IF9hcl9yZXNlcnZlKHAsIHNpemUsIGl0ZW1zaXplKTsKCiAgICBfSGVhZGVyICpzZWxmID0gX1BUUl9UT19IRFIocCk7CiAgICBzaXplX3Qgb2xkc2l6ZSA9IHNlbGYtPnNpemU7CiAgICBzZWxmLT5zaXplID0gc2l6ZTsKCiAgICBpZiAoZmlsbCAhPSAwICYmIHNpemUgPiBvbGRzaXplKQogICAgICAgIG1lbWZpbGwoX2FyX2F0KHAsIG9sZHNpemUsIGl0ZW1zaXplKSwgc2l6ZSAtIG9sZHNpemUsIGl0ZW1zaXplLCBmaWxsKTsKICAgIHJldHVybiBwOwp9Cgp2b2lkIF9hcl9mcmVlKHZvaWQgKnApCnsKICAgIGlmIChwICE9IDApCiAgICAgICAgZnJlZShfUFRSX1RPX0hEUihwKSk7Cn0KCnZvaWQgKl9hcl9pbml0KHZvaWQpCnsKICAgIF9IZWFkZXIgKnNlbGYgPSBtYWxsb2Moc2l6ZW9mICpzZWxmKTsKICAgIGFzc2VydChzZWxmICE9IDApOwogICAgc2VsZi0+c2l6ZSA9IDA7CiAgICBzZWxmLT5jYXBhY2l0eSA9IDA7CiAgICByZXR1cm4gX0hEUl9UT19QVFIoc2VsZik7Cn0KCnZvaWQgKl9hcl9pbml0X3NpemUoc2l6ZV90IHNpemUsIGNvbnN0IHZvaWQgKmZpbGwsIHNpemVfdCBpdGVtc2l6ZSkKewogICAgcmV0dXJuIF9hcl9yZXNpemUoX2FyX2luaXQoKSwgc2l6ZSwgZmlsbCwgaXRlbXNpemUpOwp9Cgp2b2lkICpfYXJfaW5pdF9jb3B5KGNvbnN0IHZvaWQgKnAsIHNpemVfdCBpdGVtc2l6ZSkKewogICAgcmV0dXJuIF9hcl9pbnNlcnQoX2FyX2luaXQoKSwgMCwgcCwgX2FyX3NpemUocCksIGl0ZW1zaXplKTsKfQoKY29uc3Qgdm9pZCAqX2FyX2F0X2MoY29uc3Qgdm9pZCAqcCwgcHRyZGlmZl90IGksIHNpemVfdCBpdGVtc2l6ZSkKewogICAgc2l6ZV90IHNpemUgPSBfYXJfc2l6ZShwKTsKICAgIHNpemVfdCBqID0gKGkgPCAwKSA/IGkgKyBzaXplIDogKHNpemVfdClpOwogICAgYXNzZXJ0KGogPCBzaXplKTsKICAgIHJldHVybiAoY29uc3QgY2hhciopcCArIGoqaXRlbXNpemU7Cn0KCnZvaWQgKl9hcl9hdCh2b2lkICpwLCBwdHJkaWZmX3QgaSwgc2l6ZV90IGl0ZW1zaXplKQp7CiAgICByZXR1cm4gKHZvaWQqKV9hcl9hdF9jKHAsIGksIGl0ZW1zaXplKTsKfQoKdm9pZCBfYXJfcmVtb3ZlKHZvaWQgKnAsIHNpemVfdCBpLCBzaXplX3Qgbiwgc2l6ZV90IGl0ZW1zaXplKQp7CiAgICBhc3NlcnQocCAhPSAwKTsKICAgIF9IZWFkZXIgKnNlbGYgPSBfUFRSX1RPX0hEUihwKTsKCiAgICBzaXplX3Qgb2xkc2l6ZSA9IHNlbGYtPnNpemU7CiAgICBhc3NlcnQob2xkc2l6ZSA+PSBpKTsKCiAgICBpZiAobiAhPSAwKQogICAgewogICAgICAgIHNpemVfdCBqOwogICAgICAgIGlmIChfX2J1aWx0aW5fYWRkX292ZXJmbG93KGksIG4sICZqKSkKICAgICAgICAgICAgYXNzZXJ0KDAgJiYgImludGVnZXIgb3ZlcmZsb3ciKTsKICAgICAgICBhc3NlcnQob2xkc2l6ZSA+PSBqKTsKCiAgICAgICAgaWYgKG9sZHNpemUgPiBqKQogICAgICAgICAgICBtZW1tb3ZlKF9hcl9hdChwLCBpLCBpdGVtc2l6ZSksIF9hcl9hdChwLCBqLCBpdGVtc2l6ZSksIChvbGRzaXplIC0gaikqaXRlbXNpemUpOwogICAgICAgIHNlbGYtPnNpemUgPSBvbGRzaXplIC0gbjsKICAgIH0KfQoKdm9pZCAqX2FyX2luc2VydCh2b2lkICpwLCBzaXplX3QgaSwgY29uc3Qgdm9pZCAqZmlyc3QsIHNpemVfdCBuLCBzaXplX3QgaXRlbXNpemUpCnsKICAgIGFzc2VydChwICE9IDApOwogICAgX0hlYWRlciAqc2VsZiA9IF9QVFJfVE9fSERSKHApOwoKICAgIHNpemVfdCBvbGRzaXplID0gc2VsZi0+c2l6ZTsKICAgIGFzc2VydChvbGRzaXplID49IGkpOwoKICAgIGlmIChuICE9IDApCiAgICB7CiAgICAgICAgc2l6ZV90IG5ld3NpemU7CiAgICAgICAgaWYgKF9fYnVpbHRpbl9hZGRfb3ZlcmZsb3cob2xkc2l6ZSwgbiwgJm5ld3NpemUpKQogICAgICAgICAgICBhc3NlcnQoMCAmJiAiaW50ZWdlciBvdmVyZmxvdyIpOwoKICAgICAgICBpZiAobmV3c2l6ZSA+IHNlbGYtPmNhcGFjaXR5KQogICAgICAgIHsKICAgICAgICAgICAgcCA9IF9hcl9yZXNlcnZlKHAsIE1BWCgyKnNlbGYtPmNhcGFjaXR5LCBuZXdzaXplKSwgaXRlbXNpemUpOwogICAgICAgICAgICBzZWxmID0gX1BUUl9UT19IRFIocCk7CiAgICAgICAgfQogICAgICAgIHNlbGYtPnNpemUgPSBuZXdzaXplOwogICAgICAgIHZvaWQgKmlwID0gX2FyX2F0KHAsIGksIGl0ZW1zaXplKTsKCiAgICAgICAgaWYgKG9sZHNpemUgPiBpKQogICAgICAgICAgICBtZW1tb3ZlKF9hcl9hdChwLCBpICsgbiwgaXRlbXNpemUpLCBpcCwgKG9sZHNpemUgLSBpKSppdGVtc2l6ZSk7CiAgICAgICAgbWVtY3B5KGlwLCBmaXJzdCwgbippdGVtc2l6ZSk7CiAgICB9CiAgICByZXR1cm4gcDsKfQoKdm9pZCAqX2FyX3B1c2godm9pZCAqcCwgY29uc3Qgdm9pZCAqaXRlbSwgc2l6ZV90IGl0ZW1zaXplKQp7CiAgICByZXR1cm4gX2FyX2luc2VydChwLCBfYXJfc2l6ZShwKSwgaXRlbSwgMSwgaXRlbXNpemUpOwp9Cgp2b2lkIF9hcl9wb3Aodm9pZCAqcCwgc2l6ZV90IGl0ZW1zaXplKQp7CiAgICBfYXJfcmVtb3ZlKHAsIF9hcl9zaXplKHApLTEsIDEsIGl0ZW1zaXplKTsKfQoKdm9pZCBfYXJfY2xlYXIodm9pZCAqcCwgc2l6ZV90IGl0ZW1zaXplKQp7CiAgICBfYXJfcmVzaXplKHAsIDAsIDAsIGl0ZW1zaXplKTsKfQoKLy8gTWFpbi4KCnZvaWQgYXJfcHJpbnQoY29uc3QgaW50ICpwKQp7CiAgICBwcmludGYoInNpemUvY2FwYWNpdHk6ICV6dS8lenUgWyIsIGFyX3NpemUocCksIGFyX2NhcGFjaXR5KHApKTsKICAgIGZvciAoc2l6ZV90IGkgPSAwOyBpIDwgYXJfc2l6ZShwKTsgaSsrKQogICAgewogICAgICAgIHByaW50ZihpID8gIiwgJWQiIDogIiVkIiwgcFtpXSk7CiAgICB9CiAgICBwdXRzKCJdIik7Cn0KCnZvaWQgdGVzdF9pbml0X2ZyZWUodm9pZCkKewogICAgLy8gSW5pdC4KCiAgICBpbnQgKnAgPSAwOwogICAgYXJfaW5pdChwKTsKICAgIGFzc2VydChhcl9zaXplKHApID09IDApOwogICAgYXJfZnJlZShwKTsKICAgIGFzc2VydChwID09IDApOwoKICAgIC8vIEluaXQgc2l6ZS4KCiAgICBhcl9pbml0X3NpemUocCwgMywgMTIzKTsKICAgIGFzc2VydChhcl9zaXplKHApID09IDMpOwogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCAzOyBpKyspCiAgICAgICAgYXNzZXJ0KGFyX2F0KHAsIGkpID09IDEyMyk7CgogICAgLy8gSW5pdCBjb3B5LgoKICAgIGludCAqcSA9IDA7CiAgICBhcl9pbml0X2NvcHkocSwgcCk7CiAgICBhcl9mcmVlKHApOwogICAgYXNzZXJ0KHAgPT0gMCk7CgogICAgYXNzZXJ0KGFyX3NpemUocSkgPT0gMyk7CiAgICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IDM7IGkrKykKICAgICAgICBhc3NlcnQoYXJfYXQocSwgaSkgPT0gMTIzKTsKICAgIGFyX2ZyZWUocSk7CiAgICBhc3NlcnQocSA9PSAwKTsKCiAgICBwcmludGYoIiVzOiBPa2F5LlxuIiwgX19mdW5jX18pOwp9Cgp2b2lkIHRlc3RfcHVzaF9wb3Aodm9pZCkKewogICAgaW50ICpwID0gMDsKICAgIGFyX2luaXQocCk7CgogICAgLy8gUHVzaCAoYmFjaykuCgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCA4OyBpKyspCiAgICB7CiAgICAgICAgYXNzZXJ0KGFyX3NpemUocCkgPT0gaSk7CiAgICAgICAgaW50IGNwMiA9IGkgPyAxPDwoMzEgLSBfX2J1aWx0aW5fY2x6KDIqaS0xKSkgOiAwOwogICAgICAgIGFzc2VydChhcl9jYXBhY2l0eShwKSA9PSBjcDIpOwogICAgICAgIGFyX3B1c2gocCwgaSk7CiAgICAgICAgYXNzZXJ0KGFyX2F0KHAsIC0xKSA9PSBpKTsKICAgIH0KCiAgICAvLyBQb3AgKGJhY2spLgoKICAgIGZvciAoaW50IGkgPSA3OyBpID49IDA7IGktLSkKICAgIHsKICAgICAgICBhc3NlcnQoYXJfYXQocCwgLTEpID09IGkpOwogICAgICAgIGFyX3BvcChwKTsKICAgIH0KICAgIGFzc2VydChhcl9zaXplKHApID09IDApOwogICAgYXJfZnJlZShwKTsKCiAgICBwcmludGYoIiVzOiBPa2F5LlxuIiwgX19mdW5jX18pOwp9Cgp2b2lkIHRlc3RfaW5zZXJ0X3JlbW92ZSh2b2lkKQp7CiAgICBpbnQgKnAgPSAwOwogICAgYXJfaW5pdChwKTsKCiAgICAvLyBJbnNlcnQgZXZlbiAoYnVsaykuCgogICAgYXJfaW5zZXJ0KHAsIDAsICgoaW50W10pezAsIDIsIDR9KSwgMyk7CiAgICBhc3NlcnQoYXJfc2l6ZShwKSA9PSAzKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMzsgaSsrKQogICAgICAgIGFzc2VydChhcl9hdChwLCBpKSA9PSAyKmkpOwoKICAgIC8vIEluc2VydCBvZGQgKHNpbmdsZSkuCgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCAzOyBpKyspCiAgICAgICAgYXJfaW5zZXJ0KHAsIDIqaSsxLCAoaW50W10pezIqaSsxfSwgMSk7CiAgICBhc3NlcnQoYXJfc2l6ZShwKSA9PSA2KTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgNjsgaSsrKQogICAgICAgIGFzc2VydChhcl9hdChwLCBpKSA9PSBpKTsKCiAgICAvLyBSZW1vdmUgZXZlbiAoc2luZ2xlKS4KCiAgICBmb3IgKGludCBpID0gMjsgaSA+PSAwOyBpLS0pCiAgICAgICAgYXJfcmVtb3ZlKHAsIDIqaSwgMSk7CiAgICBhc3NlcnQoYXJfc2l6ZShwKSA9PSAzKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMzsgaSsrKQogICAgICAgIGFzc2VydChhcl9hdChwLCBpKSA9PSAyKmkrMSk7CgogICAgLy8gUmVtb3ZlIG9kZCAoYnVsaykuCgogICAgYXJfcmVtb3ZlKHAsIDAsIDMpOwogICAgYXNzZXJ0KGFyX3NpemUocCkgPT0gMCk7CiAgICBhcl9mcmVlKHApOwoKICAgIHByaW50ZigiJXM6IE9rYXkuXG4iLCBfX2Z1bmNfXyk7Cn0KCmludCBtYWluKHZvaWQpCnsKICAgIHRlc3RfaW5pdF9mcmVlKCk7CiAgICB0ZXN0X3B1c2hfcG9wKCk7CiAgICB0ZXN0X2luc2VydF9yZW1vdmUoKTsKCiAgICBpbnQgKnAgPSAwOwogICAgYXJfaW5pdChwKTsKCiAgICBpbnQgbiA9IDU7CgogICAgLy8gUHVzaC9Qb3AgKGJhY2spLgoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKQogICAgewogICAgICAgIGFyX3B1c2gocCwgaSk7CiAgICAgICAgYXJfcHJpbnQocCk7CiAgICB9CiAgICB3aGlsZSAoYXJfc2l6ZShwKSAhPSAwKQogICAgewogICAgICAgIGFyX3BvcChwKTsKICAgICAgICBhcl9wcmludChwKTsKICAgIH0KCiAgICAvLyBJbnNlcnQvRXJhc2UuCgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICB7CiAgICAgICAgYXJfaW5zZXJ0KHAsIGksICgoaW50W10pe2krMSwgaSsxK259KSwgMik7CiAgICAgICAgYXJfcHJpbnQocCk7CiAgICB9CiAgICBmb3IgKGludCBpID0gbi0xOyBpID49IDA7IGktLSkKICAgIHsKICAgICAgICBhcl9yZW1vdmUocCwgaSwgMik7CiAgICAgICAgYXJfcHJpbnQocCk7CiAgICB9CgogICAgLy8gUmVzaXplIChmaWxsKS4KCiAgICBmb3IgKGludCBpID0gMTsgaSA8IG47IGkrKykKICAgIHsKICAgICAgICBhcl9jbGVhcihwKTsKICAgICAgICBhcl9yZXNpemUocCwgaSwgLWkpOwogICAgICAgIGFyX3ByaW50KHApOwogICAgfQoKICAgIGFyX2ZyZWUocCk7CiAgICByZXR1cm4gMDsKfQ==