xref: /freebsd/crypto/krb5/src/util/t_bimap.pm (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1package t_bimap;
2
3use strict;
4use vars qw(@ISA);
5
6require t_template;
7require t_array;
8
9@ISA=qw(t_template);
10
11my @parms = qw(NAME LEFT RIGHT LEFTCMP RIGHTCMP LEFTPRINT RIGHTPRINT);
12my %defaults = ();
13my $headertemplate = "/*
14 * bidirectional mapping table, add-only
15 *
16 * Parameters:
17 * NAME
18 * LEFT, RIGHT - types
19 * LEFTCMP, RIGHTCMP - comparison functions
20 *
21 * Methods:
22 * int init() - nonzero is error code, if any possible
23 * long size()
24 * void foreach(int (*)(LEFT, RIGHT, void*), void*)
25 * int add(LEFT, RIGHT) - 0 = success, -1 = allocation failure
26 * const <RIGHT> *findleft(<LEFT>) - null iff not found
27 * const <LEFT> *findright(<RIGHT>)
28 * void destroy() - destroys container, doesn't delete elements
29 *
30 * initial implementation: flat array of (left,right) pairs
31 */
32
33struct <NAME>__pair {
34    <LEFT> l;
35    <RIGHT> r;
36};
37";
38my $bodytemplate = join "", <DATA>;
39
40sub new { # no args
41    my $self = {};
42    bless $self;
43    $self->init(\@parms, \%defaults, []);
44    return $self;
45}
46
47sub output {
48    my ($self, $fh) = @_;
49
50    my $a = new t_array;
51    $a->setparm("NAME", $self->{values}{"NAME"} . "__pairarray");
52    $a->setparm("TYPE", "struct " . $self->{values}{"NAME"} . "__pair");
53
54    print $fh "/* start of ", ref($self), " header template */\n";
55    print $fh $self->substitute($headertemplate);
56    print $fh "/* end of ", ref($self), " header template */\n";
57    $a->output($fh);
58    print $fh "/* start of ", ref($self), " body template */\n";
59    print $fh $self->substitute($bodytemplate);
60    print $fh "/* end of ", ref($self), " body template */\n";
61}
62
631;
64
65__DATA__
66
67/* for use in cases where text substitutions may not work, like putting
68   "const" before a type that turns out to be "char *"  */
69typedef <LEFT> <NAME>__left_t;
70typedef <RIGHT> <NAME>__right_t;
71
72typedef struct {
73    <NAME>__pairarray a;
74    long nextidx;
75} <NAME>;
76
77static inline int
78<NAME>_init (<NAME> *m)
79{
80    m->nextidx = 0;
81    return <NAME>__pairarray_init (&m->a);
82}
83
84static inline long
85<NAME>_size (<NAME> *m)
86{
87    return <NAME>__pairarray_size (&m->a);
88}
89
90static inline void
91<NAME>_foreach (<NAME> *m, int (*fn)(<LEFT>, <RIGHT>, void *), void *p)
92{
93    long i, sz;
94    sz = m->nextidx;
95    for (i = 0; i < sz; i++) {
96	struct <NAME>__pair *pair;
97	pair = <NAME>__pairarray_getaddr (&m->a, i);
98	if ((*fn)(pair->l, pair->r, p) != 0)
99	    break;
100    }
101}
102
103static inline int
104<NAME>_add (<NAME> *m, <LEFT> l, <RIGHT> r)
105{
106    long i, sz;
107    struct <NAME>__pair newpair;
108    int err;
109
110    sz = m->nextidx;
111    /* Make sure we're not duplicating.  */
112    for (i = 0; i < sz; i++) {
113	struct <NAME>__pair *pair;
114	pair = <NAME>__pairarray_getaddr (&m->a, i);
115	assert ((*<LEFTCMP>)(l, pair->l) != 0);
116	if ((*<LEFTCMP>)(l, pair->l) == 0)
117	    abort();
118	assert ((*<RIGHTCMP>)(r, pair->r) != 0);
119	if ((*<RIGHTCMP>)(r, pair->r) == 0)
120	    abort();
121    }
122    newpair.l = l;
123    newpair.r = r;
124    if (sz >= LONG_MAX - 1)
125	return ENOMEM;
126    err = <NAME>__pairarray_grow (&m->a, sz+1);
127    if (err)
128	return err;
129    <NAME>__pairarray_set (&m->a, sz, newpair);
130    m->nextidx++;
131    return 0;
132}
133
134static inline const <NAME>__right_t *
135<NAME>_findleft (<NAME> *m, <LEFT> l)
136{
137    long i, sz;
138    sz = <NAME>_size (m);
139    for (i = 0; i < sz; i++) {
140	struct <NAME>__pair *pair;
141	pair = <NAME>__pairarray_getaddr (&m->a, i);
142	if ((*<LEFTCMP>)(l, pair->l) == 0)
143	    return &pair->r;
144    }
145    return 0;
146}
147
148static inline const <NAME>__left_t *
149<NAME>_findright (<NAME> *m, <RIGHT> r)
150{
151    long i, sz;
152    sz = <NAME>_size (m);
153    for (i = 0; i < sz; i++) {
154	struct <NAME>__pair *pair;
155	pair = <NAME>__pairarray_getaddr (&m->a, i);
156	if ((*<RIGHTCMP>)(r, pair->r) == 0)
157	    return &pair->l;
158    }
159    return 0;
160}
161
162struct <NAME>__printstat {
163    FILE *f;
164    int comma;
165};
166static inline int
167<NAME>__printone (<LEFT> l, <RIGHT> r, void *p)
168{
169    struct <NAME>__printstat *ps = p;
170    fprintf(ps->f, ps->comma ? ", (" : "(");
171    ps->comma = 1;
172    (*<LEFTPRINT>)(l, ps->f);
173    fprintf(ps->f, ",");
174    (*<RIGHTPRINT>)(r, ps->f);
175    fprintf(ps->f, ")");
176    return 0;
177}
178
179static inline void
180<NAME>_printmap (<NAME> *m, FILE *f)
181{
182    struct <NAME>__printstat ps;
183    ps.comma = 0;
184    ps.f = f;
185    fprintf(f, "(");
186    <NAME>_foreach (m, <NAME>__printone, &ps);
187    fprintf(f, ")");
188}
189
190static inline void
191<NAME>_destroy (<NAME> *m)
192{
193    <NAME>__pairarray_destroy (&m->a);
194}
195