#include "term.h" #define CHR sizeof(char) #define NLEN(str) (str) == NULL ? 0 : strlen((str)) static regex_t ptn; static bool ptn_init = false; /** * Free global regex struct. Register with atexit(). */ void term_cleanup() { if (ptn_init) regfree(&ptn); } int LSUP_term_init( LSUP_Term *term, LSUP_term_type type, const char *data, char *datatype, char *lang) { term->type = type; if (data == NULL) return -1; if (term->type == LSUP_TERM_URI) { if (UNLIKELY(!ptn_init)) { assert (regcomp(&ptn, URI_REGEX_STR, REG_EXTENDED) == 0); ptn_init = true; atexit(term_cleanup); } if (regexec(&ptn, data, 0, NULL, 0) != 0) { printf("Error matching URI pattern.\n"); return -1; } } term->data = malloc(strlen(data) + 1); strcpy(term->data, data); if (datatype != NULL) { term->datatype = malloc(strlen(datatype) + 1); strcpy(term->datatype, datatype); } else { term->datatype = NULL; } if (lang != NULL) { // TODO validate language and country code //char lsize = 5 ? lang[2] == "-" : 2; memcpy(term->lang, lang, LANG_SIZE); } else { memset(term->lang, 0, LANG_SIZE); } return 0; } LSUP_Term *LSUP_term_new( LSUP_term_type type, const char *data, char *datatype, char *lang) { LSUP_Term *term; CRITICAL(term = malloc(sizeof(LSUP_Term))); LSUP_term_init(term, type, data, datatype, lang); return term; } char * LSUP_term_gen_random_str() { uuid_t uuid; uuid_generate_random(uuid); uuid_str_t uuid_str; uuid_unparse_lower(uuid, uuid_str); static char uri[UUIDSTR_SIZE + 10]; sprintf(uri, "urn:uuid4:%s", uuid_str); return uri; } LSUP_rc LSUP_term_serialize(const LSUP_Term *term, LSUP_Buffer *sterm) { size_t size, data_len, datatype_len, data_idx, datatype_idx, lang_idx; if (UNLIKELY(term == NULL)) return LSUP_NOACTION; data_idx = CHR; data_len = strlen(term->data) + CHR; size = data_idx + data_len; if (term->datatype != NULL) { datatype_idx = size; datatype_len = strlen(term->datatype) + CHR; size += datatype_len; if (strlen(term->lang) > 0) { lang_idx = size; size += LANG_SIZE; } } //TRACE("Serialized term size: %lu", size); LSUP_buffer_init(sterm, size); // Copy type. memset(sterm->addr, (unsigned char)term->type, CHR); // Copy data. memcpy(sterm->addr + data_idx, term->data, data_len); if (term->datatype != NULL) { // Copy data type. memcpy(sterm->addr + datatype_idx, term->datatype, datatype_len); if (strlen(term->lang) > 0) { // Copy lang tag. memcpy(sterm->addr + lang_idx, term->lang, LANG_SIZE); } } return 0; } int LSUP_term_deserialize(const LSUP_Buffer *sterm, LSUP_Term *term) { size_t cur; char *data, *datatype = NULL; langtag lang = "\00"; char type = ((char*)(sterm->addr))[0]; cur = CHR; data = (char*)sterm->addr + cur; cur += strlen(data) + CHR; if (type == LSUP_TERM_LITERAL) { datatype = (char*)sterm->addr + cur; cur += strlen(datatype) + CHR; if (strlen(datatype) == 0) datatype = NULL; if (cur < sterm->size) strcpy(lang, sterm->addr + cur); } LSUP_term_init(term, type, data, datatype, lang); return 0; } bool LSUP_term_equals(const LSUP_Term *term1, const LSUP_Term *term2) { if (term1->type != term2->type) return false; if (strcmp(term1->data, term2->data) != 0) return false; if (term1->type == LSUP_TERM_LITERAL) { if ((term1->datatype == NULL) != (term2->datatype == NULL)) // XOR return false; if ( term1->datatype != NULL && strcmp(term1->datatype, term2->datatype) != 0) return false; if ((term1->lang == NULL) != (term2->lang == NULL)) // XOR return false; if ( term1->lang != NULL && strcmp(term1->lang, term2->lang) != 0) return false; } return true; } void LSUP_term_done(LSUP_Term *term) { if (LIKELY(term->data != NULL)) { free(term->data); term->data = NULL; } if (term->datatype != NULL) { free(term->datatype); term->datatype = NULL; } } void LSUP_term_free(LSUP_Term *term) { if (LIKELY(term != NULL)) { LSUP_term_done(term); free(term); term = NULL; } } // Extern inline functions. LSUP_Key LSUP_sterm_to_key(const LSUP_SerTerm *sterm); LSUP_Key LSUP_term_to_key(const LSUP_Term *term);