aboutsummaryrefslogtreecommitdiff
path: root/libctf/ctf-string.c
diff options
context:
space:
mode:
Diffstat (limited to 'libctf/ctf-string.c')
-rw-r--r--libctf/ctf-string.c61
1 files changed, 52 insertions, 9 deletions
diff --git a/libctf/ctf-string.c b/libctf/ctf-string.c
index 91ad2e3..9f0e540 100644
--- a/libctf/ctf-string.c
+++ b/libctf/ctf-string.c
@@ -103,7 +103,7 @@ ctf_str_create_atoms (ctf_dict_t *fp)
{
fp->ctf_str_atoms = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
free, ctf_str_free_atom);
- if (fp->ctf_str_atoms == NULL)
+ if (!fp->ctf_str_atoms)
return -ENOMEM;
if (!fp->ctf_prov_strtab)
@@ -113,6 +113,13 @@ ctf_str_create_atoms (ctf_dict_t *fp)
if (!fp->ctf_prov_strtab)
goto oom_prov_strtab;
+ if (!fp->ctf_str_pending_ref)
+ fp->ctf_str_pending_ref = ctf_dynset_create (htab_hash_pointer,
+ htab_eq_pointer,
+ NULL);
+ if (!fp->ctf_str_pending_ref)
+ goto oom_str_pending_ref;
+
errno = 0;
ctf_str_add (fp, "");
if (errno == ENOMEM)
@@ -123,6 +130,9 @@ ctf_str_create_atoms (ctf_dict_t *fp)
oom_str_add:
ctf_dynhash_destroy (fp->ctf_prov_strtab);
fp->ctf_prov_strtab = NULL;
+ oom_str_pending_ref:
+ ctf_dynset_destroy (fp->ctf_str_pending_ref);
+ fp->ctf_str_pending_ref = NULL;
oom_prov_strtab:
ctf_dynhash_destroy (fp->ctf_str_atoms);
fp->ctf_str_atoms = NULL;
@@ -135,8 +145,13 @@ ctf_str_free_atoms (ctf_dict_t *fp)
{
ctf_dynhash_destroy (fp->ctf_prov_strtab);
ctf_dynhash_destroy (fp->ctf_str_atoms);
+ ctf_dynset_destroy (fp->ctf_str_pending_ref);
}
+#define CTF_STR_ADD_REF 0x1
+#define CTF_STR_MAKE_PROVISIONAL 0x2
+#define CTF_STR_PENDING_REF 0x4
+
/* Add a string to the atoms table, copying the passed-in string. Return the
atom added. Return NULL only when out of memory (and do not touch the
passed-in string in that case). Possibly augment the ref list with the
@@ -144,7 +159,7 @@ ctf_str_free_atoms (ctf_dict_t *fp)
provisional strtab. */
static ctf_str_atom_t *
ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str,
- int add_ref, int make_provisional, uint32_t *ref)
+ int flags, uint32_t *ref)
{
char *newstr = NULL;
ctf_str_atom_t *atom = NULL;
@@ -152,7 +167,7 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str,
atom = ctf_dynhash_lookup (fp->ctf_str_atoms, str);
- if (add_ref)
+ if (flags & CTF_STR_ADD_REF)
{
if ((aref = malloc (sizeof (struct ctf_str_atom_ref))) == NULL)
return NULL;
@@ -161,8 +176,9 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str,
if (atom)
{
- if (add_ref)
+ if (flags & CTF_STR_ADD_REF)
{
+ ctf_dynset_remove (fp->ctf_str_pending_ref, (void *) ref);
ctf_list_append (&atom->csa_refs, aref);
fp->ctf_str_num_refs++;
}
@@ -182,7 +198,7 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str,
atom->csa_str = newstr;
atom->csa_snapshot_id = fp->ctf_snapshots;
- if (make_provisional)
+ if (flags & CTF_STR_MAKE_PROVISIONAL)
{
atom->csa_offset = fp->ctf_str_prov_offset;
@@ -193,8 +209,14 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str,
fp->ctf_str_prov_offset += strlen (atom->csa_str) + 1;
}
- if (add_ref)
+ if (flags & CTF_STR_PENDING_REF)
+ {
+ if (ctf_dynset_insert (fp->ctf_str_pending_ref, (void *) ref) < 0)
+ goto oom;
+ }
+ else if (flags & CTF_STR_ADD_REF)
{
+ ctf_dynset_remove (fp->ctf_str_pending_ref, (void *) ref);
ctf_list_append (&atom->csa_refs, aref);
fp->ctf_str_num_refs++;
}
@@ -222,7 +244,7 @@ ctf_str_add (ctf_dict_t *fp, const char *str)
if (!str)
str = "";
- atom = ctf_str_add_ref_internal (fp, str, FALSE, TRUE, 0);
+ atom = ctf_str_add_ref_internal (fp, str, CTF_STR_MAKE_PROVISIONAL, 0);
if (!atom)
return 0;
@@ -240,7 +262,26 @@ ctf_str_add_ref (ctf_dict_t *fp, const char *str, uint32_t *ref)
if (!str)
str = "";
- atom = ctf_str_add_ref_internal (fp, str, TRUE, TRUE, ref);
+ atom = ctf_str_add_ref_internal (fp, str, CTF_STR_ADD_REF
+ | CTF_STR_MAKE_PROVISIONAL, ref);
+ if (!atom)
+ return 0;
+
+ return atom->csa_offset;
+}
+
+/* Like ctf_str_add_ref(), but notes that this memory location must be added as
+ a ref by a later serialization phase, rather than adding it itself. */
+uint32_t
+ctf_str_add_pending (ctf_dict_t *fp, const char *str, uint32_t *ref)
+{
+ ctf_str_atom_t *atom;
+
+ if (!str)
+ str = "";
+
+ atom = ctf_str_add_ref_internal (fp, str, CTF_STR_PENDING_REF
+ | CTF_STR_MAKE_PROVISIONAL, ref);
if (!atom)
return 0;
@@ -257,7 +298,7 @@ ctf_str_add_external (ctf_dict_t *fp, const char *str, uint32_t offset)
if (!str)
str = "";
- atom = ctf_str_add_ref_internal (fp, str, FALSE, FALSE, 0);
+ atom = ctf_str_add_ref_internal (fp, str, 0, 0);
if (!atom)
return 0;
@@ -307,6 +348,8 @@ ctf_str_remove_ref (ctf_dict_t *fp, const char *str, uint32_t *ref)
free (aref);
}
}
+
+ ctf_dynset_remove (fp->ctf_str_pending_ref, (void *) ref);
}
/* A ctf_dynhash_iter_remove() callback that removes atoms later than a given