* (c) 1999 Straylight/Edgeware
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
* This file is part of Catacomb.
*
* 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,
void key_split(key_data **kk)
{
key_data *k = *kk;
-
+
if (k->ref == 1)
return;
switch (k->e & KF_ENCMASK) {
return (k);
}
-/* --- @key_mewmp@ --- *
+/* --- @key_newmp@ --- *
*
* Arguments: @unsigned e@ = other encoding flags
* @mp *m@ = pointer to the value to set
return (0);
if (tag) *tag = SYM_NAME(ks);
if (kd) *kd = ks->k;
+ return (1);
}
/* --- @key_structset@, @key_structsteal@ --- *
unsigned f;
assert(((void)"Key is not structured", k->e == KENC_STRUCT));
+ assert(((void)"Key has multiple references", k->ref == 1));
if (!kd) {
ks = sym_find(&k->u.s, tag, -1, 0, 0);
if (ks) sym_remove(&k->u.s, ks);
key_drop(ks->k);
if (!stealp) KEY_INCREF(kd);
ks->k = kd;
- }
+ }
}
void key_structset(key_data *k, const char *tag, key_data *kd)
*
* Returns: Nonzero return code from function, or zero.
*
- * Use: Runs a function over all the leaves of a key.
+ * Use: Runs a function over all the leaves of a key.
*/
int key_do(key_data *k, const key_filter *kf, dstr *d,
}
}
+/* --- @key_copydata@ --- *
+ *
+ * Arguments: @key_data *k@ = key data to copy
+ * @const key_filter *kf@ = pointer to filter block
+ *
+ * Returns: Pointer to a copy of the data, or null if the root subkey
+ * didn't match the filter.
+ *
+ * Use: Copies a chunk of key data. Subkeys, whether they're
+ * structured or leaves, which don't match the filter aren't
+ * copied. The copy may or may not have structure in common
+ * with the original.
+ */
+
+static int structmatchp(key_data *k, const key_filter *kf)
+{
+ key_subkeyiter i;
+
+ if (!KEY_MATCH(k, kf)) return (0);
+ else if ((k->e & KF_ENCMASK) == KENC_STRUCT) return (1);
+ else {
+ for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &k); )
+ if (!structmatchp(k, kf)) return (0);
+ return (1);
+ }
+}
+
+key_data *key_copydata(key_data *k, const key_filter *kf)
+{
+ key_subkeyiter i;
+ const char *tag;
+ key_data *kd, *kkd;
+
+ /* --- Trivial cases --- */
+
+ if (!KEY_MATCH(k, kf))
+ return (0);
+ else if (structmatchp(k, kf)) {
+ key_incref(k);
+ return (k);
+ }
+
+ /* --- Copy a structured key recursively --- */
+
+ kkd = key_newstruct();
+ for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) {
+ if ((kd = key_copydata(kd, kf)) != 0)
+ key_structsteal(kkd, tag, kd);
+ }
+
+ /* --- Done --- */
+
+ return (kkd);
+}
+
/*----- That's all, folks -------------------------------------------------*/