From 2fa4b6e6df05990365066a0b286322502778d530 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Tue, 11 Jun 2024 20:58:00 +0100 Subject: libctf, include: new functions for looking up enumerators Three new functions for looking up the enum type containing a given enumeration constant, and optionally that constant's value. The simplest, ctf_lookup_enumerator, looks up a root-visible enumerator by name in one dict: if the dict contains multiple such constants (which is possible for dicts created by older versions of the libctf deduplicator), ECTF_DUPLICATE is returned. The next simplest, ctf_lookup_enumerator_next, is an iterator which returns all enumerators with a given name in a given dict, whether root-visible or not. The most elaborate, ctf_arc_lookup_enumerator_next, finds all enumerators with a given name across all dicts in an entire CTF archive, whether root-visible or not, starting looking in the shared parent dict; opened dicts are cached (as with all other ctf_arc_*lookup functions) so that repeated use does not incur repeated opening costs. All three of these return enumerator values as int64_t: unfortunately, API compatibility concerns prevent us from doing the same with the other older enum-related functions, which all return enumerator constant values as ints. We may be forced to add symbol-versioning compatibility aliases that fix the other functions in due course, bumping the soname for platforms that do not support such things. ctf_arc_lookup_enumerator_next is implemented as a nested ctf_archive_next iterator, and inside that, a nested ctf_lookup_enumerator_next iterator within each dict. To aid in this, add support to ctf_next_t iterators for iterators that are implemented in terms of two simultaneous nested iterators at once. (It has always been possible for callers to use as many nested or semi-overlapping ctf_next_t iterators as they need, which is one of the advantages of this style over the _iter style that calls a function for each thing iterated over: the iterator change here permits *ctf_next_t iterators themselves* to be implemented by iterating using multiple other iterators as part of their internal operation, transparently to the caller.) Also add a testcase that tests all these functions (which is fairly easy because ctf_arc_lookup_enumerator_next is implemented in terms of ctf_lookup_enumerator_next) in addition to enumeration addition in ctf_open()ed dicts, ctf_add_enumerator duplicate enumerator addition, and conflicting enumerator constant deduplication. include/ * ctf-api.h (ctf_lookup_enumerator): New. (ctf_lookup_enumerator_next): Likewise. (ctf_arc_lookup_enumerator_next): Likewise. libctf/ * libctf.ver: Add them. * ctf-impl.h (ctf_next_t) : New. * ctf-util.c (ctf_next_copy): Copy it. (ctf_next_destroy): Destroy it. * ctf-lookup.c (ctf_lookup_enumerator): New. (ctf_lookup_enumerator_next): New. * ctf-archive.c (ctf_arc_lookup_enumerator_next): New. * testsuite/libctf-lookup/enumerator-iteration.*: New test. * testsuite/libctf-lookup/enum-ctf-2.c: New test CTF, used by the above. --- libctf/ctf-util.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'libctf/ctf-util.c') diff --git a/libctf/ctf-util.c b/libctf/ctf-util.c index 3ea6de9..f75b1bf 100644 --- a/libctf/ctf-util.c +++ b/libctf/ctf-util.c @@ -262,6 +262,8 @@ ctf_next_destroy (ctf_next_t *i) free (i->u.ctn_sorted_hkv); if (i->ctn_next) ctf_next_destroy (i->ctn_next); + if (i->ctn_next_inner) + ctf_next_destroy (i->ctn_next_inner); free (i); } @@ -276,16 +278,35 @@ ctf_next_copy (ctf_next_t *i) return NULL; memcpy (i2, i, sizeof (struct ctf_next)); + if (i2->ctn_next) + { + i2->ctn_next = ctf_next_copy (i2->ctn_next); + if (i2->ctn_next == NULL) + goto err_next; + } + + if (i2->ctn_next_inner) + { + i2->ctn_next_inner = ctf_next_copy (i2->ctn_next_inner); + if (i2->ctn_next_inner == NULL) + goto err_next_inner; + } + if (i2->ctn_iter_fun == (void (*) (void)) ctf_dynhash_next_sorted) { size_t els = ctf_dynhash_elements ((ctf_dynhash_t *) i->cu.ctn_h); if ((i2->u.ctn_sorted_hkv = calloc (els, sizeof (ctf_next_hkv_t))) == NULL) - { - free (i2); - return NULL; - } + goto err_sorted_hkv; memcpy (i2->u.ctn_sorted_hkv, i->u.ctn_sorted_hkv, els * sizeof (ctf_next_hkv_t)); } return i2; + + err_sorted_hkv: + ctf_next_destroy (i2->ctn_next_inner); + err_next_inner: + ctf_next_destroy (i2->ctn_next); + err_next: + ctf_next_destroy (i2); + return NULL; } -- cgit v1.1