diff options
Diffstat (limited to 'libctf/ctf-string.c')
-rw-r--r-- | libctf/ctf-string.c | 61 |
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 |