/**
* @file array.002.c
* @ingroup experimental
* Dynamic array using hidden header.
* @date 08/13/2026
*/
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//
// Utility.
//
#define REF_T(T, ...) \
((T[]){__VA_ARGS__})
#define DEREF_T(T, p) \
(((T*)(void*)(p))[0])
#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*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;
}
//
// Array.
//
#define ar_size(a) _ar_size(a)
#define ar_itemsize(a) _ar_itemsize(a)
#define ar_capacity(a) _ar_capacity(a)
#define ar_putitem(a) _ar_putitem(a)
#define ar_set_putitem(a, f) _ar_set_putitem(a, f)
#define ar_at(a, i) (((__typeof__(*(a))*)_ar_at(a, i))[0])
#define ar_at_c(a, i) (((const __typeof__(*(a))*)_ar_at_c(a, i))[0])
#define ar_reserve(a, n) ((a) = _ar_reserve(a, n))
#define ar_resize(a, n, v) ((a) = _ar_resize(a, n, (__typeof__(*(a))[]){v}))
#define ar_insert(a, i, s, n) ((a) = _ar_insert(a, i, s, n))
#define ar_remove(a, i, n) _ar_remove(a, i, n)
#define ar_push(a, v) ((a) = _ar_push(a, (__typeof__(*(a))[]){v}))
#define ar_pop(a) _ar_pop(a)
#define ar_clear(a) _ar_clear(a)
#define ar_free(a) (_ar_free(a), (a) = 0)
#define ar_init(a, n) ((a) = _ar_init(sizeof *(a), n))
#define ar_init_size(a, n, v) ((a) = _ar_init_size(sizeof *(a), n, (__typeof__(*(a))[]){v}))
#define ar_init_copy(a, b, n) ((a) = (__typeof__(*(b))*)_ar_init_copy(b, n))
#define ar_print(a) _ar_print(a, stdout)
#define ar_println(a) _ar_println(a, stdout)
// ..
#define _BASE_TO_SELF(p) ((_Header*)((char*)p - sizeof(_Header)))
#define _SELF_TO_BASE(p) ((void*)((char*)p + sizeof(_Header)))
typedef struct {
size_t size;
size_t itemsize;
size_t capacity;
void (*putitem)(const void *item, FILE *stream);
} _Header;
size_t _ar_size(const void *base)
{
return _BASE_TO_SELF(base)->size;
}
size_t _ar_itemsize(const void *base)
{
return _BASE_TO_SELF(base)->itemsize;
}
size_t _ar_capacity(const void *base)
{
return _BASE_TO_SELF(base)->capacity;
}
void (*_ar_putitem(const void *base))(const void *, FILE *)
{
return _BASE_TO_SELF(base)->putitem;
}
void _ar_set_putitem(void *base, void (*putitem)(const void *, FILE *))
{
_BASE_TO_SELF(base)->putitem = putitem;
}
const void *_ar_at_c(const void *base, ptrdiff_t i)
{
const _Header *self = _BASE_TO_SELF(base);
size_t size = self->size;
size_t j = (i < 0) ? i + size : (size_t)i;
return (const char*)base + j*self->itemsize;
}
void *_ar_at(void *base, ptrdiff_t i)
{
return (void*)_ar_at_c(base, i);
}
void *_ar_reserve(void *base, size_t capacity)
{
// Ensure array has enough memory for capacity items.
_Header *self = _BASE_TO_SELF(base);
if (capacity > self->capacity)
{
self
= realloc(self
, sizeof *self
+ capacity
*self
->itemsize
); self->capacity = capacity;
}
return _SELF_TO_BASE(self);
}
void *_ar_resize(void *base, size_t size, const void *fill)
{
// Change array size and initialize newly revealed items to specified fill
// value. If fill is not provided, items are not initialized.
base = _ar_reserve(base, size);
_Header *self = _BASE_TO_SELF(base);
size_t oldsize = self->size;
self->size = size;
if (fill != 0 && size > oldsize)
memfill(_ar_at(base, oldsize), size - oldsize, self->itemsize, fill);
return base;
}
void *_ar_insert(void *base, size_t i, const void *first, size_t n)
{
// Insert n items starting at first into array before position i.
_Header *self = _BASE_TO_SELF(base);
size_t oldsize = self->size;
if (n != 0)
{
size_t size;
if (__builtin_add_overflow(oldsize, n, &size))
assert(0 && "integer overflow");
if (size > self->capacity)
{
base = _ar_reserve(base, MAX(2*self->capacity, size));
self = _BASE_TO_SELF(base);
}
self->size = size;
void *ip = _ar_at(base, i);
if (oldsize > i)
memmove(_ar_at
(base
, i
+ n
), ip
, (oldsize
- i
)*self
->itemsize
); memcpy(ip
, first
, n
*self
->itemsize
); }
return base;
}
void _ar_remove(void *base, size_t i, size_t n)
{
// Remove n items from array starting at position i.
_Header *self = _BASE_TO_SELF(base);
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
(base
, i
), _ar_at
(base
, j
), (oldsize
- j
)*self
->itemsize
); self->size = oldsize - n;
}
}
void *_ar_push(void *base, const void *item)
{
return _ar_insert(base, _ar_size(base), item, 1);
}
void _ar_pop(void *base)
{
_ar_remove(base, _ar_size(base)-1, 1);
}
void _ar_clear(void *base)
{
_ar_resize(base, 0, 0);
}
void _ar_free(void *base)
{
if (base != 0)
free(_BASE_TO_SELF
(base
)); }
void *_ar_init(size_t itemsize, size_t capacity)
{
// Create array with enough memory for capacity items.
_Header
*self
= malloc(sizeof *self
+ capacity
*itemsize
); self->size = 0;
self->itemsize = itemsize;
self->capacity = capacity;
self->putitem = 0;
return _SELF_TO_BASE(self);
}
void *_ar_init_size(size_t itemsize, size_t size, const void *fill)
{
// Create with size items and initialize with specified fill value.
return _ar_resize(_ar_init(itemsize, size), size, fill);
}
void *_ar_init_copy(const void *other_base, size_t capacity)
{
// Create copy of an array with at least capacity items reserved.
const _Header *other = _BASE_TO_SELF(other_base);
void *base = _ar_init(other->itemsize, MAX(other->size, capacity));
return _ar_insert(base, 0, other_base, other->size);
}
void _ar_print(const void *base, FILE *stream)
{
const _Header *self = _BASE_TO_SELF(base);
void (*putitem)(const void *, FILE *) = self->putitem;
size_t n = self->size;
if (n != 0)
{
for (size_t i = 0;;)
{
putitem(_ar_at_c(base, i), stream);
if (++i == n) break;
}
}
}
void _ar_println(const void *base, FILE *stream)
{
_ar_print
(base
, stream
); fputc('\n', stream
);}
//
// Main.
//
void test_init_free(void)
{
// Init.
int *a = 0;
ar_init(a, 0);
assert(ar_itemsize
(a
) == sizeof(*a
));
ar_free(a);
// Init (capacity).
ar_init(a, 8);
assert(ar_itemsize
(a
) == sizeof(*a
));
ar_free(a);
// Init size.
ar_init_size(a, 3, 123);
assert(ar_itemsize
(a
) == sizeof(*a
));
for (size_t i = 0; i < 3; i++)
// Init copy.
int *b = 0;
ar_init_copy(b, a, 0);
ar_free(a);
assert(ar_itemsize
(b
) == sizeof(*b
));
for (size_t i = 0; i < 3; i++)
// Init copy (capacity).
ar_init_copy(a, b, 8);
ar_free(b);
assert(ar_itemsize
(a
) == sizeof(*a
));
for (size_t i = 0; i < 3; i++)
ar_free(a);
}
void test_push_pop(void)
{
int *a = 0;
ar_init(a, 0);
// Push (back).
for (int i = 0; i < 8; i++)
{
ar_push(a, i);
assert(ar_size
(a
) == (size_t)i
+1); }
// Pop (back).
for (int i = 8-1; i >= 0; i--)
{
ar_pop(a);
assert(ar_size
(a
) == (size_t)i
); }
ar_free(a);
}
void test_insert_remove(void)
{
int *a = 0;
ar_init(a, 0);
// Insert even (bulk).
ar_insert(a, 0, REF_T(int, 0, 2, 4), 3);
for (int i = 0; i < 3; i++)
// Insert odd (single).
for (int i = 0; i < 3; i++)
ar_insert(a, 2*i+1, REF_T(int, 2*i+1), 1);
for (int i = 0; i < 6; i++)
// Remove even (single).
for (int i = 2; i >= 0; i--)
ar_remove(a, 2*i, 1);
for (int i = 0; i < 3; i++)
// Remove odd (bulk).
ar_remove(a, 0, 3);
ar_free(a);
}
// ..
void putitem_ar(const void *item, FILE *stream)
{
_ar_print(*(const void **)item, stream);
}
void putitem_int(const void *item, FILE *stream)
{
fprintf(stream
, "%d", *(const int *)item
); }
int *iota(int n, int start, int step)
{
int *a = 0;
ar_init(a, MAX(n, 0));
ar_set_putitem(a, putitem_int);
for (int i = 0; i < n; i++)
ar_push(a, start + i*step);
return a;
}
void show_push_pop(void)
{
int *a = 0;
ar_init(a, 0);
ar_set_putitem(a, putitem_int);
int n = 4;
for (int i = 0; i < n; i++)
{
ar_push(a, i);
ar_println(a);
}
while (ar_size(a) != 0)
{
ar_pop(a);
ar_println(a);
}
ar_free(a);
}
void show_insert_remove(void)
{
int *a = 0;
ar_init(a, 0);
ar_set_putitem(a, putitem_int);
int n = 4;
for (int i = 0; i < n; i++)
{
ar_insert(a, i, REF_T(int, i+1, i+1+n), 2);
ar_println(a);
}
for (int i = n-1; i >= 0; i--)
{
ar_remove(a, i, 2);
ar_println(a);
}
ar_free(a);
}
void show_resize(void)
{
int *a = 0;
ar_init(a, 0);
ar_set_putitem(a, putitem_int);
int n = 4;
for (int i = 1; i <= n; i++)
{
ar_resize(a, i, -i);
ar_println(a);
ar_clear(a);
}
for (int i = 1; i <= n; i++)
{
ar_resize(a, i, -i);
ar_println(a);
}
ar_free(a);
}
void show_array_of_array(void)
{
int **a = 0;
ar_init(a, 0);
ar_set_putitem(a, putitem_ar);
int n = 4;
for (int i = 0; i < n; i++)
{
int count = i+1;
int start = i*(i+1)/2+1;
ar_push(a, iota(count, start, 1));
ar_println(a);
}
for (size_t i = 0; i < ar_size(a); i++)
ar_free(a[i]);
ar_free(a);
}
int main(void)
{
test_init_free();
test_push_pop();
test_insert_remove();
show_push_pop();
show_insert_remove();
show_resize();
show_array_of_array();
return 0;
}
LyoqCiAqIEBmaWxlIGFycmF5LjAwMi5jCiAqIEBpbmdyb3VwIGV4cGVyaW1lbnRhbAogKiBEeW5hbWljIGFycmF5IHVzaW5nIGhpZGRlbiBoZWFkZXIuCiAqIEBkYXRlIDA4LzEzLzIwMjYKICovCgojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxzdGRkZWYuaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDxzdGRpby5oPgoKLy8KLy8gVXRpbGl0eS4KLy8KCiNkZWZpbmUgUkVGX1QoVCwgLi4uKSBcCiAgICAoKFRbXSl7X19WQV9BUkdTX199KQoKI2RlZmluZSBERVJFRl9UKFQsIHApIFwKICAgICgoKFQqKSh2b2lkKikocCkpWzBdKQoKI2RlZmluZSBNQVgoYSwgYikgXAooeyBfX2F1dG9fdHlwZSBfeCA9IChhKTsgX19hdXRvX3R5cGUgX3kgPSAoYik7IFwKICAgKF95ID4gX3gpID8gX3kgOiBfeDsgfSkKCnZvaWQgKm1lbWZpbGwodm9pZCAqYmFzZSwgc2l6ZV90IG4sIHNpemVfdCBzaXplLCBjb25zdCB2b2lkICpmaWxsKQp7CiAgICBpZiAobipzaXplICE9IDApCiAgICB7CiAgICAgICAgbWVtbW92ZShiYXNlLCBmaWxsLCBzaXplKTsKICAgICAgICBzaXplX3QgaSA9IDE7CiAgICAgICAgZm9yICg7IGkgPD0gbi8yOyBpICo9IDIpCiAgICAgICAgICAgIG1lbWNweSgoY2hhciopYmFzZSArIGkqc2l6ZSwgYmFzZSwgaSpzaXplKTsKICAgICAgICBtZW1jcHkoKGNoYXIqKWJhc2UgKyBpKnNpemUsIGJhc2UsIChuLWkpKnNpemUpOwogICAgfQogICAgcmV0dXJuIGJhc2U7Cn0KCi8vCi8vIEFycmF5LgovLwoKI2RlZmluZSBhcl9zaXplKGEpIF9hcl9zaXplKGEpCiNkZWZpbmUgYXJfaXRlbXNpemUoYSkgX2FyX2l0ZW1zaXplKGEpCiNkZWZpbmUgYXJfY2FwYWNpdHkoYSkgX2FyX2NhcGFjaXR5KGEpCiNkZWZpbmUgYXJfcHV0aXRlbShhKSBfYXJfcHV0aXRlbShhKQojZGVmaW5lIGFyX3NldF9wdXRpdGVtKGEsIGYpIF9hcl9zZXRfcHV0aXRlbShhLCBmKQojZGVmaW5lIGFyX2F0KGEsIGkpICgoKF9fdHlwZW9mX18oKihhKSkqKV9hcl9hdChhLCBpKSlbMF0pCiNkZWZpbmUgYXJfYXRfYyhhLCBpKSAoKChjb25zdCBfX3R5cGVvZl9fKCooYSkpKilfYXJfYXRfYyhhLCBpKSlbMF0pCiNkZWZpbmUgYXJfcmVzZXJ2ZShhLCBuKSAoKGEpID0gX2FyX3Jlc2VydmUoYSwgbikpCiNkZWZpbmUgYXJfcmVzaXplKGEsIG4sIHYpICgoYSkgPSBfYXJfcmVzaXplKGEsIG4sIChfX3R5cGVvZl9fKCooYSkpW10pe3Z9KSkKI2RlZmluZSBhcl9pbnNlcnQoYSwgaSwgcywgbikgKChhKSA9IF9hcl9pbnNlcnQoYSwgaSwgcywgbikpCiNkZWZpbmUgYXJfcmVtb3ZlKGEsIGksIG4pIF9hcl9yZW1vdmUoYSwgaSwgbikKI2RlZmluZSBhcl9wdXNoKGEsIHYpICgoYSkgPSBfYXJfcHVzaChhLCAoX190eXBlb2ZfXygqKGEpKVtdKXt2fSkpCiNkZWZpbmUgYXJfcG9wKGEpIF9hcl9wb3AoYSkKI2RlZmluZSBhcl9jbGVhcihhKSBfYXJfY2xlYXIoYSkKI2RlZmluZSBhcl9mcmVlKGEpIChfYXJfZnJlZShhKSwgKGEpID0gMCkKI2RlZmluZSBhcl9pbml0KGEsIG4pICgoYSkgPSBfYXJfaW5pdChzaXplb2YgKihhKSwgbikpCiNkZWZpbmUgYXJfaW5pdF9zaXplKGEsIG4sIHYpICgoYSkgPSBfYXJfaW5pdF9zaXplKHNpemVvZiAqKGEpLCBuLCAoX190eXBlb2ZfXygqKGEpKVtdKXt2fSkpCiNkZWZpbmUgYXJfaW5pdF9jb3B5KGEsIGIsIG4pICgoYSkgPSAoX190eXBlb2ZfXygqKGIpKSopX2FyX2luaXRfY29weShiLCBuKSkKI2RlZmluZSBhcl9wcmludChhKSBfYXJfcHJpbnQoYSwgc3Rkb3V0KQojZGVmaW5lIGFyX3ByaW50bG4oYSkgX2FyX3ByaW50bG4oYSwgc3Rkb3V0KQoKLy8gLi4KCiNkZWZpbmUgX0JBU0VfVE9fU0VMRihwKSAoKF9IZWFkZXIqKSgoY2hhciopcCAtIHNpemVvZihfSGVhZGVyKSkpCiNkZWZpbmUgX1NFTEZfVE9fQkFTRShwKSAoKHZvaWQqKSgoY2hhciopcCArIHNpemVvZihfSGVhZGVyKSkpCgp0eXBlZGVmIHN0cnVjdCB7CiAgICBzaXplX3Qgc2l6ZTsKICAgIHNpemVfdCBpdGVtc2l6ZTsKICAgIHNpemVfdCBjYXBhY2l0eTsKICAgIHZvaWQgKCpwdXRpdGVtKShjb25zdCB2b2lkICppdGVtLCBGSUxFICpzdHJlYW0pOwp9IF9IZWFkZXI7CgpzaXplX3QgX2FyX3NpemUoY29uc3Qgdm9pZCAqYmFzZSkKewogICAgYXNzZXJ0KGJhc2UgIT0gMCk7CiAgICByZXR1cm4gX0JBU0VfVE9fU0VMRihiYXNlKS0+c2l6ZTsKfQoKc2l6ZV90IF9hcl9pdGVtc2l6ZShjb25zdCB2b2lkICpiYXNlKQp7CiAgICBhc3NlcnQoYmFzZSAhPSAwKTsKICAgIHJldHVybiBfQkFTRV9UT19TRUxGKGJhc2UpLT5pdGVtc2l6ZTsKfQoKc2l6ZV90IF9hcl9jYXBhY2l0eShjb25zdCB2b2lkICpiYXNlKQp7CiAgICBhc3NlcnQoYmFzZSAhPSAwKTsKICAgIHJldHVybiBfQkFTRV9UT19TRUxGKGJhc2UpLT5jYXBhY2l0eTsKfQoKdm9pZCAoKl9hcl9wdXRpdGVtKGNvbnN0IHZvaWQgKmJhc2UpKShjb25zdCB2b2lkICosIEZJTEUgKikKewogICAgYXNzZXJ0KGJhc2UgIT0gMCk7CiAgICByZXR1cm4gX0JBU0VfVE9fU0VMRihiYXNlKS0+cHV0aXRlbTsKfQoKdm9pZCBfYXJfc2V0X3B1dGl0ZW0odm9pZCAqYmFzZSwgdm9pZCAoKnB1dGl0ZW0pKGNvbnN0IHZvaWQgKiwgRklMRSAqKSkKewogICAgYXNzZXJ0KGJhc2UgIT0gMCk7CiAgICBfQkFTRV9UT19TRUxGKGJhc2UpLT5wdXRpdGVtID0gcHV0aXRlbTsKfQoKY29uc3Qgdm9pZCAqX2FyX2F0X2MoY29uc3Qgdm9pZCAqYmFzZSwgcHRyZGlmZl90IGkpCnsKICAgIGFzc2VydChiYXNlICE9IDApOwogICAgY29uc3QgX0hlYWRlciAqc2VsZiA9IF9CQVNFX1RPX1NFTEYoYmFzZSk7CgogICAgc2l6ZV90IHNpemUgPSBzZWxmLT5zaXplOwogICAgc2l6ZV90IGogPSAoaSA8IDApID8gaSArIHNpemUgOiAoc2l6ZV90KWk7CiAgICBhc3NlcnQoaiA8IHNpemUpOwogICAgcmV0dXJuIChjb25zdCBjaGFyKiliYXNlICsgaipzZWxmLT5pdGVtc2l6ZTsKfQoKdm9pZCAqX2FyX2F0KHZvaWQgKmJhc2UsIHB0cmRpZmZfdCBpKQp7CiAgICByZXR1cm4gKHZvaWQqKV9hcl9hdF9jKGJhc2UsIGkpOwp9Cgp2b2lkICpfYXJfcmVzZXJ2ZSh2b2lkICpiYXNlLCBzaXplX3QgY2FwYWNpdHkpCnsKICAgIC8vIEVuc3VyZSBhcnJheSBoYXMgZW5vdWdoIG1lbW9yeSBmb3IgY2FwYWNpdHkgaXRlbXMuCgogICAgYXNzZXJ0KGJhc2UgIT0gMCk7CiAgICBfSGVhZGVyICpzZWxmID0gX0JBU0VfVE9fU0VMRihiYXNlKTsKCiAgICBpZiAoY2FwYWNpdHkgPiBzZWxmLT5jYXBhY2l0eSkKICAgIHsKICAgICAgICBzZWxmID0gcmVhbGxvYyhzZWxmLCBzaXplb2YgKnNlbGYgKyBjYXBhY2l0eSpzZWxmLT5pdGVtc2l6ZSk7CiAgICAgICAgYXNzZXJ0KHNlbGYgIT0gMCk7CiAgICAgICAgc2VsZi0+Y2FwYWNpdHkgPSBjYXBhY2l0eTsKICAgIH0KICAgIHJldHVybiBfU0VMRl9UT19CQVNFKHNlbGYpOwp9Cgp2b2lkICpfYXJfcmVzaXplKHZvaWQgKmJhc2UsIHNpemVfdCBzaXplLCBjb25zdCB2b2lkICpmaWxsKQp7CiAgICAvLyBDaGFuZ2UgYXJyYXkgc2l6ZSBhbmQgaW5pdGlhbGl6ZSBuZXdseSByZXZlYWxlZCBpdGVtcyB0byBzcGVjaWZpZWQgZmlsbAogICAgLy8gdmFsdWUuIElmIGZpbGwgaXMgbm90IHByb3ZpZGVkLCBpdGVtcyBhcmUgbm90IGluaXRpYWxpemVkLgoKICAgIGFzc2VydChiYXNlICE9IDApOwogICAgYmFzZSA9IF9hcl9yZXNlcnZlKGJhc2UsIHNpemUpOwoKICAgIF9IZWFkZXIgKnNlbGYgPSBfQkFTRV9UT19TRUxGKGJhc2UpOwogICAgc2l6ZV90IG9sZHNpemUgPSBzZWxmLT5zaXplOwogICAgc2VsZi0+c2l6ZSA9IHNpemU7CgogICAgaWYgKGZpbGwgIT0gMCAmJiBzaXplID4gb2xkc2l6ZSkKICAgICAgICBtZW1maWxsKF9hcl9hdChiYXNlLCBvbGRzaXplKSwgc2l6ZSAtIG9sZHNpemUsIHNlbGYtPml0ZW1zaXplLCBmaWxsKTsKICAgIHJldHVybiBiYXNlOwp9Cgp2b2lkICpfYXJfaW5zZXJ0KHZvaWQgKmJhc2UsIHNpemVfdCBpLCBjb25zdCB2b2lkICpmaXJzdCwgc2l6ZV90IG4pCnsKICAgIC8vIEluc2VydCBuIGl0ZW1zIHN0YXJ0aW5nIGF0IGZpcnN0IGludG8gYXJyYXkgYmVmb3JlIHBvc2l0aW9uIGkuCgogICAgYXNzZXJ0KGJhc2UgIT0gMCk7CiAgICBfSGVhZGVyICpzZWxmID0gX0JBU0VfVE9fU0VMRihiYXNlKTsKCiAgICBzaXplX3Qgb2xkc2l6ZSA9IHNlbGYtPnNpemU7CiAgICBhc3NlcnQob2xkc2l6ZSA+PSBpKTsKCiAgICBpZiAobiAhPSAwKQogICAgewogICAgICAgIHNpemVfdCBzaXplOwogICAgICAgIGlmIChfX2J1aWx0aW5fYWRkX292ZXJmbG93KG9sZHNpemUsIG4sICZzaXplKSkKICAgICAgICAgICAgYXNzZXJ0KDAgJiYgImludGVnZXIgb3ZlcmZsb3ciKTsKCiAgICAgICAgaWYgKHNpemUgPiBzZWxmLT5jYXBhY2l0eSkKICAgICAgICB7CiAgICAgICAgICAgIGJhc2UgPSBfYXJfcmVzZXJ2ZShiYXNlLCBNQVgoMipzZWxmLT5jYXBhY2l0eSwgc2l6ZSkpOwogICAgICAgICAgICBzZWxmID0gX0JBU0VfVE9fU0VMRihiYXNlKTsKICAgICAgICB9CiAgICAgICAgc2VsZi0+c2l6ZSA9IHNpemU7CiAgICAgICAgdm9pZCAqaXAgPSBfYXJfYXQoYmFzZSwgaSk7CgogICAgICAgIGlmIChvbGRzaXplID4gaSkKICAgICAgICAgICAgbWVtbW92ZShfYXJfYXQoYmFzZSwgaSArIG4pLCBpcCwgKG9sZHNpemUgLSBpKSpzZWxmLT5pdGVtc2l6ZSk7CiAgICAgICAgbWVtY3B5KGlwLCBmaXJzdCwgbipzZWxmLT5pdGVtc2l6ZSk7CiAgICB9CiAgICByZXR1cm4gYmFzZTsKfQoKdm9pZCBfYXJfcmVtb3ZlKHZvaWQgKmJhc2UsIHNpemVfdCBpLCBzaXplX3QgbikKewogICAgLy8gUmVtb3ZlIG4gaXRlbXMgZnJvbSBhcnJheSBzdGFydGluZyBhdCBwb3NpdGlvbiBpLgoKICAgIGFzc2VydChiYXNlICE9IDApOwogICAgX0hlYWRlciAqc2VsZiA9IF9CQVNFX1RPX1NFTEYoYmFzZSk7CgogICAgc2l6ZV90IG9sZHNpemUgPSBzZWxmLT5zaXplOwogICAgYXNzZXJ0KG9sZHNpemUgPj0gaSk7CgogICAgaWYgKG4gIT0gMCkKICAgIHsKICAgICAgICBzaXplX3QgajsKICAgICAgICBpZiAoX19idWlsdGluX2FkZF9vdmVyZmxvdyhpLCBuLCAmaikpCiAgICAgICAgICAgIGFzc2VydCgwICYmICJpbnRlZ2VyIG92ZXJmbG93Iik7CiAgICAgICAgYXNzZXJ0KG9sZHNpemUgPj0gaik7CgogICAgICAgIGlmIChvbGRzaXplID4gaikKICAgICAgICAgICAgbWVtbW92ZShfYXJfYXQoYmFzZSwgaSksIF9hcl9hdChiYXNlLCBqKSwgKG9sZHNpemUgLSBqKSpzZWxmLT5pdGVtc2l6ZSk7CiAgICAgICAgc2VsZi0+c2l6ZSA9IG9sZHNpemUgLSBuOwogICAgfQp9Cgp2b2lkICpfYXJfcHVzaCh2b2lkICpiYXNlLCBjb25zdCB2b2lkICppdGVtKQp7CiAgICByZXR1cm4gX2FyX2luc2VydChiYXNlLCBfYXJfc2l6ZShiYXNlKSwgaXRlbSwgMSk7Cn0KCnZvaWQgX2FyX3BvcCh2b2lkICpiYXNlKQp7CiAgICBfYXJfcmVtb3ZlKGJhc2UsIF9hcl9zaXplKGJhc2UpLTEsIDEpOwp9Cgp2b2lkIF9hcl9jbGVhcih2b2lkICpiYXNlKQp7CiAgICBfYXJfcmVzaXplKGJhc2UsIDAsIDApOwp9Cgp2b2lkIF9hcl9mcmVlKHZvaWQgKmJhc2UpCnsKICAgIGlmIChiYXNlICE9IDApCiAgICAgICAgZnJlZShfQkFTRV9UT19TRUxGKGJhc2UpKTsKfQoKdm9pZCAqX2FyX2luaXQoc2l6ZV90IGl0ZW1zaXplLCBzaXplX3QgY2FwYWNpdHkpCnsKICAgIC8vIENyZWF0ZSBhcnJheSB3aXRoIGVub3VnaCBtZW1vcnkgZm9yIGNhcGFjaXR5IGl0ZW1zLgoKICAgIF9IZWFkZXIgKnNlbGYgPSBtYWxsb2Moc2l6ZW9mICpzZWxmICsgY2FwYWNpdHkqaXRlbXNpemUpOwogICAgYXNzZXJ0KHNlbGYgIT0gMCk7CiAgICBzZWxmLT5zaXplID0gMDsKICAgIHNlbGYtPml0ZW1zaXplID0gaXRlbXNpemU7CiAgICBzZWxmLT5jYXBhY2l0eSA9IGNhcGFjaXR5OwogICAgc2VsZi0+cHV0aXRlbSA9IDA7CiAgICByZXR1cm4gX1NFTEZfVE9fQkFTRShzZWxmKTsKfQoKdm9pZCAqX2FyX2luaXRfc2l6ZShzaXplX3QgaXRlbXNpemUsIHNpemVfdCBzaXplLCBjb25zdCB2b2lkICpmaWxsKQp7CiAgICAvLyBDcmVhdGUgd2l0aCBzaXplIGl0ZW1zIGFuZCBpbml0aWFsaXplIHdpdGggc3BlY2lmaWVkIGZpbGwgdmFsdWUuCgogICAgcmV0dXJuIF9hcl9yZXNpemUoX2FyX2luaXQoaXRlbXNpemUsIHNpemUpLCBzaXplLCBmaWxsKTsKfQoKdm9pZCAqX2FyX2luaXRfY29weShjb25zdCB2b2lkICpvdGhlcl9iYXNlLCBzaXplX3QgY2FwYWNpdHkpCnsKICAgIC8vIENyZWF0ZSBjb3B5IG9mIGFuIGFycmF5IHdpdGggYXQgbGVhc3QgY2FwYWNpdHkgaXRlbXMgcmVzZXJ2ZWQuCgogICAgYXNzZXJ0KG90aGVyX2Jhc2UgIT0gMCk7CiAgICBjb25zdCBfSGVhZGVyICpvdGhlciA9IF9CQVNFX1RPX1NFTEYob3RoZXJfYmFzZSk7CgogICAgdm9pZCAqYmFzZSA9IF9hcl9pbml0KG90aGVyLT5pdGVtc2l6ZSwgTUFYKG90aGVyLT5zaXplLCBjYXBhY2l0eSkpOwogICAgcmV0dXJuIF9hcl9pbnNlcnQoYmFzZSwgMCwgb3RoZXJfYmFzZSwgb3RoZXItPnNpemUpOwp9Cgp2b2lkIF9hcl9wcmludChjb25zdCB2b2lkICpiYXNlLCBGSUxFICpzdHJlYW0pCnsKICAgIGFzc2VydChiYXNlICE9IDApOwogICAgY29uc3QgX0hlYWRlciAqc2VsZiA9IF9CQVNFX1RPX1NFTEYoYmFzZSk7CgogICAgdm9pZCAoKnB1dGl0ZW0pKGNvbnN0IHZvaWQgKiwgRklMRSAqKSA9IHNlbGYtPnB1dGl0ZW07CiAgICBhc3NlcnQocHV0aXRlbSAhPSAwKTsKCiAgICBzaXplX3QgbiA9IHNlbGYtPnNpemU7CgogICAgZnB1dGMoJ3snLCBzdHJlYW0pOwogICAgaWYgKG4gIT0gMCkKICAgIHsKICAgICAgICBmb3IgKHNpemVfdCBpID0gMDs7KQogICAgICAgIHsKICAgICAgICAgICAgcHV0aXRlbShfYXJfYXRfYyhiYXNlLCBpKSwgc3RyZWFtKTsKICAgICAgICAgICAgaWYgKCsraSA9PSBuKSBicmVhazsKICAgICAgICAgICAgZnB1dHMoIiwgIiwgc3RyZWFtKTsKICAgICAgICB9CiAgICB9CiAgICBmcHV0YygnfScsIHN0cmVhbSk7Cn0KCnZvaWQgX2FyX3ByaW50bG4oY29uc3Qgdm9pZCAqYmFzZSwgRklMRSAqc3RyZWFtKQp7CiAgICBfYXJfcHJpbnQoYmFzZSwgc3RyZWFtKTsgZnB1dGMoJ1xuJywgc3RyZWFtKTsKfQoKLy8KLy8gTWFpbi4KLy8KCnZvaWQgdGVzdF9pbml0X2ZyZWUodm9pZCkKewogICAgcHJpbnRmKCI8JXM+XG4iLCBfX2Z1bmNfXyk7CgogICAgLy8gSW5pdC4KCiAgICBpbnQgKmEgPSAwOwogICAgYXJfaW5pdChhLCAwKTsKICAgIGFzc2VydChhcl9zaXplKGEpID09IDApOwogICAgYXNzZXJ0KGFyX2l0ZW1zaXplKGEpID09IHNpemVvZigqYSkpOwogICAgYXNzZXJ0KGFyX2NhcGFjaXR5KGEpID09IDApOwoKICAgIGFyX2ZyZWUoYSk7CiAgICBhc3NlcnQoYSA9PSAwKTsKCiAgICAvLyBJbml0IChjYXBhY2l0eSkuCgogICAgYXJfaW5pdChhLCA4KTsKICAgIGFzc2VydChhcl9zaXplKGEpID09IDApOwogICAgYXNzZXJ0KGFyX2l0ZW1zaXplKGEpID09IHNpemVvZigqYSkpOwogICAgYXNzZXJ0KGFyX2NhcGFjaXR5KGEpID09IDgpOwoKICAgIGFyX2ZyZWUoYSk7CiAgICBhc3NlcnQoYSA9PSAwKTsKCiAgICAvLyBJbml0IHNpemUuCgogICAgYXJfaW5pdF9zaXplKGEsIDMsIDEyMyk7CiAgICBhc3NlcnQoYXJfc2l6ZShhKSA9PSAzKTsKICAgIGFzc2VydChhcl9pdGVtc2l6ZShhKSA9PSBzaXplb2YoKmEpKTsKICAgIGFzc2VydChhcl9jYXBhY2l0eShhKSA9PSAzKTsKCiAgICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IDM7IGkrKykKICAgICAgICBhc3NlcnQoYXJfYXQoYSwgaSkgPT0gMTIzKTsKCiAgICAvLyBJbml0IGNvcHkuCgogICAgaW50ICpiID0gMDsKICAgIGFyX2luaXRfY29weShiLCBhLCAwKTsKCiAgICBhcl9mcmVlKGEpOwogICAgYXNzZXJ0KGEgPT0gMCk7CgogICAgYXNzZXJ0KGFyX3NpemUoYikgPT0gMyk7CiAgICBhc3NlcnQoYXJfaXRlbXNpemUoYikgPT0gc2l6ZW9mKCpiKSk7CiAgICBhc3NlcnQoYXJfY2FwYWNpdHkoYikgPT0gMyk7CgogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCAzOyBpKyspCiAgICAgICAgYXNzZXJ0KGFyX2F0KGIsIGkpID09IDEyMyk7CgogICAgLy8gSW5pdCBjb3B5IChjYXBhY2l0eSkuCgogICAgYXJfaW5pdF9jb3B5KGEsIGIsIDgpOwoKICAgIGFyX2ZyZWUoYik7CiAgICBhc3NlcnQoYiA9PSAwKTsKCiAgICBhc3NlcnQoYXJfc2l6ZShhKSA9PSAzKTsKICAgIGFzc2VydChhcl9pdGVtc2l6ZShhKSA9PSBzaXplb2YoKmEpKTsKICAgIGFzc2VydChhcl9jYXBhY2l0eShhKSA9PSA4KTsKCiAgICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IDM7IGkrKykKICAgICAgICBhc3NlcnQoYXJfYXQoYSwgaSkgPT0gMTIzKTsKICAgIGFyX2ZyZWUoYSk7CiAgICBhc3NlcnQoYSA9PSAwKTsKCiAgICBwdXRzKCIuLk9rYXkiKTsKfQoKdm9pZCB0ZXN0X3B1c2hfcG9wKHZvaWQpCnsKICAgIHByaW50ZigiPCVzPlxuIiwgX19mdW5jX18pOwoKICAgIGludCAqYSA9IDA7CiAgICBhcl9pbml0KGEsIDApOwoKICAgIC8vIFB1c2ggKGJhY2spLgoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgODsgaSsrKQogICAgewogICAgICAgIGFyX3B1c2goYSwgaSk7CiAgICAgICAgYXNzZXJ0KGFyX3NpemUoYSkgPT0gKHNpemVfdClpKzEpOwogICAgICAgIGFzc2VydChhcl9hdChhLCAtMSkgPT0gaSk7CiAgICB9CgogICAgLy8gUG9wIChiYWNrKS4KCiAgICBmb3IgKGludCBpID0gOC0xOyBpID49IDA7IGktLSkKICAgIHsKICAgICAgICBhc3NlcnQoYXJfYXQoYSwgLTEpID09IGkpOwogICAgICAgIGFyX3BvcChhKTsKICAgICAgICBhc3NlcnQoYXJfc2l6ZShhKSA9PSAoc2l6ZV90KWkpOwogICAgfQoKICAgIGFyX2ZyZWUoYSk7CgogICAgcHV0cygiLi5Pa2F5Iik7Cn0KCnZvaWQgdGVzdF9pbnNlcnRfcmVtb3ZlKHZvaWQpCnsKICAgIHByaW50ZigiPCVzPlxuIiwgX19mdW5jX18pOwoKICAgIGludCAqYSA9IDA7CiAgICBhcl9pbml0KGEsIDApOwoKICAgIC8vIEluc2VydCBldmVuIChidWxrKS4KCiAgICBhcl9pbnNlcnQoYSwgMCwgUkVGX1QoaW50LCAwLCAyLCA0KSwgMyk7CiAgICBhc3NlcnQoYXJfc2l6ZShhKSA9PSAzKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMzsgaSsrKQogICAgICAgIGFzc2VydChhcl9hdChhLCBpKSA9PSAyKmkpOwoKICAgIC8vIEluc2VydCBvZGQgKHNpbmdsZSkuCgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCAzOyBpKyspCiAgICAgICAgYXJfaW5zZXJ0KGEsIDIqaSsxLCBSRUZfVChpbnQsIDIqaSsxKSwgMSk7CiAgICBhc3NlcnQoYXJfc2l6ZShhKSA9PSA2KTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgNjsgaSsrKQogICAgICAgIGFzc2VydChhcl9hdChhLCBpKSA9PSBpKTsKCiAgICAvLyBSZW1vdmUgZXZlbiAoc2luZ2xlKS4KCiAgICBmb3IgKGludCBpID0gMjsgaSA+PSAwOyBpLS0pCiAgICAgICAgYXJfcmVtb3ZlKGEsIDIqaSwgMSk7CiAgICBhc3NlcnQoYXJfc2l6ZShhKSA9PSAzKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMzsgaSsrKQogICAgICAgIGFzc2VydChhcl9hdChhLCBpKSA9PSAyKmkrMSk7CgogICAgLy8gUmVtb3ZlIG9kZCAoYnVsaykuCgogICAgYXJfcmVtb3ZlKGEsIDAsIDMpOwogICAgYXNzZXJ0KGFyX3NpemUoYSkgPT0gMCk7CiAgICBhcl9mcmVlKGEpOwoKICAgIHB1dHMoIi4uT2theSIpOwp9CgovLyAuLgoKdm9pZCBwdXRpdGVtX2FyKGNvbnN0IHZvaWQgKml0ZW0sIEZJTEUgKnN0cmVhbSkKewogICAgX2FyX3ByaW50KCooY29uc3Qgdm9pZCAqKilpdGVtLCBzdHJlYW0pOwp9Cgp2b2lkIHB1dGl0ZW1faW50KGNvbnN0IHZvaWQgKml0ZW0sIEZJTEUgKnN0cmVhbSkKewogICAgZnByaW50ZihzdHJlYW0sICIlZCIsICooY29uc3QgaW50ICopaXRlbSk7Cn0KCmludCAqaW90YShpbnQgbiwgaW50IHN0YXJ0LCBpbnQgc3RlcCkKewogICAgaW50ICphID0gMDsKICAgIGFyX2luaXQoYSwgTUFYKG4sIDApKTsKICAgIGFyX3NldF9wdXRpdGVtKGEsIHB1dGl0ZW1faW50KTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKQogICAgICAgIGFyX3B1c2goYSwgc3RhcnQgKyBpKnN0ZXApOwogICAgcmV0dXJuIGE7Cn0KCnZvaWQgc2hvd19wdXNoX3BvcCh2b2lkKQp7CiAgICBwcmludGYoIjwlcz5cbiIsIF9fZnVuY19fKTsKCiAgICBpbnQgKmEgPSAwOwogICAgYXJfaW5pdChhLCAwKTsKICAgIGFyX3NldF9wdXRpdGVtKGEsIHB1dGl0ZW1faW50KTsKCiAgICBpbnQgbiA9IDQ7CgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICB7CiAgICAgICAgYXJfcHVzaChhLCBpKTsKICAgICAgICBhcl9wcmludGxuKGEpOwogICAgfQoKICAgIHdoaWxlIChhcl9zaXplKGEpICE9IDApCiAgICB7CiAgICAgICAgYXJfcG9wKGEpOwogICAgICAgIGFyX3ByaW50bG4oYSk7CiAgICB9CgogICAgYXJfZnJlZShhKTsKfQoKdm9pZCBzaG93X2luc2VydF9yZW1vdmUodm9pZCkKewogICAgcHJpbnRmKCI8JXM+XG4iLCBfX2Z1bmNfXyk7CgogICAgaW50ICphID0gMDsKICAgIGFyX2luaXQoYSwgMCk7CiAgICBhcl9zZXRfcHV0aXRlbShhLCBwdXRpdGVtX2ludCk7CgogICAgaW50IG4gPSA0OwoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKQogICAgewogICAgICAgIGFyX2luc2VydChhLCBpLCBSRUZfVChpbnQsIGkrMSwgaSsxK24pLCAyKTsKICAgICAgICBhcl9wcmludGxuKGEpOwogICAgfQoKICAgIGZvciAoaW50IGkgPSBuLTE7IGkgPj0gMDsgaS0tKQogICAgewogICAgICAgIGFyX3JlbW92ZShhLCBpLCAyKTsKICAgICAgICBhcl9wcmludGxuKGEpOwogICAgfQoKICAgIGFyX2ZyZWUoYSk7Cn0KCnZvaWQgc2hvd19yZXNpemUodm9pZCkKewogICAgcHJpbnRmKCI8JXM+XG4iLCBfX2Z1bmNfXyk7CgogICAgaW50ICphID0gMDsKICAgIGFyX2luaXQoYSwgMCk7CiAgICBhcl9zZXRfcHV0aXRlbShhLCBwdXRpdGVtX2ludCk7CgogICAgaW50IG4gPSA0OwoKICAgIGZvciAoaW50IGkgPSAxOyBpIDw9IG47IGkrKykKICAgIHsKICAgICAgICBhcl9yZXNpemUoYSwgaSwgLWkpOwogICAgICAgIGFyX3ByaW50bG4oYSk7CiAgICAgICAgYXJfY2xlYXIoYSk7CiAgICB9CgogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgaSsrKQogICAgewogICAgICAgIGFyX3Jlc2l6ZShhLCBpLCAtaSk7CiAgICAgICAgYXJfcHJpbnRsbihhKTsKICAgIH0KCiAgICBhcl9mcmVlKGEpOwp9Cgp2b2lkIHNob3dfYXJyYXlfb2ZfYXJyYXkodm9pZCkKewogICAgcHJpbnRmKCI8JXM+XG4iLCBfX2Z1bmNfXyk7CgogICAgaW50ICoqYSA9IDA7CiAgICBhcl9pbml0KGEsIDApOwogICAgYXJfc2V0X3B1dGl0ZW0oYSwgcHV0aXRlbV9hcik7CgogICAgaW50IG4gPSA0OwoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKQogICAgewogICAgICAgIGludCBjb3VudCA9IGkrMTsKICAgICAgICBpbnQgc3RhcnQgPSBpKihpKzEpLzIrMTsKICAgICAgICBhcl9wdXNoKGEsIGlvdGEoY291bnQsIHN0YXJ0LCAxKSk7CiAgICAgICAgYXJfcHJpbnRsbihhKTsKICAgIH0KCiAgICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IGFyX3NpemUoYSk7IGkrKykKICAgICAgICBhcl9mcmVlKGFbaV0pOwogICAgYXJfZnJlZShhKTsKfQoKaW50IG1haW4odm9pZCkKewogICAgdGVzdF9pbml0X2ZyZWUoKTsKICAgIHRlc3RfcHVzaF9wb3AoKTsKICAgIHRlc3RfaW5zZXJ0X3JlbW92ZSgpOwoKICAgIHNob3dfcHVzaF9wb3AoKTsKICAgIHNob3dfaW5zZXJ0X3JlbW92ZSgpOwogICAgc2hvd19yZXNpemUoKTsKICAgIHNob3dfYXJyYXlfb2ZfYXJyYXkoKTsKICAgIHJldHVybiAwOwp9