xref: /freebsd/crypto/krb5/src/util/t_enum.pm (revision b670c9bafc0e31c7609969bf374b2e80bdc00211)
1package t_enum;
2
3use strict;
4use vars qw(@ISA);
5
6#require ktemplate;
7require t_template;
8require t_array;
9
10@ISA=qw(t_template);
11
12my @parms = qw(NAME TYPE COMPARE);
13my %defaults = ( );
14my @templatelines = <DATA>;
15
16sub new { # no args
17    my $self = {};
18    bless $self;
19    $self->init(\@parms, \%defaults, \@templatelines);
20    return $self;
21}
22
23sub output {
24    my ($self, $fh) = @_;
25    my $a = new t_array;
26    $a->setparm("NAME", $self->{values}{"NAME"} . "__enumerator_array");
27    $a->setparm("TYPE", $self->{values}{"TYPE"});
28    $a->output($fh);
29    $self->SUPER::output($fh);
30}
31
321;
33
34__DATA__
35
36/*
37 * an enumerated collection type, generated from template
38 *
39 * Methods:
40 * int init() -> returns nonzero on alloc failure
41 * long size()
42 * long find(match) -> -1 or index of any match
43 * long append(value) -> -1 or new index
44 * <TYPE> get(index) -> aborts if out of range
45 * void destroy() -> frees array data
46 *
47 * Errors adding elements don't distinguish between "out of memory"
48 * and "too big for size_t".
49 *
50 * Initial implementation: A flat array, reallocated as needed.  Our
51 * uses probably aren't going to get very large.
52 */
53
54struct <NAME>__enumerator {
55    <NAME>__enumerator_array a;
56    size_t used;       /* number of entries used, idx used-1 is last */
57};
58typedef struct <NAME>__enumerator <NAME>;
59
60static inline int
61<NAME>_init(<NAME> *en)
62{
63    en->used = 0;
64    return <NAME>__enumerator_array_init(&en->a);
65}
66
67static inline long
68<NAME>_size(<NAME> *en)
69{
70    return en->used;
71}
72
73static inline long
74<NAME>__s2l(size_t idx)
75{
76    long l;
77    if (idx > LONG_MAX)
78	abort();
79    l = idx;
80    if (l != idx)
81	abort();
82    return l;
83}
84
85static inline long
86<NAME>_find(<NAME> *en, <TYPE> value)
87{
88    size_t i;
89    for (i = 0; i < en->used; i++) {
90	if (<COMPARE> (value, <NAME>__enumerator_array_get(&en->a, <NAME>__s2l(i))) == 0)
91	    return i;
92    }
93    return -1;
94}
95
96static inline long
97<NAME>_append(<NAME> *en, <TYPE> value)
98{
99    if (en->used >= LONG_MAX - 1)
100	return -1;
101    if (en->used >= SIZE_MAX - 1)
102	return -1;
103    if (<NAME>__enumerator_array_size(&en->a) == en->used) {
104	if (<NAME>__enumerator_array_grow(&en->a, en->used + 1) < 0)
105	    return -1;
106    }
107    <NAME>__enumerator_array_set(&en->a, <NAME>__s2l(en->used), value);
108    en->used++;
109    return en->used-1;
110}
111
112static inline <TYPE>
113<NAME>_get(<NAME> *en, size_t idx)
114{
115    return <NAME>__enumerator_array_get(&en->a, <NAME>__s2l(idx));
116}
117
118static inline void
119<NAME>_destroy(<NAME> *en)
120{
121    <NAME>__enumerator_array_destroy(&en->a);
122    en->used = 0;
123}
124
125static inline void
126<NAME>_foreach(<NAME> *en, int (*fn)(size_t i, <TYPE> t, void *p), void *p)
127{
128    size_t i;
129    for (i = 0; i < en->used; i++) {
130	if (fn (i, <NAME>__enumerator_array_get(&en->a, <NAME>__s2l(i)), p) != 0)
131	    break;
132    }
133}
134