#include "uthash.h" #include "namespace.h" typedef struct namespace_t { ns_pfx pfx; // Namespace prefix. char * ns; // Fully qualified NS. UT_hash_handle hh; // UTHash handle. } Namespace; typedef struct namespace_index_t { Namespace * ns; // Pointer to a NS struct. UT_hash_handle hh; // UTHash handle. } NSIndex; typedef struct ns_map_t { Namespace * pn; // Prefix to namespace. NSIndex * np; // Namespace to prefix. } NSMap; NSMap * LSUP_nsmap_new (void) { NSMap *map; CALLOC_GUARD (map, NULL); return map; } void LSUP_nsmap_free (NSMap *map) { if (UNLIKELY (!map)) return; Namespace *entry, *tmp; HASH_ITER (hh, map->pn, entry, tmp) { HASH_DEL (map->pn, entry); free (entry->ns); free (entry); } NSIndex *idx_entry, *idx_tmp; HASH_ITER (hh, map->np, idx_entry, idx_tmp) { HASH_DEL (map->np, idx_entry); free (idx_entry); } free (map); } LSUP_rc LSUP_nsmap_add (NSMap *map, const ns_pfx pfx, const char *nsstr) { // Main entry (pn) // Delete any found record. // Main and index are deleted independently because the pair may be // different. Namespace *entry = NULL; HASH_FIND_STR (map->pn, pfx, entry); if (entry) { HASH_DEL (map->pn, entry); free (entry->ns); free (entry); } // Add. MALLOC_GUARD (entry, LSUP_MEM_ERR); //entry = malloc (sizeof (*entry)); //if (UNLIKELY (!entry)) return LSUP_MEM_ERR; entry->ns = strdup (nsstr); strcpy (entry->pfx, pfx); HASH_ADD_STR (map->pn, pfx, entry); // Index. // Delete any found record. NSIndex *idx_entry = NULL; HASH_FIND_STR (map->np, nsstr, idx_entry); if (idx_entry) { HASH_DEL (map->np, idx_entry); free (idx_entry); } // Add. MALLOC_GUARD (idx_entry, LSUP_MEM_ERR); //idx_entry = malloc (sizeof (*idx_entry)); //if (UNLIKELY (!entry)) return LSUP_MEM_ERR; idx_entry->ns = entry; HASH_ADD_KEYPTR (hh, map->np, entry->ns, strlen (nsstr), idx_entry); return LSUP_OK; } LSUP_rc LSUP_nsmap_remove (NSMap *map, const ns_pfx pfx) { Namespace *entry = NULL; NSIndex *idx_entry = NULL; HASH_FIND_STR (map->pn, pfx, entry); if (entry) { HASH_FIND_STR (map->np, entry->ns, idx_entry); if (idx_entry) { HASH_DEL (map->np, idx_entry); free (idx_entry); } HASH_DEL (map->pn, entry); free (entry->ns); free (entry); return LSUP_OK; } return LSUP_NOACTION; } const char * LSUP_nsmap_get (const NSMap *map, const ns_pfx pfx) { Namespace *entry = NULL; HASH_FIND_STR (map->pn, pfx, entry); return (entry) ? entry->ns : NULL; } LSUP_rc LSUP_nsmap_normalize_uri ( const NSMap *map, const char *uri, char **pfx_uri) { *pfx_uri = NULL; NSIndex *entry; HASH_FIND_STR (map->np, uri, entry); if (entry) { *pfx_uri = malloc ( strlen (entry->ns->pfx) + strlen (uri) - strlen (entry->ns->ns) + 2); // one for terminating \x00, one for the colon. if (UNLIKELY (! (*pfx_uri))) return LSUP_MEM_ERR; sprintf ( *pfx_uri, "%s:%s", entry->ns->pfx, uri + strlen (entry->ns->ns)); return LSUP_OK; } else return LSUP_NORESULT; } LSUP_rc LSUP_nsmap_denormalize_uri ( const NSMap *map, const char *pfx_uri, char **uri) { *uri = NULL; size_t pfx_len = strcspn (pfx_uri, ":"); if (pfx_len >= PFX_LEN) pfx_len = PFX_LEN - 1; ns_pfx pfx; strncpy (pfx, pfx_uri, pfx_len); pfx[pfx_len] = 0; Namespace *entry; HASH_FIND_STR (map->pn, pfx, entry); if (entry) *uri = malloc (strlen (entry->ns) + strlen (pfx_uri) - pfx_len - 1); else *uri = strdup (pfx_uri); return LSUP_OK; }