123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- #include "core.h"
- #include "namespace.h"
- /** @brief Prefix / Namespace pair.
- */
- typedef struct ns_entry_t {
- ns_pfx pfx; // Namespace prefix.
- char * ns; // Fully qualified NS.
- } NSEntry;
- typedef struct hashmap NSMap;
- /** @brief Iterator for dumping NS map.
- */
- struct dump_iter_t {
- size_t i; // Iterator counter.
- const char *** data; // Stored data.
- };
- /**
- * Callbacks.
- */
- static int nsmap_comp_fn (const void *a, const void *b, void *udata)
- {
- const NSEntry *nsa = a;
- const NSEntry *nsb = b;
- return strncmp (nsa->pfx, nsb->pfx, PFX_LEN);
- }
- static uint64_t nsmap_hash_fn (
- const void *item, uint64_t seed0, uint64_t seed1)
- {
- const NSEntry *nse = item;
- return (uint64_t) LSUP_HASH64 (nse->pfx, strlen (nse->pfx), seed0);
- }
- static void nsmap_free_fn (void *item)
- { free (((NSEntry *) item)->ns); }
- static bool nsmap_dump_ns_iter_fn (const void *item, void *udata)
- {
- const NSEntry *entry = item;
- struct dump_iter_t *cur = udata;
- cur->data[cur->i][0] = (const char *)entry->pfx;
- cur->data[cur->i++][1] = (const char *)entry->ns;
- return true;
- }
- /**
- * API.
- */
- NSMap *
- LSUP_nsmap_new (void)
- {
- return hashmap_new (
- sizeof (NSEntry), 0, LSUP_HASH_SEED, 0,
- nsmap_hash_fn, nsmap_comp_fn, nsmap_free_fn, NULL);
- }
- void
- LSUP_nsmap_free (NSMap *map)
- { hashmap_free (map); }
- LSUP_rc
- LSUP_nsmap_add (NSMap *map, const char *pfx, const char *nsstr)
- {
- NSEntry entry_s = {};
- if (strlen(pfx) >= PFX_LEN)
- log_warn(
- "Prefix `%s` is longer than the maximum allowed size "
- "(%d characters). Truncating.", pfx, PFX_LEN - 1);
- strncpy (entry_s.pfx, pfx, PFX_LEN -1);
- char *ns = strdup (nsstr);
- NSEntry *ret = hashmap_get (map, &entry_s);
- if (!ret) {
- entry_s.ns = ns;
- hashmap_set (map, &entry_s);
- if (hashmap_oom (map)) return LSUP_MEM_ERR;
- log_debug ("Added prefix '%s' to NS map.", entry_s.pfx);
- } else {
- log_debug (
- "Replacing NS '%s' with '%s' for preix '%s'.",
- ret->ns, ns, entry_s.pfx);
- free (ret->ns);
- ret->ns = ns;
- }
- // Free replaced NS string.
- return LSUP_OK;
- }
- LSUP_rc
- LSUP_nsmap_remove (NSMap *map, const char *pfx)
- {
- NSEntry entry_s = {};
- strncpy (entry_s.pfx, pfx, PFX_LEN - 1);
- NSEntry *entry = hashmap_delete (map, &entry_s);
- if (!entry) return LSUP_NOACTION;
- free (entry->ns);
- return LSUP_OK;
- }
- const char *
- LSUP_nsmap_get_ns (const NSMap *map, const char *pfx)
- {
- NSEntry entry_s = {};
- strncpy (entry_s.pfx, pfx, PFX_LEN - 1);
- NSEntry *entry = hashmap_get ((NSMap *)map, &entry_s);
- return (entry) ? entry->ns : NULL;
- }
- const char *
- LSUP_nsmap_get_pfx (const NSMap *map, const char *ns)
- {
- const NSEntry *entry;
- size_t i = 0;
- while (hashmap_iter ((NSMap *)map, &i, (void **) &entry)) {
- if (strncmp (entry->ns, ns, strlen (ns)) == 0)
- return entry->pfx;
- }
- return NULL;
- }
- LSUP_rc
- LSUP_nsmap_normalize_uri (
- const NSMap *map, const char *pfx_uri, char **fq_uri_p)
- {
- LSUP_rc rc;
- char *fq_uri = NULL;
- size_t pfx_len = strcspn (pfx_uri, ":");
- if (pfx_len >= PFX_LEN) {
- log_warn (
- "Prefix in `%s` is longer than the maximum allowed size "
- "(%d characters). Truncating.", pfx_uri, PFX_LEN - 1);
- pfx_len = PFX_LEN - 1;
- }
- ns_pfx pfx;
- strncpy (pfx, pfx_uri, pfx_len);
- pfx[pfx_len] = '\0';
- const char *ns = LSUP_nsmap_get_ns ((NSMap *)map, pfx);
- if (ns) {
- // -1 for :, +1 for terminator.
- size_t fq_size = strlen (ns) + strlen (pfx_uri) - pfx_len;
- fq_uri = malloc (fq_size);
- if (UNLIKELY (! (fq_uri))) return LSUP_MEM_ERR;
- strcpy (fq_uri, ns);
- strcat (fq_uri, pfx_uri + pfx_len + 1);
- rc = LSUP_OK;
- } else {
- log_error ("No NS prefix found in map to normalize %s", pfx_uri);
- rc = LSUP_VALUE_ERR;
- }
- *fq_uri_p = fq_uri;
- return rc;
- }
- LSUP_rc
- LSUP_nsmap_denormalize_uri (
- const NSMap *map, const char *fq_uri, char **pfx_uri_p)
- {
- /*
- * This is different from LSUP_nsmap_get_ns, in that the URI being looked
- * at will unlikely match exactly the full namespace stored in the map.
- * This function has to count the characters left over from the match in
- * order to add the URI suffix.
- */
- LSUP_rc rc;
- const NSEntry *entry;
- const char *pfx = NULL;
- size_t i = 0, offset;
- while (hashmap_iter ((NSMap *)map, &i, (void **) &entry)) {
- offset = strlen (entry->ns);
- if (strncmp (entry->ns, fq_uri, offset) == 0) {
- pfx = entry->pfx;
- break;
- }
- }
- char *pfx_uri = NULL;
- if (pfx) {
- // +2: one for terminating \x00, one for the colon.
- pfx_uri = malloc (strlen (pfx) + strlen (fq_uri) - offset + 2);
- if (UNLIKELY (! (pfx_uri))) return LSUP_MEM_ERR;
- sprintf (pfx_uri, "%s:%s", pfx, fq_uri + offset);
- rc = LSUP_OK;
- } else {
- pfx_uri = strdup (fq_uri);
- rc = LSUP_NORESULT;
- }
- *pfx_uri_p = pfx_uri;
- return rc;
- }
- const char ***
- LSUP_nsmap_dump (const NSMap *map)
- {
- size_t i = hashmap_count ((NSMap *) map);
- const char ***data = malloc (2 * (i + 1) * sizeof (char *));
- if (UNLIKELY (!data)) return NULL;
- for (size_t j = 0; j < i; j++) {
- data[j] = malloc (2 * sizeof (char *));
- if (UNLIKELY (!data[j])) return NULL;
- }
- struct dump_iter_t cur = {.i = 0, .data = data};
- hashmap_scan ((NSMap *) map, nsmap_dump_ns_iter_fn, &cur);
- data[i] = NULL; // Sentinel
- return data;
- }
|