From f403c41393f37d9e903957c680671cae9ca328dc Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Tue, 4 Sep 2007 23:03:03 +0000 Subject: [PATCH] Bidirectional map template code git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19918 dc483132-0cff-0310-8789-dd5450dbe970 --- src/util/t_bimap.pm | 194 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 src/util/t_bimap.pm diff --git a/src/util/t_bimap.pm b/src/util/t_bimap.pm new file mode 100644 index 000000000..111c24964 --- /dev/null +++ b/src/util/t_bimap.pm @@ -0,0 +1,194 @@ +package t_bimap; + +use strict; +use vars qw(@ISA); + +require t_template; +require t_array; + +@ISA=qw(t_template); + +my @parms = qw(NAME LEFT RIGHT LEFTCMP RIGHTCMP LEFTPRINT RIGHTPRINT); +my %defaults = (); +my $headertemplate = "/* + * bidirectional mapping table, add-only + * + * Parameters: + * NAME + * LEFT, RIGHT - types + * LEFTCMP, RIGHTCMP - comparison functions + * + * Methods: + * int init() - nonzero is error code, if any possible + * long size() + * void foreach(int (*)(LEFT, RIGHT, void*), void*) + * int add(LEFT, RIGHT) - 0 = success, -1 = allocation failure + * const *findleft() - null iff not found + * const *findright() + * void destroy() - destroys container, doesn't delete elements + * + * initial implementation: flat array of (left,right) pairs + */ + +struct __pair { + l; + r; +}; +"; +my $bodytemplate = join "", ; + +sub new { # no args + my $self = {}; + bless $self; + $self->init(\@parms, \%defaults, []); + return $self; +} + +sub output { + my ($self, $fh) = @_; + + my $a = new t_array; + $a->setparm("NAME", $self->{values}{"NAME"} . "__pairarray"); + $a->setparm("TYPE", "struct " . $self->{values}{"NAME"} . "__pair"); + + print $fh "/* start of ", ref($self), " header template */\n"; + print $fh $self->substitute($headertemplate); + print $fh "/* end of ", ref($self), " header template */\n"; + $a->output($fh); + print $fh "/* start of ", ref($self), " body template */\n"; + print $fh $self->substitute($bodytemplate); + print $fh "/* end of ", ref($self), " body template */\n"; +} + +1; + +__DATA__ + +/* for use in cases where text substitutions may not work, like putting + "const" before a type that turns out to be "char *" */ +typedef __left_t; +typedef __right_t; + +typedef struct { + __pairarray a; + long nextidx; +} ; + +static inline int +_init ( *m) +{ + m->nextidx = 0; + return __pairarray_init (&m->a); +} + +static inline long +_size ( *m) +{ + return __pairarray_size (&m->a); +} + +static inline void +_foreach ( *m, int (*fn)(, , void *), void *p) +{ + long i, sz; + sz = m->nextidx; + for (i = 0; i < sz; i++) { + struct __pair *pair; + pair = __pairarray_getaddr (&m->a, i); + if ((*fn)(pair->l, pair->r, p) != 0) + break; + } +} + +static inline int +_add ( *m, l, r) +{ + long i, sz; + struct __pair newpair; + int err; + + sz = m->nextidx; + /* Make sure we're not duplicating. */ + for (i = 0; i < sz; i++) { + struct __pair *pair; + pair = __pairarray_getaddr (&m->a, i); + assert ((*)(l, pair->l) != 0); + if ((*)(l, pair->l) == 0) + abort(); + assert ((*)(r, pair->r) != 0); + if ((*)(r, pair->r) == 0) + abort(); + } + newpair.l = l; + newpair.r = r; + if (sz >= LONG_MAX - 1) + return ENOMEM; + err = __pairarray_grow (&m->a, sz+1); + if (err) + return err; + __pairarray_set (&m->a, sz, newpair); + m->nextidx++; + return 0; +} + +static inline const __right_t * +_findleft ( *m, l) +{ + long i, sz; + sz = _size (m); + for (i = 0; i < sz; i++) { + struct __pair *pair; + pair = __pairarray_getaddr (&m->a, i); + if ((*)(l, pair->l) == 0) + return &pair->r; + } + return 0; +} + +static inline const __left_t * +_findright ( *m, r) +{ + long i, sz; + sz = _size (m); + for (i = 0; i < sz; i++) { + struct __pair *pair; + pair = __pairarray_getaddr (&m->a, i); + if ((*)(r, pair->r) == 0) + return &pair->l; + } + return 0; +} + +struct __printstat { + FILE *f; + int comma; +}; +static inline int +__printone ( l, r, void *p) +{ + struct __printstat *ps = p; + fprintf(ps->f, ps->comma ? ", (" : "("); + ps->comma = 1; + (*)(l, ps->f); + fprintf(ps->f, ","); + (*)(r, ps->f); + fprintf(ps->f, ")"); + return 0; +} + +static inline void +_printmap ( *m, FILE *f) +{ + struct __printstat ps; + ps.comma = 0; + ps.f = f; + fprintf(f, "("); + _foreach (m, __printone, &ps); + fprintf(f, ")"); +} + +static inline void +_destroy ( *m) +{ + __pairarray_destroy (&m->a); +} -- 2.26.2