namespace.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #include "uthash.h"
  2. #include "namespace.h"
  3. typedef struct namespace_t {
  4. ns_pfx pfx; // Namespace prefix.
  5. char * ns; // Fully qualified NS.
  6. UT_hash_handle hh; // UTHash handle.
  7. } Namespace;
  8. typedef struct namespace_index_t {
  9. Namespace * ns; // Pointer to a NS struct.
  10. UT_hash_handle hh; // UTHash handle.
  11. } NSIndex;
  12. typedef struct ns_map_t {
  13. Namespace * pn; // Prefix to namespace.
  14. NSIndex * np; // Namespace to prefix.
  15. } NSMap;
  16. NSMap *
  17. LSUP_nsmap_new (void)
  18. {
  19. NSMap *map;
  20. CALLOC_GUARD (map, NULL);
  21. return map;
  22. }
  23. void
  24. LSUP_nsmap_free (NSMap *map)
  25. {
  26. if (UNLIKELY (!map)) return;
  27. Namespace *entry, *tmp;
  28. HASH_ITER (hh, map->pn, entry, tmp) {
  29. HASH_DEL (map->pn, entry);
  30. free (entry->ns);
  31. free (entry);
  32. }
  33. NSIndex *idx_entry, *idx_tmp;
  34. HASH_ITER (hh, map->np, idx_entry, idx_tmp) {
  35. HASH_DEL (map->np, idx_entry);
  36. free (idx_entry);
  37. }
  38. free (map);
  39. }
  40. LSUP_rc
  41. LSUP_nsmap_add (NSMap *map, const ns_pfx pfx, const char *nsstr)
  42. {
  43. // Main entry (pn)
  44. // Delete any found record.
  45. // Main and index are deleted independently because the pair may be
  46. // different.
  47. Namespace *entry = NULL;
  48. HASH_FIND_STR (map->pn, pfx, entry);
  49. if (entry) {
  50. HASH_DEL (map->pn, entry);
  51. free (entry->ns);
  52. free (entry);
  53. }
  54. // Add.
  55. MALLOC_GUARD (entry, LSUP_MEM_ERR);
  56. entry->ns = strdup (nsstr);
  57. strcpy (entry->pfx, pfx);
  58. HASH_ADD_STR (map->pn, pfx, entry);
  59. // Index.
  60. // Delete any found record.
  61. NSIndex *idx_entry = NULL;
  62. HASH_FIND_STR (map->np, nsstr, idx_entry);
  63. if (idx_entry) {
  64. HASH_DEL (map->np, idx_entry);
  65. free (idx_entry);
  66. }
  67. // Add.
  68. MALLOC_GUARD (idx_entry, LSUP_MEM_ERR);
  69. //idx_entry = malloc (sizeof (*idx_entry));
  70. //if (UNLIKELY (!entry)) return LSUP_MEM_ERR;
  71. idx_entry->ns = entry;
  72. HASH_ADD_KEYPTR (hh, map->np, entry->ns, strlen (nsstr), idx_entry);
  73. return LSUP_OK;
  74. }
  75. LSUP_rc
  76. LSUP_nsmap_remove (NSMap *map, const ns_pfx pfx)
  77. {
  78. Namespace *entry = NULL;
  79. NSIndex *idx_entry = NULL;
  80. HASH_FIND_STR (map->pn, pfx, entry);
  81. if (entry) {
  82. HASH_FIND_STR (map->np, entry->ns, idx_entry);
  83. if (idx_entry) {
  84. HASH_DEL (map->np, idx_entry);
  85. free (idx_entry);
  86. }
  87. HASH_DEL (map->pn, entry);
  88. free (entry->ns);
  89. free (entry);
  90. return LSUP_OK;
  91. }
  92. return LSUP_NOACTION;
  93. }
  94. const char *
  95. LSUP_nsmap_get (const NSMap *map, const ns_pfx pfx)
  96. {
  97. Namespace *entry = NULL;
  98. HASH_FIND_STR (map->pn, pfx, entry);
  99. return (entry) ? entry->ns : NULL;
  100. }
  101. LSUP_rc
  102. LSUP_nsmap_normalize_uri (
  103. const NSMap *map, const char *pfx_uri, char **fq_uri_p)
  104. {
  105. char *fq_uri = NULL;
  106. size_t pfx_len = strcspn (pfx_uri, ":");
  107. if (pfx_len >= PFX_LEN) pfx_len = PFX_LEN - 1;
  108. ns_pfx pfx;
  109. strncpy (pfx, pfx_uri, pfx_len);
  110. pfx[pfx_len] = 0;
  111. Namespace *entry;
  112. for (entry = map->pn; entry != NULL; entry = entry->hh.next) {
  113. if (strncmp (entry->pfx, pfx_uri, strlen (entry->pfx)) == 0)
  114. break;
  115. }
  116. if (entry) {
  117. // -1 for :, +1 for terminator.
  118. size_t fq_size = strlen (entry->ns) + strlen (pfx_uri) - pfx_len;
  119. fq_uri = malloc (fq_size);
  120. if (UNLIKELY (! (fq_uri))) return LSUP_MEM_ERR;
  121. strcpy (fq_uri, entry->ns);
  122. strcat (fq_uri, pfx_uri + pfx_len + 1);
  123. }
  124. else fq_uri = strdup (pfx_uri);
  125. *fq_uri_p = fq_uri;
  126. return LSUP_OK;
  127. }
  128. LSUP_rc
  129. LSUP_nsmap_denormalize_uri (
  130. const NSMap *map, const char *fq_uri, char **pfx_uri_p)
  131. {
  132. char *pfx_uri = NULL;
  133. NSIndex *entry;
  134. for (entry = map->np; entry != NULL; entry = entry->hh.next) {
  135. if (memcmp (entry->ns->ns, fq_uri, strlen (entry->ns->ns)) == 0)
  136. break;
  137. }
  138. if (entry) {
  139. pfx_uri = malloc (
  140. strlen (entry->ns->pfx)
  141. + strlen (fq_uri) - strlen (entry->ns->ns)
  142. + 2); // one for terminating \x00, one for the colon.
  143. if (UNLIKELY (! (pfx_uri))) return LSUP_MEM_ERR;
  144. sprintf (
  145. pfx_uri, "%s:%s",
  146. entry->ns->pfx, fq_uri + strlen (entry->ns->ns));
  147. }
  148. else pfx_uri = strdup (fq_uri);
  149. *pfx_uri_p = pfx_uri;
  150. return LSUP_OK;
  151. }
  152. const char ***
  153. LSUP_nsmap_dump (const NSMap *map)
  154. {
  155. size_t i = 0;
  156. Namespace *cur;
  157. for (cur = map->pn; cur != NULL; cur = cur->hh.next) i++;
  158. const char ***data = malloc (2 * (i + 1) * sizeof (char *));
  159. if (UNLIKELY (!data)) return NULL;
  160. for (size_t j = 0; j < i; j++) {
  161. data[j] = malloc (2 * sizeof (char *));
  162. if (UNLIKELY (!data[j])) return NULL;
  163. }
  164. i = 0;
  165. for (cur = map->pn; cur != NULL; cur = cur->hh.next) {
  166. data[i][0] = (const char *)cur->pfx;
  167. data[i++][1] = (const char *)cur->ns;
  168. }
  169. data[i] = NULL; // Sentinel
  170. return data;
  171. }