#include "tpl.h" #include "term.h" /* * tpl packing format for the term structure. */ #define TERM_PACK_FMT "S(suc)" /* * Extern variables. */ IDCache *LSUP_id_cache = NULL; uint32_t LSUP_default_dtype_key = 0; regex_t *LSUP_uri_ptn; /* * Static variables. */ // Characters not allowed in a URI string. static const char *invalid_uri_chars = "<>\" {}|\\^`"; /* * API functions. */ LSUP_Term * LSUP_term_new ( LSUP_TermType type, const char *data, const char *metadata) { LSUP_Term *term; CALLOC_GUARD (term, NULL); // If undefined, just set the type. if (type == LSUP_TERM_UNDEFINED) term->type = type; else if (UNLIKELY (LSUP_term_init ( term, type, data, metadata) != LSUP_OK)) { free (term); return NULL; } return term; } LSUP_Term * LSUP_term_new_from_buffer (const LSUP_Buffer *sterm) { if (UNLIKELY (!sterm)) return NULL; LSUP_Term *term; MALLOC_GUARD (term, NULL); tpl_node *tn; tn = tpl_map (TERM_PACK_FMT, term); if (UNLIKELY (!tn)) goto fail; if (UNLIKELY (tpl_load (tn, TPL_MEM, sterm->addr, sterm->size) < 0)) goto fail; if (UNLIKELY (tpl_unpack (tn, 0) < 0)) goto fail; tpl_free (tn); return term; fail: tpl_free (tn); free (term); return NULL; } LSUP_Buffer * LSUP_buffer_new_from_term (const LSUP_Term *term) { if (UNLIKELY (!term)) return NULL; LSUP_Buffer *sterm; MALLOC_GUARD (sterm, NULL); int rc = tpl_jot ( TPL_MEM, &sterm->addr, &sterm->size, TERM_PACK_FMT, term); if (rc != 0) { free (sterm); return NULL; } return sterm; } LSUP_rc LSUP_term_init( LSUP_Term *term, LSUP_TermType type, const char *data, const char *metadata) { // This can never be LSUP_TERM_UNDEFINED. if (!data) return LSUP_VALUE_ERR; term->type = type; // Validate URI. if (term->type == LSUP_TERM_IRIREF) { if (strpbrk (data, invalid_uri_chars) != NULL) { log_error ( "Characters %s are not allowed. Got: %s\n", invalid_uri_chars, data); return LSUP_VALUE_ERR; } if (regexec (LSUP_uri_ptn, data, 0, NULL, 0) != 0) { fprintf (stderr, "Error matching URI pattern.\n"); return LSUP_VALUE_ERR; } } char *data_tmp = realloc (term->data, strlen (data) + 1); if (UNLIKELY (!data_tmp)) return LSUP_MEM_ERR; term->data = data_tmp; strcpy (term->data, data); if (term->type == LSUP_TERM_LT_LITERAL) { term->lang = XXH64 (metadata, strlen (metadata) + 1, HASH_SEED); LSUP_tcache_add_id (term->lang, metadata); } else if (metadata && strcmp (metadata, DEFAULT_DTYPE) != 0) { term->datatype = XXH64 (metadata, strlen (metadata) + 1, HASH_SEED); LSUP_tcache_add_id (term->datatype, metadata); } return LSUP_OK; } LSUP_rc LSUP_uri_init (LSUP_Term *term, const char *data) { if (!data) { uuid_t uuid; uuid_generate_random (uuid); uuid_str_t uuid_str; uuid_unparse_lower (uuid, uuid_str); char uri[UUIDSTR_SIZE + 10]; sprintf (uri, "urn:uuid4:%s", uuid_str); data = uri; } return LSUP_term_init (term, LSUP_TERM_IRIREF, data, NULL); } 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) return term1->datatype == term2->datatype; if (term1->type == LSUP_TERM_LT_LITERAL) return term1->lang == term2->lang; return true; } void LSUP_term_done (LSUP_Term *term) { free (term->data); term->data = NULL; } void LSUP_term_free (LSUP_Term *term) { if (LIKELY (term != NULL)) { free (term->data); free (term); } } LSUP_rc LSUP_tcache_add_id (const uint32_t key, const char *data) { struct id_cache_t *entry; HASH_FIND_INT (LSUP_id_cache, &key, entry); if (entry) return LSUP_NOACTION; MALLOC_GUARD (entry, LSUP_MEM_ERR); entry->key = key; entry->data = strdup (data); HASH_ADD_INT (LSUP_id_cache, key, entry); return LSUP_OK; } const char * LSUP_tcache_get_id (const uint32_t key) { struct id_cache_t *entry; HASH_FIND_INT (LSUP_id_cache, &key, entry); if (entry) log_trace ("Id found for key %d: %s", key, entry->data); else log_trace ("No ID found for key %d.", key); return (entry) ? entry->data : NULL; } // Extern inline functions. LSUP_Key LSUP_term_hash (const LSUP_Term *term); LSUP_Term *LSUP_uri_new (const char *data); LSUP_rc LSUP_uri_init (LSUP_Term *term, const char *data);