/**
* @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 - offsetof(_Header, _base)))
#define _SELF_TO_BASE(p) ((void *)(((_Header *)p)->_base))
typedef struct {
size_t size;
size_t itemsize;
size_t capacity;
void (*putitem)(const void *item, FILE *stream);
_Alignas(max_align_t) char _base[];
} _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;
if (i < 0) i += size;
return (const char *)base + i*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 test_resize(void)
{
int *a = 0;
ar_init(a, 0);
// Resize (with clear).
for (int i = 0; i < 3; i++)
{
int n = i+1;
ar_resize(a, n, i);
assert(ar_size
(a
) == (size_t)n
); for (int j = 0; j < n; j++)
ar_clear(a);
}
// Resize (without clear).
for (int i = 0; i < 3; i++)
{
int n = i+1;
ar_resize(a, n, i);
assert(ar_size
(a
) == (size_t)n
); for (int j = 0; j < n; j++)
}
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();
test_resize();
show_push_pop();
show_insert_remove();
show_resize();
show_array_of_array();
return 0;
}
LyoqCiAqIEBmaWxlIGFycmF5LjAwMi5jCiAqIEBpbmdyb3VwIGV4cGVyaW1lbnRhbAogKiBEeW5hbWljIGFycmF5IHVzaW5nIGhpZGRlbiBoZWFkZXIuCiAqIEBkYXRlIDA4LzEzLzIwMjYKICovCgojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxzdGRkZWYuaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDxzdGRpby5oPgoKLy8KLy8gVXRpbGl0eS4KLy8KCiNkZWZpbmUgUkVGX1QoVCwgLi4uKSBcCiAgICAoKFRbXSl7X19WQV9BUkdTX199KQoKI2RlZmluZSBERVJFRl9UKFQsIHApIFwKICAgICgoKFQgKikodm9pZCAqKShwKSlbMF0pCgojZGVmaW5lIE1BWChhLCBiKSBcCih7IF9fYXV0b190eXBlIF94ID0gKGEpOyBfX2F1dG9fdHlwZSBfeSA9IChiKTsgXAogICAoX3kgPiBfeCkgPyBfeSA6IF94OyB9KQoKdm9pZCAqbWVtZmlsbCh2b2lkICpiYXNlLCBzaXplX3Qgbiwgc2l6ZV90IHNpemUsIGNvbnN0IHZvaWQgKmZpbGwpCnsKICAgIGlmIChuKnNpemUgIT0gMCkKICAgIHsKICAgICAgICBtZW1tb3ZlKGJhc2UsIGZpbGwsIHNpemUpOwogICAgICAgIHNpemVfdCBpID0gMTsKICAgICAgICBmb3IgKDsgaSA8PSBuLzI7IGkgKj0gMikKICAgICAgICAgICAgbWVtY3B5KChjaGFyICopYmFzZSArIGkqc2l6ZSwgYmFzZSwgaSpzaXplKTsKICAgICAgICBtZW1jcHkoKGNoYXIgKiliYXNlICsgaSpzaXplLCBiYXNlLCAobi1pKSpzaXplKTsKICAgIH0KICAgIHJldHVybiBiYXNlOwp9CgovLwovLyBBcnJheS4KLy8KCiNkZWZpbmUgYXJfc2l6ZShhKSBfYXJfc2l6ZShhKQojZGVmaW5lIGFyX2l0ZW1zaXplKGEpIF9hcl9pdGVtc2l6ZShhKQojZGVmaW5lIGFyX2NhcGFjaXR5KGEpIF9hcl9jYXBhY2l0eShhKQojZGVmaW5lIGFyX3B1dGl0ZW0oYSkgX2FyX3B1dGl0ZW0oYSkKI2RlZmluZSBhcl9zZXRfcHV0aXRlbShhLCBmKSBfYXJfc2V0X3B1dGl0ZW0oYSwgZikKI2RlZmluZSBhcl9hdChhLCBpKSAoKChfX3R5cGVvZl9fKCooYSkpICopX2FyX2F0KGEsIGkpKVswXSkKI2RlZmluZSBhcl9hdF9jKGEsIGkpICgoKGNvbnN0IF9fdHlwZW9mX18oKihhKSkgKilfYXJfYXRfYyhhLCBpKSlbMF0pCiNkZWZpbmUgYXJfcmVzZXJ2ZShhLCBuKSAoKGEpID0gX2FyX3Jlc2VydmUoYSwgbikpCiNkZWZpbmUgYXJfcmVzaXplKGEsIG4sIHYpICgoYSkgPSBfYXJfcmVzaXplKGEsIG4sIChfX3R5cGVvZl9fKCooYSkpW10pe3Z9KSkKI2RlZmluZSBhcl9pbnNlcnQoYSwgaSwgcywgbikgKChhKSA9IF9hcl9pbnNlcnQoYSwgaSwgcywgbikpCiNkZWZpbmUgYXJfcmVtb3ZlKGEsIGksIG4pIF9hcl9yZW1vdmUoYSwgaSwgbikKI2RlZmluZSBhcl9wdXNoKGEsIHYpICgoYSkgPSBfYXJfcHVzaChhLCAoX190eXBlb2ZfXygqKGEpKVtdKXt2fSkpCiNkZWZpbmUgYXJfcG9wKGEpIF9hcl9wb3AoYSkKI2RlZmluZSBhcl9jbGVhcihhKSBfYXJfY2xlYXIoYSkKI2RlZmluZSBhcl9mcmVlKGEpIChfYXJfZnJlZShhKSwgKGEpID0gMCkKI2RlZmluZSBhcl9pbml0KGEsIG4pICgoYSkgPSBfYXJfaW5pdChzaXplb2YgKihhKSwgbikpCiNkZWZpbmUgYXJfaW5pdF9zaXplKGEsIG4sIHYpICgoYSkgPSBfYXJfaW5pdF9zaXplKHNpemVvZiAqKGEpLCBuLCAoX190eXBlb2ZfXygqKGEpKVtdKXt2fSkpCiNkZWZpbmUgYXJfaW5pdF9jb3B5KGEsIGIsIG4pICgoYSkgPSAoX190eXBlb2ZfXygqKGIpKSAqKV9hcl9pbml0X2NvcHkoYiwgbikpCiNkZWZpbmUgYXJfcHJpbnQoYSkgX2FyX3ByaW50KGEsIHN0ZG91dCkKI2RlZmluZSBhcl9wcmludGxuKGEpIF9hcl9wcmludGxuKGEsIHN0ZG91dCkKCi8vIC4uCgojZGVmaW5lIF9CQVNFX1RPX1NFTEYocCkgKChfSGVhZGVyICopKChjaGFyICopcCAtIG9mZnNldG9mKF9IZWFkZXIsIF9iYXNlKSkpCiNkZWZpbmUgX1NFTEZfVE9fQkFTRShwKSAoKHZvaWQgKikoKChfSGVhZGVyICopcCktPl9iYXNlKSkKCnR5cGVkZWYgc3RydWN0IHsKICAgIHNpemVfdCBzaXplOwogICAgc2l6ZV90IGl0ZW1zaXplOwogICAgc2l6ZV90IGNhcGFjaXR5OwogICAgdm9pZCAoKnB1dGl0ZW0pKGNvbnN0IHZvaWQgKml0ZW0sIEZJTEUgKnN0cmVhbSk7CiAgICBfQWxpZ25hcyhtYXhfYWxpZ25fdCkgY2hhciBfYmFzZVtdOwp9IF9IZWFkZXI7CgpzaXplX3QgX2FyX3NpemUoY29uc3Qgdm9pZCAqYmFzZSkKewogICAgYXNzZXJ0KGJhc2UgIT0gMCk7CiAgICByZXR1cm4gX0JBU0VfVE9fU0VMRihiYXNlKS0+c2l6ZTsKfQoKc2l6ZV90IF9hcl9pdGVtc2l6ZShjb25zdCB2b2lkICpiYXNlKQp7CiAgICBhc3NlcnQoYmFzZSAhPSAwKTsKICAgIHJldHVybiBfQkFTRV9UT19TRUxGKGJhc2UpLT5pdGVtc2l6ZTsKfQoKc2l6ZV90IF9hcl9jYXBhY2l0eShjb25zdCB2b2lkICpiYXNlKQp7CiAgICBhc3NlcnQoYmFzZSAhPSAwKTsKICAgIHJldHVybiBfQkFTRV9UT19TRUxGKGJhc2UpLT5jYXBhY2l0eTsKfQoKdm9pZCAoKl9hcl9wdXRpdGVtKGNvbnN0IHZvaWQgKmJhc2UpKShjb25zdCB2b2lkICosIEZJTEUgKikKewogICAgYXNzZXJ0KGJhc2UgIT0gMCk7CiAgICByZXR1cm4gX0JBU0VfVE9fU0VMRihiYXNlKS0+cHV0aXRlbTsKfQoKdm9pZCBfYXJfc2V0X3B1dGl0ZW0odm9pZCAqYmFzZSwgdm9pZCAoKnB1dGl0ZW0pKGNvbnN0IHZvaWQgKiwgRklMRSAqKSkKewogICAgYXNzZXJ0KGJhc2UgIT0gMCk7CiAgICBfQkFTRV9UT19TRUxGKGJhc2UpLT5wdXRpdGVtID0gcHV0aXRlbTsKfQoKY29uc3Qgdm9pZCAqX2FyX2F0X2MoY29uc3Qgdm9pZCAqYmFzZSwgcHRyZGlmZl90IGkpCnsKICAgIGFzc2VydChiYXNlICE9IDApOwogICAgY29uc3QgX0hlYWRlciAqc2VsZiA9IF9CQVNFX1RPX1NFTEYoYmFzZSk7CgogICAgc2l6ZV90IHNpemUgPSBzZWxmLT5zaXplOwogICAgaWYgKGkgPCAwKSBpICs9IHNpemU7CiAgICBhc3NlcnQoKHNpemVfdClpIDwgc2l6ZSk7CiAgICByZXR1cm4gKGNvbnN0IGNoYXIgKiliYXNlICsgaSpzZWxmLT5pdGVtc2l6ZTsKfQoKdm9pZCAqX2FyX2F0KHZvaWQgKmJhc2UsIHB0cmRpZmZfdCBpKQp7CiAgICByZXR1cm4gKHZvaWQgKilfYXJfYXRfYyhiYXNlLCBpKTsKfQoKdm9pZCAqX2FyX3Jlc2VydmUodm9pZCAqYmFzZSwgc2l6ZV90IGNhcGFjaXR5KQp7CiAgICAvLyBFbnN1cmUgYXJyYXkgaGFzIGVub3VnaCBtZW1vcnkgZm9yIGNhcGFjaXR5IGl0ZW1zLgoKICAgIGFzc2VydChiYXNlICE9IDApOwogICAgX0hlYWRlciAqc2VsZiA9IF9CQVNFX1RPX1NFTEYoYmFzZSk7CgogICAgaWYgKGNhcGFjaXR5ID4gc2VsZi0+Y2FwYWNpdHkpCiAgICB7CiAgICAgICAgc2VsZiA9IHJlYWxsb2Moc2VsZiwgc2l6ZW9mICpzZWxmICsgY2FwYWNpdHkqc2VsZi0+aXRlbXNpemUpOwogICAgICAgIGFzc2VydChzZWxmICE9IDApOwogICAgICAgIHNlbGYtPmNhcGFjaXR5ID0gY2FwYWNpdHk7CiAgICB9CiAgICByZXR1cm4gX1NFTEZfVE9fQkFTRShzZWxmKTsKfQoKdm9pZCAqX2FyX3Jlc2l6ZSh2b2lkICpiYXNlLCBzaXplX3Qgc2l6ZSwgY29uc3Qgdm9pZCAqZmlsbCkKewogICAgLy8gQ2hhbmdlIGFycmF5IHNpemUgYW5kIGluaXRpYWxpemUgbmV3bHkgcmV2ZWFsZWQgaXRlbXMgdG8gc3BlY2lmaWVkIGZpbGwKICAgIC8vIHZhbHVlLiBJZiBmaWxsIGlzIG5vdCBwcm92aWRlZCwgaXRlbXMgYXJlIG5vdCBpbml0aWFsaXplZC4KCiAgICBhc3NlcnQoYmFzZSAhPSAwKTsKICAgIGJhc2UgPSBfYXJfcmVzZXJ2ZShiYXNlLCBzaXplKTsKCiAgICBfSGVhZGVyICpzZWxmID0gX0JBU0VfVE9fU0VMRihiYXNlKTsKICAgIHNpemVfdCBvbGRzaXplID0gc2VsZi0+c2l6ZTsKICAgIHNlbGYtPnNpemUgPSBzaXplOwoKICAgIGlmIChmaWxsICE9IDAgJiYgc2l6ZSA+IG9sZHNpemUpCiAgICAgICAgbWVtZmlsbChfYXJfYXQoYmFzZSwgb2xkc2l6ZSksIHNpemUgLSBvbGRzaXplLCBzZWxmLT5pdGVtc2l6ZSwgZmlsbCk7CiAgICByZXR1cm4gYmFzZTsKfQoKdm9pZCAqX2FyX2luc2VydCh2b2lkICpiYXNlLCBzaXplX3QgaSwgY29uc3Qgdm9pZCAqZmlyc3QsIHNpemVfdCBuKQp7CiAgICAvLyBJbnNlcnQgbiBpdGVtcyBzdGFydGluZyBhdCBmaXJzdCBpbnRvIGFycmF5IGJlZm9yZSBwb3NpdGlvbiBpLgoKICAgIGFzc2VydChiYXNlICE9IDApOwogICAgX0hlYWRlciAqc2VsZiA9IF9CQVNFX1RPX1NFTEYoYmFzZSk7CgogICAgc2l6ZV90IG9sZHNpemUgPSBzZWxmLT5zaXplOwogICAgYXNzZXJ0KG9sZHNpemUgPj0gaSk7CgogICAgaWYgKG4gIT0gMCkKICAgIHsKICAgICAgICBzaXplX3Qgc2l6ZTsKICAgICAgICBpZiAoX19idWlsdGluX2FkZF9vdmVyZmxvdyhvbGRzaXplLCBuLCAmc2l6ZSkpCiAgICAgICAgICAgIGFzc2VydCgwICYmICJpbnRlZ2VyIG92ZXJmbG93Iik7CgogICAgICAgIGlmIChzaXplID4gc2VsZi0+Y2FwYWNpdHkpCiAgICAgICAgewogICAgICAgICAgICBiYXNlID0gX2FyX3Jlc2VydmUoYmFzZSwgTUFYKDIqc2VsZi0+Y2FwYWNpdHksIHNpemUpKTsKICAgICAgICAgICAgc2VsZiA9IF9CQVNFX1RPX1NFTEYoYmFzZSk7CiAgICAgICAgfQogICAgICAgIHNlbGYtPnNpemUgPSBzaXplOwogICAgICAgIHZvaWQgKmlwID0gX2FyX2F0KGJhc2UsIGkpOwoKICAgICAgICBpZiAob2xkc2l6ZSA+IGkpCiAgICAgICAgICAgIG1lbW1vdmUoX2FyX2F0KGJhc2UsIGkgKyBuKSwgaXAsIChvbGRzaXplIC0gaSkqc2VsZi0+aXRlbXNpemUpOwogICAgICAgIG1lbWNweShpcCwgZmlyc3QsIG4qc2VsZi0+aXRlbXNpemUpOwogICAgfQogICAgcmV0dXJuIGJhc2U7Cn0KCnZvaWQgX2FyX3JlbW92ZSh2b2lkICpiYXNlLCBzaXplX3QgaSwgc2l6ZV90IG4pCnsKICAgIC8vIFJlbW92ZSBuIGl0ZW1zIGZyb20gYXJyYXkgc3RhcnRpbmcgYXQgcG9zaXRpb24gaS4KCiAgICBhc3NlcnQoYmFzZSAhPSAwKTsKICAgIF9IZWFkZXIgKnNlbGYgPSBfQkFTRV9UT19TRUxGKGJhc2UpOwoKICAgIHNpemVfdCBvbGRzaXplID0gc2VsZi0+c2l6ZTsKICAgIGFzc2VydChvbGRzaXplID49IGkpOwoKICAgIGlmIChuICE9IDApCiAgICB7CiAgICAgICAgc2l6ZV90IGo7CiAgICAgICAgaWYgKF9fYnVpbHRpbl9hZGRfb3ZlcmZsb3coaSwgbiwgJmopKQogICAgICAgICAgICBhc3NlcnQoMCAmJiAiaW50ZWdlciBvdmVyZmxvdyIpOwogICAgICAgIGFzc2VydChvbGRzaXplID49IGopOwoKICAgICAgICBpZiAob2xkc2l6ZSA+IGopCiAgICAgICAgICAgIG1lbW1vdmUoX2FyX2F0KGJhc2UsIGkpLCBfYXJfYXQoYmFzZSwgaiksIChvbGRzaXplIC0gaikqc2VsZi0+aXRlbXNpemUpOwogICAgICAgIHNlbGYtPnNpemUgPSBvbGRzaXplIC0gbjsKICAgIH0KfQoKdm9pZCAqX2FyX3B1c2godm9pZCAqYmFzZSwgY29uc3Qgdm9pZCAqaXRlbSkKewogICAgcmV0dXJuIF9hcl9pbnNlcnQoYmFzZSwgX2FyX3NpemUoYmFzZSksIGl0ZW0sIDEpOwp9Cgp2b2lkIF9hcl9wb3Aodm9pZCAqYmFzZSkKewogICAgX2FyX3JlbW92ZShiYXNlLCBfYXJfc2l6ZShiYXNlKS0xLCAxKTsKfQoKdm9pZCBfYXJfY2xlYXIodm9pZCAqYmFzZSkKewogICAgX2FyX3Jlc2l6ZShiYXNlLCAwLCAwKTsKfQoKdm9pZCBfYXJfZnJlZSh2b2lkICpiYXNlKQp7CiAgICBpZiAoYmFzZSAhPSAwKQogICAgICAgIGZyZWUoX0JBU0VfVE9fU0VMRihiYXNlKSk7Cn0KCnZvaWQgKl9hcl9pbml0KHNpemVfdCBpdGVtc2l6ZSwgc2l6ZV90IGNhcGFjaXR5KQp7CiAgICAvLyBDcmVhdGUgYXJyYXkgd2l0aCBlbm91Z2ggbWVtb3J5IGZvciBjYXBhY2l0eSBpdGVtcy4KCiAgICBfSGVhZGVyICpzZWxmID0gbWFsbG9jKHNpemVvZiAqc2VsZiArIGNhcGFjaXR5Kml0ZW1zaXplKTsKICAgIGFzc2VydChzZWxmICE9IDApOwogICAgc2VsZi0+c2l6ZSA9IDA7CiAgICBzZWxmLT5pdGVtc2l6ZSA9IGl0ZW1zaXplOwogICAgc2VsZi0+Y2FwYWNpdHkgPSBjYXBhY2l0eTsKICAgIHNlbGYtPnB1dGl0ZW0gPSAwOwogICAgcmV0dXJuIF9TRUxGX1RPX0JBU0Uoc2VsZik7Cn0KCnZvaWQgKl9hcl9pbml0X3NpemUoc2l6ZV90IGl0ZW1zaXplLCBzaXplX3Qgc2l6ZSwgY29uc3Qgdm9pZCAqZmlsbCkKewogICAgLy8gQ3JlYXRlIHdpdGggc2l6ZSBpdGVtcyBhbmQgaW5pdGlhbGl6ZSB3aXRoIHNwZWNpZmllZCBmaWxsIHZhbHVlLgoKICAgIHJldHVybiBfYXJfcmVzaXplKF9hcl9pbml0KGl0ZW1zaXplLCBzaXplKSwgc2l6ZSwgZmlsbCk7Cn0KCnZvaWQgKl9hcl9pbml0X2NvcHkoY29uc3Qgdm9pZCAqb3RoZXJfYmFzZSwgc2l6ZV90IGNhcGFjaXR5KQp7CiAgICAvLyBDcmVhdGUgY29weSBvZiBhbiBhcnJheSB3aXRoIGF0IGxlYXN0IGNhcGFjaXR5IGl0ZW1zIHJlc2VydmVkLgoKICAgIGFzc2VydChvdGhlcl9iYXNlICE9IDApOwogICAgY29uc3QgX0hlYWRlciAqb3RoZXIgPSBfQkFTRV9UT19TRUxGKG90aGVyX2Jhc2UpOwoKICAgIHZvaWQgKmJhc2UgPSBfYXJfaW5pdChvdGhlci0+aXRlbXNpemUsIE1BWChvdGhlci0+c2l6ZSwgY2FwYWNpdHkpKTsKICAgIHJldHVybiBfYXJfaW5zZXJ0KGJhc2UsIDAsIG90aGVyX2Jhc2UsIG90aGVyLT5zaXplKTsKfQoKdm9pZCBfYXJfcHJpbnQoY29uc3Qgdm9pZCAqYmFzZSwgRklMRSAqc3RyZWFtKQp7CiAgICBhc3NlcnQoYmFzZSAhPSAwKTsKICAgIGNvbnN0IF9IZWFkZXIgKnNlbGYgPSBfQkFTRV9UT19TRUxGKGJhc2UpOwoKICAgIHZvaWQgKCpwdXRpdGVtKShjb25zdCB2b2lkICosIEZJTEUgKikgPSBzZWxmLT5wdXRpdGVtOwogICAgYXNzZXJ0KHB1dGl0ZW0gIT0gMCk7CgogICAgc2l6ZV90IG4gPSBzZWxmLT5zaXplOwoKICAgIGZwdXRjKCd7Jywgc3RyZWFtKTsKICAgIGlmIChuICE9IDApCiAgICB7CiAgICAgICAgZm9yIChzaXplX3QgaSA9IDA7OykKICAgICAgICB7CiAgICAgICAgICAgIHB1dGl0ZW0oX2FyX2F0X2MoYmFzZSwgaSksIHN0cmVhbSk7CiAgICAgICAgICAgIGlmICgrK2kgPT0gbikgYnJlYWs7CiAgICAgICAgICAgIGZwdXRzKCIsICIsIHN0cmVhbSk7CiAgICAgICAgfQogICAgfQogICAgZnB1dGMoJ30nLCBzdHJlYW0pOwp9Cgp2b2lkIF9hcl9wcmludGxuKGNvbnN0IHZvaWQgKmJhc2UsIEZJTEUgKnN0cmVhbSkKewogICAgX2FyX3ByaW50KGJhc2UsIHN0cmVhbSk7IGZwdXRjKCdcbicsIHN0cmVhbSk7Cn0KCi8vCi8vIE1haW4uCi8vCgp2b2lkIHRlc3RfaW5pdF9mcmVlKHZvaWQpCnsKICAgIHByaW50ZigiPCVzPlxuIiwgX19mdW5jX18pOwoKICAgIC8vIEluaXQuCgogICAgaW50ICphID0gMDsKICAgIGFyX2luaXQoYSwgMCk7CiAgICBhc3NlcnQoYXJfc2l6ZShhKSA9PSAwKTsKICAgIGFzc2VydChhcl9pdGVtc2l6ZShhKSA9PSBzaXplb2YoKmEpKTsKICAgIGFzc2VydChhcl9jYXBhY2l0eShhKSA9PSAwKTsKCiAgICBhcl9mcmVlKGEpOwogICAgYXNzZXJ0KGEgPT0gMCk7CgogICAgLy8gSW5pdCAoY2FwYWNpdHkpLgoKICAgIGFyX2luaXQoYSwgOCk7CiAgICBhc3NlcnQoYXJfc2l6ZShhKSA9PSAwKTsKICAgIGFzc2VydChhcl9pdGVtc2l6ZShhKSA9PSBzaXplb2YoKmEpKTsKICAgIGFzc2VydChhcl9jYXBhY2l0eShhKSA9PSA4KTsKCiAgICBhcl9mcmVlKGEpOwogICAgYXNzZXJ0KGEgPT0gMCk7CgogICAgLy8gSW5pdCBzaXplLgoKICAgIGFyX2luaXRfc2l6ZShhLCAzLCAxMjMpOwogICAgYXNzZXJ0KGFyX3NpemUoYSkgPT0gMyk7CiAgICBhc3NlcnQoYXJfaXRlbXNpemUoYSkgPT0gc2l6ZW9mKCphKSk7CiAgICBhc3NlcnQoYXJfY2FwYWNpdHkoYSkgPT0gMyk7CgogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCAzOyBpKyspCiAgICAgICAgYXNzZXJ0KGFyX2F0KGEsIGkpID09IDEyMyk7CgogICAgLy8gSW5pdCBjb3B5LgoKICAgIGludCAqYiA9IDA7CiAgICBhcl9pbml0X2NvcHkoYiwgYSwgMCk7CgogICAgYXJfZnJlZShhKTsKICAgIGFzc2VydChhID09IDApOwoKICAgIGFzc2VydChhcl9zaXplKGIpID09IDMpOwogICAgYXNzZXJ0KGFyX2l0ZW1zaXplKGIpID09IHNpemVvZigqYikpOwogICAgYXNzZXJ0KGFyX2NhcGFjaXR5KGIpID09IDMpOwoKICAgIGZvciAoc2l6ZV90IGkgPSAwOyBpIDwgMzsgaSsrKQogICAgICAgIGFzc2VydChhcl9hdChiLCBpKSA9PSAxMjMpOwoKICAgIC8vIEluaXQgY29weSAoY2FwYWNpdHkpLgoKICAgIGFyX2luaXRfY29weShhLCBiLCA4KTsKCiAgICBhcl9mcmVlKGIpOwogICAgYXNzZXJ0KGIgPT0gMCk7CgogICAgYXNzZXJ0KGFyX3NpemUoYSkgPT0gMyk7CiAgICBhc3NlcnQoYXJfaXRlbXNpemUoYSkgPT0gc2l6ZW9mKCphKSk7CiAgICBhc3NlcnQoYXJfY2FwYWNpdHkoYSkgPT0gOCk7CgogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCAzOyBpKyspCiAgICAgICAgYXNzZXJ0KGFyX2F0KGEsIGkpID09IDEyMyk7CiAgICBhcl9mcmVlKGEpOwogICAgYXNzZXJ0KGEgPT0gMCk7CgogICAgcHV0cygiLi5Pa2F5Iik7Cn0KCnZvaWQgdGVzdF9wdXNoX3BvcCh2b2lkKQp7CiAgICBwcmludGYoIjwlcz5cbiIsIF9fZnVuY19fKTsKCiAgICBpbnQgKmEgPSAwOwogICAgYXJfaW5pdChhLCAwKTsKCiAgICAvLyBQdXNoIChiYWNrKS4KCiAgICBmb3IgKGludCBpID0gMDsgaSA8IDg7IGkrKykKICAgIHsKICAgICAgICBhcl9wdXNoKGEsIGkpOwogICAgICAgIGFzc2VydChhcl9zaXplKGEpID09IChzaXplX3QpaSsxKTsKICAgICAgICBhc3NlcnQoYXJfYXQoYSwgLTEpID09IGkpOwogICAgfQoKICAgIC8vIFBvcCAoYmFjaykuCgogICAgZm9yIChpbnQgaSA9IDgtMTsgaSA+PSAwOyBpLS0pCiAgICB7CiAgICAgICAgYXNzZXJ0KGFyX2F0KGEsIC0xKSA9PSBpKTsKICAgICAgICBhcl9wb3AoYSk7CiAgICAgICAgYXNzZXJ0KGFyX3NpemUoYSkgPT0gKHNpemVfdClpKTsKICAgIH0KCiAgICBhcl9mcmVlKGEpOwoKICAgIHB1dHMoIi4uT2theSIpOwp9Cgp2b2lkIHRlc3RfaW5zZXJ0X3JlbW92ZSh2b2lkKQp7CiAgICBwcmludGYoIjwlcz5cbiIsIF9fZnVuY19fKTsKCiAgICBpbnQgKmEgPSAwOwogICAgYXJfaW5pdChhLCAwKTsKCiAgICAvLyBJbnNlcnQgZXZlbiAoYnVsaykuCgogICAgYXJfaW5zZXJ0KGEsIDAsIFJFRl9UKGludCwgMCwgMiwgNCksIDMpOwogICAgYXNzZXJ0KGFyX3NpemUoYSkgPT0gMyk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IDM7IGkrKykKICAgICAgICBhc3NlcnQoYXJfYXQoYSwgaSkgPT0gMippKTsKCiAgICAvLyBJbnNlcnQgb2RkIChzaW5nbGUpLgoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMzsgaSsrKQogICAgICAgIGFyX2luc2VydChhLCAyKmkrMSwgUkVGX1QoaW50LCAyKmkrMSksIDEpOwogICAgYXNzZXJ0KGFyX3NpemUoYSkgPT0gNik7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IDY7IGkrKykKICAgICAgICBhc3NlcnQoYXJfYXQoYSwgaSkgPT0gaSk7CgogICAgLy8gUmVtb3ZlIGV2ZW4gKHNpbmdsZSkuCgogICAgZm9yIChpbnQgaSA9IDI7IGkgPj0gMDsgaS0tKQogICAgICAgIGFyX3JlbW92ZShhLCAyKmksIDEpOwogICAgYXNzZXJ0KGFyX3NpemUoYSkgPT0gMyk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IDM7IGkrKykKICAgICAgICBhc3NlcnQoYXJfYXQoYSwgaSkgPT0gMippKzEpOwoKICAgIC8vIFJlbW92ZSBvZGQgKGJ1bGspLgoKICAgIGFyX3JlbW92ZShhLCAwLCAzKTsKICAgIGFzc2VydChhcl9zaXplKGEpID09IDApOwogICAgYXJfZnJlZShhKTsKCiAgICBwdXRzKCIuLk9rYXkiKTsKfQoKdm9pZCB0ZXN0X3Jlc2l6ZSh2b2lkKQp7CiAgICBwcmludGYoIjwlcz5cbiIsIF9fZnVuY19fKTsKCiAgICBpbnQgKmEgPSAwOwogICAgYXJfaW5pdChhLCAwKTsKCiAgICAvLyBSZXNpemUgKHdpdGggY2xlYXIpLgoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMzsgaSsrKQogICAgewogICAgICAgIGludCBuID0gaSsxOwogICAgICAgIGFyX3Jlc2l6ZShhLCBuLCBpKTsKICAgICAgICBhc3NlcnQoYXJfc2l6ZShhKSA9PSAoc2l6ZV90KW4pOwogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgbjsgaisrKQogICAgICAgICAgICBhc3NlcnQoYXJfYXQoYSwgaikgPT0gaSk7CiAgICAgICAgYXJfY2xlYXIoYSk7CiAgICAgICAgYXNzZXJ0KGFyX3NpemUoYSkgPT0gMCk7CiAgICB9CgogICAgLy8gUmVzaXplICh3aXRob3V0IGNsZWFyKS4KCiAgICBmb3IgKGludCBpID0gMDsgaSA8IDM7IGkrKykKICAgIHsKICAgICAgICBpbnQgbiA9IGkrMTsKICAgICAgICBhcl9yZXNpemUoYSwgbiwgaSk7CiAgICAgICAgYXNzZXJ0KGFyX3NpemUoYSkgPT0gKHNpemVfdCluKTsKICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IG47IGorKykKICAgICAgICAgICAgYXNzZXJ0KGFyX2F0KGEsIGopID09IGopOwogICAgfQoKICAgIGFyX2ZyZWUoYSk7CgogICAgcHV0cygiLi5Pa2F5Iik7Cn0KCi8vIC4uCgp2b2lkIHB1dGl0ZW1fYXIoY29uc3Qgdm9pZCAqaXRlbSwgRklMRSAqc3RyZWFtKQp7CiAgICBfYXJfcHJpbnQoKihjb25zdCB2b2lkICoqKWl0ZW0sIHN0cmVhbSk7Cn0KCnZvaWQgcHV0aXRlbV9pbnQoY29uc3Qgdm9pZCAqaXRlbSwgRklMRSAqc3RyZWFtKQp7CiAgICBmcHJpbnRmKHN0cmVhbSwgIiVkIiwgKihjb25zdCBpbnQgKilpdGVtKTsKfQoKaW50ICppb3RhKGludCBuLCBpbnQgc3RhcnQsIGludCBzdGVwKQp7CiAgICBpbnQgKmEgPSAwOwogICAgYXJfaW5pdChhLCBNQVgobiwgMCkpOwogICAgYXJfc2V0X3B1dGl0ZW0oYSwgcHV0aXRlbV9pbnQpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgYXJfcHVzaChhLCBzdGFydCArIGkqc3RlcCk7CiAgICByZXR1cm4gYTsKfQoKdm9pZCBzaG93X3B1c2hfcG9wKHZvaWQpCnsKICAgIHByaW50ZigiPCVzPlxuIiwgX19mdW5jX18pOwoKICAgIGludCAqYSA9IDA7CiAgICBhcl9pbml0KGEsIDApOwogICAgYXJfc2V0X3B1dGl0ZW0oYSwgcHV0aXRlbV9pbnQpOwoKICAgIGludCBuID0gNDsKCiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykKICAgIHsKICAgICAgICBhcl9wdXNoKGEsIGkpOwogICAgICAgIGFyX3ByaW50bG4oYSk7CiAgICB9CgogICAgd2hpbGUgKGFyX3NpemUoYSkgIT0gMCkKICAgIHsKICAgICAgICBhcl9wb3AoYSk7CiAgICAgICAgYXJfcHJpbnRsbihhKTsKICAgIH0KCiAgICBhcl9mcmVlKGEpOwp9Cgp2b2lkIHNob3dfaW5zZXJ0X3JlbW92ZSh2b2lkKQp7CiAgICBwcmludGYoIjwlcz5cbiIsIF9fZnVuY19fKTsKCiAgICBpbnQgKmEgPSAwOwogICAgYXJfaW5pdChhLCAwKTsKICAgIGFyX3NldF9wdXRpdGVtKGEsIHB1dGl0ZW1faW50KTsKCiAgICBpbnQgbiA9IDQ7CgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICB7CiAgICAgICAgYXJfaW5zZXJ0KGEsIGksIFJFRl9UKGludCwgaSsxLCBpKzErbiksIDIpOwogICAgICAgIGFyX3ByaW50bG4oYSk7CiAgICB9CgogICAgZm9yIChpbnQgaSA9IG4tMTsgaSA+PSAwOyBpLS0pCiAgICB7CiAgICAgICAgYXJfcmVtb3ZlKGEsIGksIDIpOwogICAgICAgIGFyX3ByaW50bG4oYSk7CiAgICB9CgogICAgYXJfZnJlZShhKTsKfQoKdm9pZCBzaG93X3Jlc2l6ZSh2b2lkKQp7CiAgICBwcmludGYoIjwlcz5cbiIsIF9fZnVuY19fKTsKCiAgICBpbnQgKmEgPSAwOwogICAgYXJfaW5pdChhLCAwKTsKICAgIGFyX3NldF9wdXRpdGVtKGEsIHB1dGl0ZW1faW50KTsKCiAgICBpbnQgbiA9IDQ7CgogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgaSsrKQogICAgewogICAgICAgIGFyX3Jlc2l6ZShhLCBpLCAtaSk7CiAgICAgICAgYXJfcHJpbnRsbihhKTsKICAgICAgICBhcl9jbGVhcihhKTsKICAgIH0KCiAgICBmb3IgKGludCBpID0gMTsgaSA8PSBuOyBpKyspCiAgICB7CiAgICAgICAgYXJfcmVzaXplKGEsIGksIC1pKTsKICAgICAgICBhcl9wcmludGxuKGEpOwogICAgfQoKICAgIGFyX2ZyZWUoYSk7Cn0KCnZvaWQgc2hvd19hcnJheV9vZl9hcnJheSh2b2lkKQp7CiAgICBwcmludGYoIjwlcz5cbiIsIF9fZnVuY19fKTsKCiAgICBpbnQgKiphID0gMDsKICAgIGFyX2luaXQoYSwgMCk7CiAgICBhcl9zZXRfcHV0aXRlbShhLCBwdXRpdGVtX2FyKTsKCiAgICBpbnQgbiA9IDQ7CgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICB7CiAgICAgICAgaW50IGNvdW50ID0gaSsxOwogICAgICAgIGludCBzdGFydCA9IGkqKGkrMSkvMisxOwogICAgICAgIGFyX3B1c2goYSwgaW90YShjb3VudCwgc3RhcnQsIDEpKTsKICAgICAgICBhcl9wcmludGxuKGEpOwogICAgfQoKICAgIGZvciAoc2l6ZV90IGkgPSAwOyBpIDwgYXJfc2l6ZShhKTsgaSsrKQogICAgICAgIGFyX2ZyZWUoYVtpXSk7CiAgICBhcl9mcmVlKGEpOwp9CgppbnQgbWFpbih2b2lkKQp7CiAgICB0ZXN0X2luaXRfZnJlZSgpOwogICAgdGVzdF9wdXNoX3BvcCgpOwogICAgdGVzdF9pbnNlcnRfcmVtb3ZlKCk7CiAgICB0ZXN0X3Jlc2l6ZSgpOwoKICAgIHNob3dfcHVzaF9wb3AoKTsKICAgIHNob3dfaW5zZXJ0X3JlbW92ZSgpOwogICAgc2hvd19yZXNpemUoKTsKICAgIHNob3dfYXJyYXlfb2ZfYXJyYXkoKTsKICAgIHJldHVybiAwOwp9