math/mpreduce.h: Missing include files.
[u/mdw/catacomb] / key / key-fetch.c
CommitLineData
1aaed0ba 1/* -*-c-*-
2 *
1aaed0ba 3 * Higher-level key unpacking
4 *
5 * (c) 2000 Straylight/Edgeware
6 */
7
45c0fd36 8/*----- Licensing notice --------------------------------------------------*
1aaed0ba 9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
45c0fd36 16 *
1aaed0ba 17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
45c0fd36 21 *
1aaed0ba 22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
1aaed0ba 28/*----- Header files ------------------------------------------------------*/
29
30#include <mLib/dstr.h>
31
32#include "key.h"
33#include "key-data.h"
34
35/*----- Main code ---------------------------------------------------------*/
36
37/* --- @key_fetchinit@ --- *
38 *
39 * Arguments: @const key_fetchdef *kf@ = pointer to base definition
40 * @key_packstruct *kps@ = pointer to destination packing def
41 * @void *p@ = pointer to destination block
42 *
43 * Returns: Pointer to packing definition.
44 *
45 * Use: Initializes a packing definition (@key_packdef@ structure).
46 * If @kps@ is null on entry, an appropriately sized block is
47 * allocated automatically. Otherwise it must be large enough.
48 */
49
50static size_t kfcount(const key_fetchdef *kf)
51{
52 size_t n = 1;
53 while (kf->name) {
54 n++;
55 if (kf->kf)
56 n += kfcount(kf->kf);
57 kf++;
58 }
59 return (n);
60}
61
62key_packdef *key_fetchinit(const key_fetchdef *kf,
63 key_packstruct *kp, void *p)
64{
65 size_t n = 1 + kfcount(kf);
66 key_packdef *kpd;
67 key_packstruct *kps;
68 char *cp = p;
69
70 /* --- If @kps@ is null, count the entries and allocate --- */
71
72 if (kp)
73 kp->name = 0;
74 else {
75 kp = xmalloc(n * sizeof(*kp));
76 kp->name = (char *)kp;
77 }
78
79 /* --- Fill in the top part --- */
80
ef13e9a4 81 kp->kp.e = KENC_STRUCT;
1aaed0ba 82 kp->kp.p = &kp[1];
ef13e9a4 83 kp->kp.kd = 0;
1aaed0ba 84 kpd = &kp->kp;
85
86 /* --- Initialize for the main loop --- */
87
88 kps = kp + n;
89 n = 0;
90 kp++;
91
92 /* --- Iterate over the entries in the table --- *
93 *
94 * The end of the target block is used as a stack to record where
95 * substructure is meant to occur. The integer @n@ is the depth of the
96 * stack; @kps@ is a full descending stack pointer. The @kp.p@ member of a
97 * stack element points back to an entry with substructure, the @kp.p@
98 * member of which refers to the @kf@ table for the substructure.
99 *
100 * This should all be about as clear as mud.
101 */
102
103 for (;;) {
104
105 /* --- Blat out a level's worth --- */
106
107 while (kf->name) {
108 kp->name = kf->name;
ef13e9a4 109 kp->kp.e = kf->e;
110 kp->kp.kd = 0;
1aaed0ba 111 if ((kf->e & KF_ENCMASK) != KENC_STRUCT)
112 kp->kp.p = cp + kf->off;
113 else {
114 (--kps)->kp.p = kp;
115 kp->kp.p = (void *)kf->kf;
116 n++;
117 }
118 kf++;
119 kp++;
120 }
121 (kp++)->name = 0;
122 if (!n)
123 break;
124
125 /* --- Pop an entry from the stack --- */
126
127 {
128 key_packstruct *kkp = (kps++)->kp.p;
129 kf = kkp->kp.p;
130 kkp->kp.p = kp;
131 n--;
132 }
133 }
134
135 /* --- We're done --- */
136
137 return (kpd);
138}
139
140/* --- @key_fetch@ --- *
141 *
142 * Arguments: @key_packdef *kp@ = pointer to packing structure
143 * @key *k@ = key file containing desired key
144 *
145 * Returns: Error code, or zero.
146 *
147 * Use: Fetches an unpacked key from a packed one.
148 */
149
150int key_fetch(key_packdef *kp, key *k)
151{
152 dstr d = DSTR_INIT;
153 int e;
154
155 key_fulltag(k, &d);
ef13e9a4 156 e = key_unpack(kp, k->k, &d);
1aaed0ba 157 dstr_destroy(&d);
158 return (e);
159}
160
161/* --- @key_fetchbyname@ --- *
162 *
163 * Arguments: @key_packdef *kp@ = pointer to packing structure
164 * @key_file *kf@ = key file containing desired key
165 * @const char *tag@ = user's tag describing the key
166 *
167 * Returns: Error code, or zero.
168 *
169 * Use: Fetches a named key from a key file and unpacks it
170 * conveniently.
171 */
172
173int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag)
174{
175 dstr d = DSTR_INIT;
ef13e9a4 176 key_data **kd;
1aaed0ba 177 int e;
178
179 if (key_qtag(kf, tag, &d, 0, &kd))
180 e = KERR_NOTFOUND;
181 else
ef13e9a4 182 e = key_unpack(kp, *kd, &d);
1aaed0ba 183 dstr_destroy(&d);
184 return (e);
185}
186
187/* --- @key_fetchdone@ --- *
188 *
189 * Arguments: @key_packdef *kp@ = pointer to packing structure
190 *
191 * Returns: ---
192 *
193 * Use: Frees a packing structure. If the structure was allocated by
194 * @key_fetchinit@ then it is freed.
195 */
196
197void key_fetchdone(key_packdef *kp)
198{
ef13e9a4 199 key_packstruct *kps =
200 (key_packstruct *)(((char *)kp) - offsetof(key_packstruct, kp));
1aaed0ba 201 key_unpackdone(kp);
202 if (kps->name)
12ed8a1f 203 xfree(kps);
45c0fd36 204}
1aaed0ba 205
206/*----- That's all, folks -------------------------------------------------*/