term.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include "tpl.h"
  2. #include "term.h"
  3. /*
  4. * tpl packing format for the term structure.
  5. */
  6. #define TERM_PACK_FMT "S(suc)"
  7. /*
  8. * Extern variables.
  9. */
  10. IDCache *LSUP_id_cache = NULL;
  11. uint32_t LSUP_default_dtype_key = 0;
  12. regex_t *LSUP_uri_ptn;
  13. /*
  14. * Static variables.
  15. */
  16. // Characters not allowed in a URI string.
  17. static const char *invalid_uri_chars = "<>\" {}|\\^`";
  18. /*
  19. * API functions.
  20. */
  21. LSUP_Term *
  22. LSUP_term_new (
  23. LSUP_TermType type, const char *data, const char *metadata)
  24. {
  25. LSUP_Term *term;
  26. CALLOC_GUARD (term, NULL);
  27. // If undefined, just set the type.
  28. if (type == LSUP_TERM_UNDEFINED) term->type = type;
  29. else if (UNLIKELY (LSUP_term_init (
  30. term, type, data, metadata) != LSUP_OK)) {
  31. free (term);
  32. return NULL;
  33. }
  34. return term;
  35. }
  36. LSUP_Term *
  37. LSUP_term_new_from_buffer (const LSUP_Buffer *sterm)
  38. {
  39. if (UNLIKELY (!sterm)) return NULL;
  40. LSUP_Term *term;
  41. MALLOC_GUARD (term, NULL);
  42. tpl_node *tn;
  43. tn = tpl_map (TERM_PACK_FMT, term);
  44. if (UNLIKELY (!tn)) goto fail;
  45. if (UNLIKELY (tpl_load (tn, TPL_MEM, sterm->addr, sterm->size) < 0))
  46. goto fail;
  47. if (UNLIKELY (tpl_unpack (tn, 0) < 0)) goto fail;
  48. tpl_free (tn);
  49. return term;
  50. fail:
  51. tpl_free (tn);
  52. free (term);
  53. return NULL;
  54. }
  55. LSUP_Buffer *
  56. LSUP_buffer_new_from_term (const LSUP_Term *term)
  57. {
  58. if (UNLIKELY (!term)) return NULL;
  59. LSUP_Buffer *sterm;
  60. MALLOC_GUARD (sterm, NULL);
  61. int rc = tpl_jot (
  62. TPL_MEM, &sterm->addr, &sterm->size, TERM_PACK_FMT, term);
  63. if (rc != 0) {
  64. free (sterm);
  65. return NULL;
  66. }
  67. return sterm;
  68. }
  69. LSUP_rc
  70. LSUP_term_init(
  71. LSUP_Term *term, LSUP_TermType type,
  72. const char *data, const char *metadata)
  73. {
  74. // This can never be LSUP_TERM_UNDEFINED.
  75. if (!data) return LSUP_VALUE_ERR;
  76. term->type = type;
  77. // Validate URI.
  78. if (term->type == LSUP_TERM_IRIREF) {
  79. if (strpbrk (data, invalid_uri_chars) != NULL) {
  80. log_error (
  81. "Characters %s are not allowed. Got: %s\n",
  82. invalid_uri_chars, data);
  83. return LSUP_VALUE_ERR;
  84. }
  85. if (regexec (LSUP_uri_ptn, data, 0, NULL, 0) != 0) {
  86. fprintf (stderr, "Error matching URI pattern.\n");
  87. return LSUP_VALUE_ERR;
  88. }
  89. }
  90. char *data_tmp = realloc (term->data, strlen (data) + 1);
  91. if (UNLIKELY (!data_tmp)) return LSUP_MEM_ERR;
  92. term->data = data_tmp;
  93. strcpy (term->data, data);
  94. if (term->type == LSUP_TERM_LT_LITERAL) {
  95. term->lang = XXH64 (metadata, strlen (metadata) + 1, HASH_SEED);
  96. LSUP_tcache_add_id (term->lang, metadata);
  97. } else if (metadata && strcmp (metadata, DEFAULT_DTYPE) != 0) {
  98. term->datatype = XXH64 (metadata, strlen (metadata) + 1, HASH_SEED);
  99. LSUP_tcache_add_id (term->datatype, metadata);
  100. }
  101. return LSUP_OK;
  102. }
  103. LSUP_rc
  104. LSUP_uri_init (LSUP_Term *term, const char *data)
  105. {
  106. if (!data) {
  107. uuid_t uuid;
  108. uuid_generate_random (uuid);
  109. uuid_str_t uuid_str;
  110. uuid_unparse_lower (uuid, uuid_str);
  111. char uri[UUIDSTR_SIZE + 10];
  112. sprintf (uri, "urn:uuid4:%s", uuid_str);
  113. data = uri;
  114. }
  115. return LSUP_term_init (term, LSUP_TERM_IRIREF, data, NULL);
  116. }
  117. bool LSUP_term_equals (const LSUP_Term *term1, const LSUP_Term *term2)
  118. {
  119. if (term1->type != term2->type)
  120. return false;
  121. if (strcmp (term1->data, term2->data) != 0)
  122. return false;
  123. if (term1->type == LSUP_TERM_LITERAL)
  124. return term1->datatype == term2->datatype;
  125. if (term1->type == LSUP_TERM_LT_LITERAL)
  126. return term1->lang == term2->lang;
  127. return true;
  128. }
  129. void LSUP_term_done (LSUP_Term *term)
  130. {
  131. free (term->data);
  132. term->data = NULL;
  133. }
  134. void LSUP_term_free (LSUP_Term *term)
  135. {
  136. if (LIKELY (term != NULL)) {
  137. free (term->data);
  138. free (term);
  139. }
  140. }
  141. LSUP_rc
  142. LSUP_tcache_add_id (const uint32_t key, const char *data)
  143. {
  144. struct id_cache_t *entry;
  145. HASH_FIND_INT (LSUP_id_cache, &key, entry);
  146. if (entry) return LSUP_NOACTION;
  147. MALLOC_GUARD (entry, LSUP_MEM_ERR);
  148. entry->key = key;
  149. entry->data = strdup (data);
  150. HASH_ADD_INT (LSUP_id_cache, key, entry);
  151. return LSUP_OK;
  152. }
  153. const char *
  154. LSUP_tcache_get_id (const uint32_t key)
  155. {
  156. struct id_cache_t *entry;
  157. HASH_FIND_INT (LSUP_id_cache, &key, entry);
  158. if (entry) log_trace ("Id found for key %d: %s", key, entry->data);
  159. else log_trace ("No ID found for key %d.", key);
  160. return (entry) ? entry->data : NULL;
  161. }
  162. // Extern inline functions.
  163. LSUP_Key LSUP_term_hash (const LSUP_Term *term);
  164. LSUP_Term *LSUP_uri_new (const char *data);
  165. LSUP_rc LSUP_uri_init (LSUP_Term *term, const char *data);