From: mdw Date: Sat, 17 Jun 2000 10:42:54 +0000 (+0000) Subject: Convenient table-driven extraction of structured keys. X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/commitdiff_plain/1aaed0baa0fb203218a0e20c1f776b679a4b7287 Convenient table-driven extraction of structured keys. --- diff --git a/key-fetch.c b/key-fetch.c new file mode 100644 index 0000000..9f4863a --- /dev/null +++ b/key-fetch.c @@ -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 + +#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 -------------------------------------------------*/