#include "codec.h" uint8_t *unescape_unicode (const uint8_t *esc_str) { size_t size = strlen ((char *)esc_str); uint8_t *data = malloc (size + 1); size_t j = 0; uint8_t tmp_chr[5]; for (size_t i = 0; i < size;) { if (esc_str[i] == '\\') { i++; // Skip over '\\' // 4-hex sequence. if (esc_str[i] == 'u') { i ++; // Skip over 'u' // Use tmp_chr to hold the hex string for the code point. memcpy (tmp_chr, esc_str + i, sizeof (tmp_chr) - 1); tmp_chr[4] = '\0'; uint32_t tmp_val = strtol ((char*)tmp_chr, NULL, 16); log_debug ("tmp_val: %d", tmp_val); // Reuse tmp_chr to hold the byte values for the code point. int nbytes = utf8_encode (tmp_val, tmp_chr); if (nbytes == 0) log_error ("Error encoding sequence: \\u%s", tmp_chr); // Copy bytes into destination. memcpy (data + j, tmp_chr, nbytes); log_trace ("UC byte value: %x %x", data[j], data[j + 1]); j += nbytes; i += 4; // 8-hex sequence. } else if (esc_str[i] == 'U') { i ++; // Skip over 'U' log_error ("4-byte sequence encoding is not yet implemented."); return NULL; // TODO encode 4-byte sequences // Unescape other escaped characters. } else data[j++] = unescape_char (esc_str[i++]); } else { // Copy ASCII char verbatim. data[j++] = esc_str[i++]; } } data[j++] = '\0'; uint8_t *tmp = realloc (data, j); // Compact result. if (UNLIKELY (!tmp)) return NULL; data = tmp; return data; } LSUP_Term ** LSUP_obj_list_add (LSUP_Term **ol, LSUP_Term *o) { size_t i = 0; while (ol[i++]); LSUP_Term **tmp = realloc (ol, sizeof (*ol) * (i + 1)); if (!tmp) return NULL; tmp[i] = o; tmp[i + 1] = NULL; return ol; } LSUP_PredObjList * LSUP_pred_obj_list_new (void) { /* * Init state: * {p: [NULL], o: [NULL]} */ LSUP_PredObjList *po; MALLOC_GUARD (po, NULL); // Set sentinels. CALLOC_GUARD (po->p, NULL); CALLOC_GUARD (po->o, NULL); return po; } void LSUP_pred_obj_list_free (LSUP_PredObjList *po) { for (size_t i = 0; po->p[i]; i++) { LSUP_term_free (po->p[i]); } for (size_t i = 0; po->o[i]; i++) { for (size_t j = 0; po->o[i][j]; j++) { LSUP_term_free (po->o[i][j]); } } free (po); } LSUP_rc LSUP_pred_obj_list_add (LSUP_PredObjList *po, LSUP_Term *p, LSUP_Term **o) { size_t i; i = 0; while (po->p[i++]); // Count includes sentinel. LSUP_Term **tmp_p = realloc (po->p, sizeof (*po->p) * (i + 1)); if (!tmp_p) return LSUP_MEM_ERR; tmp_p[i] = p; tmp_p[i + 1] = NULL; po->p = tmp_p; i = 0; while (po->o[i++]); LSUP_Term ***tmp_o = realloc (po->o, sizeof (*po->o) * (i + 1)); if (!tmp_o) return LSUP_MEM_ERR; tmp_o[i] = o; tmp_o[i + 1] = NULL; po->o = tmp_o; return LSUP_OK; } LSUP_rc LSUP_spo_list_add_triples ( LSUP_GraphIterator *it, LSUP_Term *s, const LSUP_PredObjList *po) { LSUP_Triple *spo = LSUP_triple_new (s, NULL, NULL); for (size_t i = 0; po->p[i]; i++) { spo->p = po->p[i]; for (size_t j = 0; po->o[i][j]; j++) { spo->o = po->o[i][j]; PRCCK (LSUP_graph_add_iter (it, spo)); } } free (spo); return LSUP_OK; } LSUP_Term * LSUP_bnode_add_collection (LSUP_GraphIterator *it, LSUP_Term **ol) { LSUP_NSMap *nsm = LSUP_graph_namespace (LSUP_graph_iter_graph (it)); LSUP_Term *s = LSUP_term_new (LSUP_TERM_BNODE, NULL, NULL), *rdf_first = LSUP_iriref_new ("rdf:first", nsm), *rdf_rest = LSUP_iriref_new ("rdf:rest", nsm), *rdf_nil = LSUP_iriref_new ("rdf:nil", nsm), *link; LSUP_Triple *spo = TRP_DUMMY; link = s; for (size_t i = 0; ol[i]; i++) { spo->s = link; spo->p = rdf_first; spo->o = ol[i]; PRCNL (LSUP_graph_add_iter (it, spo)); spo->p = rdf_rest; spo->o = ( ol[i + 1] ? LSUP_term_new (LSUP_TERM_BNODE, NULL, NULL) : rdf_nil); PRCNL (LSUP_graph_add_iter (it, spo)); if (link != s) LSUP_term_free (link); // Current object becomes next subject. Irrelevant for last item. link = spo->o; } LSUP_term_free (rdf_first); LSUP_term_free (rdf_rest); LSUP_term_free (rdf_nil); free (spo); return s; } /* * Extern inline functions. */ char unescape_char (const char c); uint8_t *uint8_dup (const uint8_t *str); uint8_t *uint8_ndup (const uint8_t *str, size_t size);