term.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #include "term.h"
  2. #define CHR sizeof(char)
  3. #define NLEN(str) (str) == NULL ? 0 : strlen((str))
  4. static regex_t ptn;
  5. static bool ptn_init = false;
  6. /* Global inline prototypes. */
  7. LSUP_Term * LSUP_uri_new(const char *data);
  8. /**
  9. * Free global regex struct. Register with atexit().
  10. */
  11. void term_cleanup() { if (ptn_init) regfree(&ptn); }
  12. int
  13. LSUP_term_init(
  14. LSUP_Term *term, LSUP_term_type type,
  15. const char *data, char *datatype, char *lang)
  16. {
  17. term->type = type;
  18. if (data == NULL) return -1;
  19. if (term->type == LSUP_TERM_URI) {
  20. if (UNLIKELY(!ptn_init)) {
  21. assert (regcomp(&ptn, URI_REGEX_STR, REG_EXTENDED) == 0);
  22. ptn_init = true;
  23. atexit(term_cleanup);
  24. }
  25. if (regexec(&ptn, data, 0, NULL, 0) != 0) {
  26. printf("Error matching URI pattern.\n");
  27. return -1;
  28. }
  29. }
  30. term->data = malloc(strlen(data) + 1);
  31. strcpy(term->data, data);
  32. if (datatype != NULL) {
  33. term->datatype = malloc(strlen(datatype) + 1);
  34. strcpy(term->datatype, datatype);
  35. } else {
  36. term->datatype = NULL;
  37. }
  38. if (lang != NULL) {
  39. // TODO validate language and country code
  40. //char lsize = 5 ? lang[2] == "-" : 2;
  41. memcpy(term->lang, lang, LANG_SIZE);
  42. } else {
  43. memset(term->lang, 0, LANG_SIZE);
  44. }
  45. return 0;
  46. }
  47. LSUP_Term
  48. *LSUP_term_new(
  49. LSUP_term_type type, const char *data, char *datatype, char *lang) {
  50. LSUP_Term *term;
  51. CRITICAL(term = malloc(sizeof(LSUP_Term)));
  52. LSUP_term_init(term, type, data, datatype, lang);
  53. return term;
  54. }
  55. char *
  56. LSUP_term_gen_random_str()
  57. {
  58. uuid_t uuid;
  59. uuid_generate_random(uuid);
  60. uuid_str_t uuid_str;
  61. uuid_unparse_lower(uuid, uuid_str);
  62. static char uri[UUIDSTR_SIZE + 10];
  63. sprintf(uri, "urn:uuid4:%s", uuid_str);
  64. return uri;
  65. }
  66. LSUP_rc
  67. LSUP_term_serialize(const LSUP_Term *term, LSUP_Buffer *sterm)
  68. {
  69. size_t size, data_len, datatype_len,
  70. data_idx, datatype_idx, lang_idx;
  71. if (UNLIKELY(term == NULL)) return LSUP_NOACTION;
  72. data_idx = CHR;
  73. data_len = strlen(term->data) + CHR;
  74. size = data_idx + data_len;
  75. if (term->datatype != NULL) {
  76. datatype_idx = size;
  77. datatype_len = strlen(term->datatype) + CHR;
  78. size += datatype_len;
  79. if (strlen(term->lang) > 0) {
  80. lang_idx = size;
  81. size += LANG_SIZE;
  82. }
  83. }
  84. //TRACE("Serialized term size: %lu", size);
  85. LSUP_buffer_init(sterm, size);
  86. // Copy type.
  87. memset(sterm->addr, (unsigned char)term->type, CHR);
  88. // Copy data.
  89. memcpy(sterm->addr + data_idx, term->data, data_len);
  90. if (term->datatype != NULL) {
  91. // Copy data type.
  92. memcpy(sterm->addr + datatype_idx, term->datatype, datatype_len);
  93. if (strlen(term->lang) > 0) {
  94. // Copy lang tag.
  95. memcpy(sterm->addr + lang_idx, term->lang, LANG_SIZE);
  96. }
  97. }
  98. return 0;
  99. }
  100. int
  101. LSUP_term_deserialize(const LSUP_Buffer *sterm, LSUP_Term *term)
  102. {
  103. size_t cur;
  104. char *data, *datatype = NULL;
  105. langtag lang = "\00";
  106. char type = ((char*)(sterm->addr))[0];
  107. cur = CHR;
  108. data = (char*)sterm->addr + cur;
  109. cur += strlen(data) + CHR;
  110. if (type == LSUP_TERM_LITERAL) {
  111. datatype = (char*)sterm->addr + cur;
  112. cur += strlen(datatype) + CHR;
  113. if (strlen(datatype) == 0)
  114. datatype = NULL;
  115. if (cur < sterm->size)
  116. strcpy(lang, sterm->addr + cur);
  117. }
  118. LSUP_term_init(term, type, data, datatype, lang);
  119. return 0;
  120. }
  121. bool LSUP_term_equals(const LSUP_Term *term1, const LSUP_Term *term2)
  122. {
  123. if (term1->type != term2->type)
  124. return false;
  125. if (strcmp(term1->data, term2->data) != 0)
  126. return false;
  127. if (term1->type == LSUP_TERM_LITERAL) {
  128. if ((term1->datatype == NULL) != (term2->datatype == NULL)) // XOR
  129. return false;
  130. if (
  131. term1->datatype != NULL &&
  132. strcmp(term1->datatype, term2->datatype) != 0)
  133. return false;
  134. if ((term1->lang == NULL) != (term2->lang == NULL)) // XOR
  135. return false;
  136. if (
  137. term1->lang != NULL &&
  138. strcmp(term1->lang, term2->lang) != 0)
  139. return false;
  140. }
  141. return true;
  142. }
  143. void LSUP_term_done(LSUP_Term *term)
  144. {
  145. if (LIKELY(term->data != NULL)) {
  146. free(term->data);
  147. term->data = NULL;
  148. }
  149. if (term->datatype != NULL) {
  150. free(term->datatype);
  151. term->datatype = NULL;
  152. }
  153. }
  154. void LSUP_term_free(LSUP_Term *term)
  155. {
  156. if (LIKELY(term != NULL)) {
  157. LSUP_term_done(term);
  158. free(term);
  159. term = NULL;
  160. }
  161. }
  162. // Extern inline functions.
  163. LSUP_Key LSUP_sterm_to_key(const LSUP_SerTerm *sterm);
  164. LSUP_Key LSUP_term_to_key(const LSUP_Term *term);