Convenient table-driven extraction of structured keys.
authormdw <mdw>
Sat, 17 Jun 2000 10:42:54 +0000 (10:42 +0000)
committermdw <mdw>
Sat, 17 Jun 2000 10:42:54 +0000 (10:42 +0000)
key-fetch.c [new file with mode: 0644]

diff --git a/key-fetch.c b/key-fetch.c
new file mode 100644 (file)
index 0000000..9f4863a
--- /dev/null
@@ -0,0 +1,214 @@
+/* -*-c-*-
+ *
+ * $Id: key-fetch.c,v 1.1 2000/06/17 10:42:54 mdw Exp $
+ *
+ * Higher-level key unpacking
+ *
+ * (c) 2000 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ * 
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: key-fetch.c,v $
+ * Revision 1.1  2000/06/17 10:42:54  mdw
+ * Convenient table-driven extraction of structured keys.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "key.h"
+#include "key-data.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @key_fetchinit@ --- *
+ *
+ * Arguments:  @const key_fetchdef *kf@ = pointer to base definition
+ *             @key_packstruct *kps@ = pointer to destination packing def
+ *             @void *p@ = pointer to destination block
+ *
+ * Returns:    Pointer to packing definition.
+ *
+ * Use:                Initializes a packing definition (@key_packdef@ structure).
+ *             If @kps@ is null on entry, an appropriately sized block is
+ *             allocated automatically.  Otherwise it must be large enough.
+ */
+
+static size_t kfcount(const key_fetchdef *kf)
+{
+  size_t n = 1;
+  while (kf->name) {
+    n++;
+    if (kf->kf)
+      n += kfcount(kf->kf);
+    kf++;
+  }
+  return (n);
+}
+
+key_packdef *key_fetchinit(const key_fetchdef *kf,
+                          key_packstruct *kp, void *p)
+{
+  size_t n = 1 + kfcount(kf);
+  key_packdef *kpd;
+  key_packstruct *kps;
+  char *cp = p;
+
+  /* --- If @kps@ is null, count the entries and allocate --- */
+
+  if (kp)
+    kp->name = 0;
+  else {
+    kp = xmalloc(n * sizeof(*kp));
+    kp->name = (char *)kp;
+  }
+
+  /* --- Fill in the top part --- */
+
+  kp->kp.kd.e = KENC_STRUCT;
+  kp->kp.p = &kp[1];
+  kpd = &kp->kp;
+
+  /* --- Initialize for the main loop --- */
+
+  kps = kp + n;
+  n = 0;
+  kp++;
+
+  /* --- Iterate over the entries in the table --- *
+   *
+   * The end of the target block is used as a stack to record where
+   * substructure is meant to occur.  The integer @n@ is the depth of the
+   * stack; @kps@ is a full descending stack pointer.  The @kp.p@ member of a
+   * stack element points back to an entry with substructure, the @kp.p@
+   * member of which refers to the @kf@ table for the substructure.
+   *
+   * This should all be about as clear as mud.
+   */
+
+  for (;;) {
+
+    /* --- Blat out a level's worth --- */
+
+    while (kf->name) {
+      kp->name = kf->name;
+      kp->kp.kd.e = kf->e;
+      if ((kf->e & KF_ENCMASK) != KENC_STRUCT)
+       kp->kp.p = cp + kf->off;
+      else {
+       (--kps)->kp.p = kp;
+       kp->kp.p = (void *)kf->kf;
+       n++;
+      }
+      kf++;
+      kp++;
+    }
+    (kp++)->name = 0;
+    if (!n)
+      break;
+
+    /* --- Pop an entry from the stack --- */
+
+    {
+      key_packstruct *kkp = (kps++)->kp.p;
+      kf = kkp->kp.p;
+      kkp->kp.p = kp;
+      n--;
+    }
+  }
+
+  /* --- We're done --- */
+
+  return (kpd);
+}
+
+/* --- @key_fetch@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key *k@ = key file containing desired key
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Fetches an unpacked key from a packed one.
+ */
+
+int key_fetch(key_packdef *kp, key *k)
+{
+  dstr d = DSTR_INIT;
+  int e;
+
+  key_fulltag(k, &d);
+  e = key_unpack(kp, &k->k, &d);
+  dstr_destroy(&d);
+  return (e);
+}
+
+/* --- @key_fetchbyname@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key_file *kf@ = key file containing desired key
+ *             @const char *tag@ = user's tag describing the key
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Fetches a named key from a key file and unpacks it
+ *             conveniently.
+ */
+
+int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag)
+{
+  dstr d = DSTR_INIT;
+  key_data *kd;
+  int e;
+
+  if (key_qtag(kf, tag, &d, 0, &kd))
+    e = KERR_NOTFOUND;
+  else
+    e = key_unpack(kp, kd, &d);
+  dstr_destroy(&d);
+  return (e);
+}
+
+/* --- @key_fetchdone@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a packing structure.  If the structure was allocated by
+ *             @key_fetchinit@ then it is freed.
+ */
+
+void key_fetchdone(key_packdef *kp)
+{
+  key_packstruct *kps = (key_packstruct *)(((char *)kp) -
+                                          offsetof(key_packstruct, kp));
+  key_unpackdone(kp);
+  if (kps->name)
+    free(kps);
+}  
+
+/*----- That's all, folks -------------------------------------------------*/