xref: /freebsd/crypto/krb5/src/util/t_array.pm (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubertpackage t_array;
2*7f2fe78bSCy Schubert
3*7f2fe78bSCy Schubertuse strict;
4*7f2fe78bSCy Schubertuse vars qw(@ISA);
5*7f2fe78bSCy Schubert
6*7f2fe78bSCy Schubert#require ktemplate;
7*7f2fe78bSCy Schubertrequire t_template;
8*7f2fe78bSCy Schubert
9*7f2fe78bSCy Schubert@ISA=qw(t_template);
10*7f2fe78bSCy Schubert
11*7f2fe78bSCy Schubertmy @parms = qw(NAME TYPE);
12*7f2fe78bSCy Schubertmy %defaults = ( );
13*7f2fe78bSCy Schubertmy @templatelines = <DATA>;
14*7f2fe78bSCy Schubert
15*7f2fe78bSCy Schubertsub new { # no args
16*7f2fe78bSCy Schubert    my $self = {};
17*7f2fe78bSCy Schubert    bless $self;
18*7f2fe78bSCy Schubert    $self->init(\@parms, \%defaults, \@templatelines);
19*7f2fe78bSCy Schubert    return $self;
20*7f2fe78bSCy Schubert}
21*7f2fe78bSCy Schubert
22*7f2fe78bSCy Schubert__DATA__
23*7f2fe78bSCy Schubert
24*7f2fe78bSCy Schubert/*
25*7f2fe78bSCy Schubert * array type, derived from template
26*7f2fe78bSCy Schubert *
27*7f2fe78bSCy Schubert * parameters:
28*7f2fe78bSCy Schubert * NAME: <NAME>
29*7f2fe78bSCy Schubert * TYPE: <TYPE>
30*7f2fe78bSCy Schubert *
31*7f2fe78bSCy Schubert * methods:
32*7f2fe78bSCy Schubert * int init() -> nonzero if fail initial allocation
33*7f2fe78bSCy Schubert * unsigned long size() -> nonnegative number of values stored
34*7f2fe78bSCy Schubert * int grow(newsize) -> negative if fail allocation, memset(,0,) new space
35*7f2fe78bSCy Schubert * <TYPE> *getaddr(idx) -> aborts if out of range
36*7f2fe78bSCy Schubert * void set(idx, value) -> aborts if out of range
37*7f2fe78bSCy Schubert * <TYPE> get(idx) -> value, or aborts if out of range
38*7f2fe78bSCy Schubert */
39*7f2fe78bSCy Schubert
40*7f2fe78bSCy Schubert#include <stdlib.h>
41*7f2fe78bSCy Schubert#include <errno.h>
42*7f2fe78bSCy Schubert#include <limits.h>
43*7f2fe78bSCy Schubert#include <string.h>
44*7f2fe78bSCy Schubert#include <stdint.h>
45*7f2fe78bSCy Schubert
46*7f2fe78bSCy Schubertstruct <NAME>__header {
47*7f2fe78bSCy Schubert    size_t allocated;
48*7f2fe78bSCy Schubert    <TYPE> *elts;
49*7f2fe78bSCy Schubert};
50*7f2fe78bSCy Schuberttypedef struct <NAME>__header <NAME>;
51*7f2fe78bSCy Schubert
52*7f2fe78bSCy Schubertstatic inline int
53*7f2fe78bSCy Schubert<NAME>_init(<NAME> *arr)
54*7f2fe78bSCy Schubert{
55*7f2fe78bSCy Schubert    arr->elts = calloc(10, sizeof(<TYPE>));
56*7f2fe78bSCy Schubert    if (arr->elts == NULL)
57*7f2fe78bSCy Schubert	return ENOMEM;
58*7f2fe78bSCy Schubert    arr->allocated = 10;
59*7f2fe78bSCy Schubert    return 0;
60*7f2fe78bSCy Schubert}
61*7f2fe78bSCy Schubert
62*7f2fe78bSCy Schubertstatic inline long
63*7f2fe78bSCy Schubert<NAME>_size(<NAME> *arr)
64*7f2fe78bSCy Schubert{
65*7f2fe78bSCy Schubert    return arr->allocated;
66*7f2fe78bSCy Schubert}
67*7f2fe78bSCy Schubert
68*7f2fe78bSCy Schubertstatic inline unsigned long
69*7f2fe78bSCy Schubert<NAME>_max_size(<NAME> *arr)
70*7f2fe78bSCy Schubert{
71*7f2fe78bSCy Schubert    size_t upper_bound;
72*7f2fe78bSCy Schubert
73*7f2fe78bSCy Schubert    upper_bound = SIZE_MAX / sizeof(*arr->elts);
74*7f2fe78bSCy Schubert    if (upper_bound > ULONG_MAX)
75*7f2fe78bSCy Schubert	upper_bound = ULONG_MAX;
76*7f2fe78bSCy Schubert    return (unsigned long) upper_bound;
77*7f2fe78bSCy Schubert}
78*7f2fe78bSCy Schubert
79*7f2fe78bSCy Schubertstatic inline int
80*7f2fe78bSCy Schubert<NAME>_grow(<NAME> *arr, unsigned long newcount)
81*7f2fe78bSCy Schubert{
82*7f2fe78bSCy Schubert    size_t oldsize = sizeof(*arr->elts) * arr->allocated;
83*7f2fe78bSCy Schubert    size_t newsize;
84*7f2fe78bSCy Schubert    void *ptr;
85*7f2fe78bSCy Schubert
86*7f2fe78bSCy Schubert    if (newcount > LONG_MAX)
87*7f2fe78bSCy Schubert	return -1;
88*7f2fe78bSCy Schubert    if (newcount < arr->allocated)
89*7f2fe78bSCy Schubert	return 0;
90*7f2fe78bSCy Schubert    if (newcount > <NAME>_max_size(arr))
91*7f2fe78bSCy Schubert	return -1;
92*7f2fe78bSCy Schubert
93*7f2fe78bSCy Schubert    newsize = sizeof(*arr->elts) * newcount;
94*7f2fe78bSCy Schubert    ptr = realloc(arr->elts, newsize);
95*7f2fe78bSCy Schubert    if (ptr == NULL)
96*7f2fe78bSCy Schubert	return -1;
97*7f2fe78bSCy Schubert    memset((char *)ptr + oldsize, 0, newsize - oldsize);
98*7f2fe78bSCy Schubert    arr->elts = ptr;
99*7f2fe78bSCy Schubert    arr->allocated = newcount;
100*7f2fe78bSCy Schubert    return 0;
101*7f2fe78bSCy Schubert}
102*7f2fe78bSCy Schubert
103*7f2fe78bSCy Schubertstatic inline <TYPE> *
104*7f2fe78bSCy Schubert<NAME>_getaddr (<NAME> *arr, long idx)
105*7f2fe78bSCy Schubert{
106*7f2fe78bSCy Schubert    if (idx < 0 || (unsigned long) idx >= arr->allocated)
107*7f2fe78bSCy Schubert	abort();
108*7f2fe78bSCy Schubert    return arr->elts + idx;
109*7f2fe78bSCy Schubert}
110*7f2fe78bSCy Schubert
111*7f2fe78bSCy Schubertstatic inline void
112*7f2fe78bSCy Schubert<NAME>_set (<NAME> *arr, long idx, <TYPE> value)
113*7f2fe78bSCy Schubert{
114*7f2fe78bSCy Schubert    <TYPE> *newvalp;
115*7f2fe78bSCy Schubert    newvalp = <NAME>_getaddr(arr, idx);
116*7f2fe78bSCy Schubert    *newvalp = value;
117*7f2fe78bSCy Schubert}
118*7f2fe78bSCy Schubert
119*7f2fe78bSCy Schubertstatic inline <TYPE>
120*7f2fe78bSCy Schubert<NAME>_get (<NAME> *arr, long idx)
121*7f2fe78bSCy Schubert{
122*7f2fe78bSCy Schubert    return *<NAME>_getaddr(arr, idx);
123*7f2fe78bSCy Schubert}
124*7f2fe78bSCy Schubert
125*7f2fe78bSCy Schubertstatic inline void
126*7f2fe78bSCy Schubert<NAME>_destroy (<NAME> *arr)
127*7f2fe78bSCy Schubert{
128*7f2fe78bSCy Schubert    free(arr->elts);
129*7f2fe78bSCy Schubert    arr->elts = 0;
130*7f2fe78bSCy Schubert}
131