11
my @parms = qw(NAME LEFT RIGHT LEFTCMP RIGHTCMP LEFTPRINT RIGHTPRINT);
13
my $headertemplate = "/*
14
* bidirectional mapping table, add-only
19
* LEFTCMP, RIGHTCMP - comparison functions
22
* int init() - nonzero is error code, if any possible
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
30
* initial implementation: flat array of (left,right) pairs
38
my $bodytemplate = join "", <DATA>;
43
$self->init(\@parms, \%defaults, []);
51
$a->setparm("NAME", $self->{values}{"NAME"} . "__pairarray");
52
$a->setparm("TYPE", "struct " . $self->{values}{"NAME"} . "__pair");
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";
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";
67
/* for use in cases where text substitutions may not work, like putting
68
"const" before a type that turns out to be "char *" */
69
typedef <LEFT> <NAME>__left_t;
70
typedef <RIGHT> <NAME>__right_t;
78
<NAME>_init (<NAME> *m)
81
return <NAME>__pairarray_init (&m->a);
85
<NAME>_size (<NAME> *m)
87
return <NAME>__pairarray_size (&m->a);
91
<NAME>_foreach (<NAME> *m, int (*fn)(<LEFT>, <RIGHT>, void *), void *p)
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)
104
<NAME>_add (<NAME> *m, <LEFT> l, <RIGHT> r)
107
struct <NAME>__pair newpair;
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)
118
assert ((*<RIGHTCMP>)(r, pair->r) != 0);
119
if ((*<RIGHTCMP>)(r, pair->r) == 0)
124
if (sz >= LONG_MAX - 1)
126
err = <NAME>__pairarray_grow (&m->a, sz+1);
129
<NAME>__pairarray_set (&m->a, sz, newpair);
134
static inline const <NAME>__right_t *
135
<NAME>_findleft (<NAME> *m, <LEFT> l)
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)
148
static inline const <NAME>__left_t *
149
<NAME>_findright (<NAME> *m, <RIGHT> r)
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)
162
struct <NAME>__printstat {
167
<NAME>__printone (<LEFT> l, <RIGHT> r, void *p)
169
struct <NAME>__printstat *ps = p;
170
fprintf(ps->f, ps->comma ? ", (" : "(");
172
(*<LEFTPRINT>)(l, ps->f);
174
(*<RIGHTPRINT>)(r, ps->f);
180
<NAME>_printmap (<NAME> *m, FILE *f)
182
struct <NAME>__printstat ps;
186
<NAME>_foreach (m, <NAME>__printone, &ps);
191
<NAME>_destroy (<NAME> *m)
193
<NAME>__pairarray_destroy (&m->a);