term.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #ifndef _LSUP_TERM_H
  2. #define _LSUP_TERM_H
  3. #include <assert.h>
  4. #include <regex.h>
  5. #include "buffer.h"
  6. #include "namespace.h"
  7. #define LANG_SIZE 8 // Size in chars of lang tag
  8. // "NULL" triple, a value that is never user-provided. Used to fill deleted
  9. // triples in a keyset.
  10. #define NULL_TRP {NULL_KEY, NULL_KEY, NULL_KEY}
  11. #define UUID4_URN_SIZE UUIDSTR_SIZE + 10
  12. typedef XXH64_hash_t LSUP_TermHash64;
  13. typedef char langtag[LANG_SIZE];
  14. typedef char LSUP_term_type;
  15. #define LSUP_TERM_UNDEFINED 0
  16. #define LSUP_TERM_URI 1
  17. #define LSUP_TERM_BNODE 2
  18. #define LSUP_TERM_LITERAL 3
  19. typedef struct LSUP_Term {
  20. char *data;
  21. char *datatype;
  22. // This language variable currently supports a 2-digit ISO 639 language
  23. // code and a 2-character ISO 3166-1 country code, separated by a hyphen.
  24. // See https://tools.ietf.org/html/bcp47#section-2.1
  25. langtag lang;
  26. LSUP_term_type type;
  27. } LSUP_Term;
  28. /** @brief Create a new term.
  29. *
  30. * @param type[in] Term type. One of #LSUP_term_type.
  31. *
  32. * @param data[in] Term data: textual URI, literal value without data type
  33. * or langtag, etc.
  34. *
  35. * @param datatype[in]: data type for literals.
  36. *
  37. * @param lang[in]: language tag for string literals.
  38. *
  39. * @param term[out] Pointer to a new term, which must be freed with
  40. * #LSUP_term_free after use.
  41. *
  42. * @return LSUP_OK if successful, LSUP_VALUE_ERR if validation fails.
  43. */
  44. LSUP_Term *
  45. LSUP_term_new(
  46. LSUP_term_type type, const char *data, char *datatype, char *lang);
  47. /** @brief Placeholder term to use with LSUP_term_reset.
  48. */
  49. #define TERM_DUMMY LSUP_term_new (LSUP_TERM_UNDEFINED, NULL, NULL, NULL)
  50. /** @brief Shortcut to create a URI.
  51. *
  52. * Must be freed with #LSUP_term_free.
  53. *
  54. * @param data[in] The URI string. If NULL, a UUID4-based URN is generated.
  55. *
  56. * @param uri[out] The URI to be created.
  57. *
  58. * @return LSUP_OK if successful, LSUP_VALUE_ERR if validation fails.
  59. */
  60. inline LSUP_Term *
  61. LSUP_uri_new (const char *data)
  62. {
  63. if (!data) {
  64. uuid_t uuid;
  65. uuid_generate_random (uuid);
  66. uuid_str_t uuid_str;
  67. uuid_unparse_lower (uuid, uuid_str);
  68. char uri[UUID4_URN_SIZE];
  69. snprintf (uri, UUID4_URN_SIZE, "urn:uuid4:%s", uuid_str);
  70. data = uri;
  71. }
  72. return LSUP_term_new (LSUP_TERM_URI, data, NULL, NULL);
  73. }
  74. /* @brief Reuse a pre-allocated term structure.
  75. *
  76. * The structure must have been previously created with #LSUP_term_new. It can
  77. * be reinitialized multiple times without freeing it. It must be eventually
  78. * freed with #LSUP_term_free.
  79. */
  80. LSUP_rc
  81. LSUP_term_init(
  82. LSUP_Term *term, LSUP_term_type type,
  83. const char *data, char *datatype, char *lang);
  84. LSUP_Term *
  85. LSUP_term_new_from_buffer (const LSUP_Buffer *sterm);
  86. LSUP_Buffer *
  87. LSUP_buffer_new_from_term (const LSUP_Term *term);
  88. /**
  89. * @brief Shortcut to initialize a URI.
  90. */
  91. inline LSUP_rc
  92. LSUP_uri_init (LSUP_Term *term, const char *data)
  93. {
  94. if (!data) {
  95. uuid_t uuid;
  96. uuid_generate_random (uuid);
  97. uuid_str_t uuid_str;
  98. uuid_unparse_lower (uuid, uuid_str);
  99. char uri[UUIDSTR_SIZE + 10];
  100. sprintf (uri, "urn:uuid4:%s", uuid_str);
  101. data = uri;
  102. }
  103. return LSUP_term_init (term, LSUP_TERM_URI, data, NULL, NULL);
  104. }
  105. /** @brief Simple ad-hoc serialization function.
  106. *
  107. * The resulting term must be freed with #LSUP_term_free after use.
  108. */
  109. LSUP_rc
  110. LSUP_term_serialize (const LSUP_Term *term, LSUP_Buffer *sterm);
  111. /** @brief Deserialize a buffer into a term.
  112. *
  113. * The buffer must be a well-formed serialization of a term, e.g. as obtained
  114. * by #LSUP_term_serialize.
  115. */
  116. LSUP_rc
  117. LSUP_term_deserialize (const LSUP_Buffer *sterm, LSUP_Term *term);
  118. /** @brief Hash a buffer.
  119. */
  120. inline LSUP_Key
  121. LSUP_term_hash (const LSUP_Term *term)
  122. {
  123. LSUP_Buffer *buf;
  124. if (UNLIKELY (!term)) buf = BUF_DUMMY;
  125. else buf = LSUP_buffer_new_from_term (term);
  126. LSUP_Key key = LSUP_buffer_hash (buf);
  127. LSUP_buffer_free (buf);
  128. return key;
  129. }
  130. /**
  131. * Compare two terms.
  132. */
  133. bool LSUP_term_equals (const LSUP_Term *term1, const LSUP_Term *term2);
  134. /*
  135. // TODO Implement when xxhash v0.8 is released with stable xxhash128 function.
  136. inline XXH128_hash_t
  137. LSUP_term_hash128(const LSUP_Term *term);
  138. */
  139. void
  140. LSUP_term_done (LSUP_Term *term);
  141. void
  142. LSUP_term_free (LSUP_Term *term);
  143. #endif