summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2007-09-04 23:03:03 +0000
committerKen Raeburn <raeburn@mit.edu>2007-09-04 23:03:03 +0000
commitf403c41393f37d9e903957c680671cae9ca328dc (patch)
treec98982e225a24395cd527f997e283246bd8b61a9
parentf1d276113617068b3c54d9f452108a5e02a6b096 (diff)
Bidirectional map template code
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19918 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/util/t_bimap.pm194
1 files changed, 194 insertions, 0 deletions
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 <RIGHT> *findleft(<LEFT>) - null iff not found
+ * const <LEFT> *findright(<RIGHT>)
+ * void destroy() - destroys container, doesn't delete elements
+ *
+ * initial implementation: flat array of (left,right) pairs
+ */
+
+struct <NAME>__pair {
+ <LEFT> l;
+ <RIGHT> r;
+};
+";
+my $bodytemplate = join "", <DATA>;
+
+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> <NAME>__left_t;
+typedef <RIGHT> <NAME>__right_t;
+
+typedef struct {
+ <NAME>__pairarray a;
+ long nextidx;
+} <NAME>;
+
+static inline int
+<NAME>_init (<NAME> *m)
+{
+ m->nextidx = 0;
+ return <NAME>__pairarray_init (&m->a);
+}
+
+static inline long
+<NAME>_size (<NAME> *m)
+{
+ return <NAME>__pairarray_size (&m->a);
+}
+
+static inline void
+<NAME>_foreach (<NAME> *m, int (*fn)(<LEFT>, <RIGHT>, void *), void *p)
+{
+ long i, sz;
+ sz = m->nextidx;
+ for (i = 0; i < sz; i++) {
+ struct <NAME>__pair *pair;
+ pair = <NAME>__pairarray_getaddr (&m->a, i);
+ if ((*fn)(pair->l, pair->r, p) != 0)
+ break;
+ }
+}
+
+static inline int
+<NAME>_add (<NAME> *m, <LEFT> l, <RIGHT> r)
+{
+ long i, sz;
+ struct <NAME>__pair newpair;
+ int err;
+
+ sz = m->nextidx;
+ /* Make sure we're not duplicating. */
+ for (i = 0; i < sz; i++) {
+ struct <NAME>__pair *pair;
+ pair = <NAME>__pairarray_getaddr (&m->a, i);
+ assert ((*<LEFTCMP>)(l, pair->l) != 0);
+ if ((*<LEFTCMP>)(l, pair->l) == 0)
+ abort();
+ assert ((*<RIGHTCMP>)(r, pair->r) != 0);
+ if ((*<RIGHTCMP>)(r, pair->r) == 0)
+ abort();
+ }
+ newpair.l = l;
+ newpair.r = r;
+ if (sz >= LONG_MAX - 1)
+ return ENOMEM;
+ err = <NAME>__pairarray_grow (&m->a, sz+1);
+ if (err)
+ return err;
+ <NAME>__pairarray_set (&m->a, sz, newpair);
+ m->nextidx++;
+ return 0;
+}
+
+static inline const <NAME>__right_t *
+<NAME>_findleft (<NAME> *m, <LEFT> l)
+{
+ long i, sz;
+ sz = <NAME>_size (m);
+ for (i = 0; i < sz; i++) {
+ struct <NAME>__pair *pair;
+ pair = <NAME>__pairarray_getaddr (&m->a, i);
+ if ((*<LEFTCMP>)(l, pair->l) == 0)
+ return &pair->r;
+ }
+ return 0;
+}
+
+static inline const <NAME>__left_t *
+<NAME>_findright (<NAME> *m, <RIGHT> r)
+{
+ long i, sz;
+ sz = <NAME>_size (m);
+ for (i = 0; i < sz; i++) {
+ struct <NAME>__pair *pair;
+ pair = <NAME>__pairarray_getaddr (&m->a, i);
+ if ((*<RIGHTCMP>)(r, pair->r) == 0)
+ return &pair->l;
+ }
+ return 0;
+}
+
+struct <NAME>__printstat {
+ FILE *f;
+ int comma;
+};
+static inline int
+<NAME>__printone (<LEFT> l, <RIGHT> r, void *p)
+{
+ struct <NAME>__printstat *ps = p;
+ fprintf(ps->f, ps->comma ? ", (" : "(");
+ ps->comma = 1;
+ (*<LEFTPRINT>)(l, ps->f);
+ fprintf(ps->f, ",");
+ (*<RIGHTPRINT>)(r, ps->f);
+ fprintf(ps->f, ")");
+ return 0;
+}
+
+static inline void
+<NAME>_printmap (<NAME> *m, FILE *f)
+{
+ struct <NAME>__printstat ps;
+ ps.comma = 0;
+ ps.f = f;
+ fprintf(f, "(");
+ <NAME>_foreach (m, <NAME>__printone, &ps);
+ fprintf(f, ")");
+}
+
+static inline void
+<NAME>_destroy (<NAME> *m)
+{
+ <NAME>__pairarray_destroy (&m->a);
+}