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