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