term.c 4.7 KB

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