|
@@ -0,0 +1,192 @@
|
|
|
|
+#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 = malloc (sizeof (*map));
|
|
|
|
+ if (UNLIKELY (!map)) return NULL;
|
|
|
|
+
|
|
|
|
+ map->pn = NULL;
|
|
|
|
+ map->np = 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->ns);
|
|
|
|
+ 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.
|
|
|
|
+ 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.
|
|
|
|
+ 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 strcpy (*uri, pfx_uri);
|
|
|
|
+
|
|
|
|
+ return LSUP_OK;
|
|
|
|
+}
|