#include "buffer.h" /* * * Inline extern prototypes * * */ LSUP_Buffer *LSUP_buffer_new (const unsigned char *data, const size_t size); LSUP_rc LSUP_buffer_init ( LSUP_Buffer *buf, const size_t size, const unsigned char *data); bool LSUP_buffer_eq (const LSUP_Buffer *buf1, const LSUP_Buffer *buf2); int LSUP_buffer_cmp (const LSUP_Buffer *buf1, const LSUP_Buffer *buf2); static inline char unescape_char (const char c); /* * * API * * */ LSUP_rc LSUP_buffer_init ( LSUP_Buffer *buf, const size_t size, const unsigned char *data) { // If size is zero, addr becomes NULL. unsigned char *tmp = realloc (buf->addr, size); if (UNLIKELY (size > 0 && tmp == NULL)) return LSUP_MEM_ERR; buf->addr = tmp; buf->size = size; if (data) memcpy (buf->addr, data, buf->size); return LSUP_OK; } void LSUP_buffer_print (const LSUP_Buffer *buf) { for (size_t i = 0; i < buf->size; i++) { char chr = ((char*)buf->addr)[i]; if (isprint (chr)) { fputc (chr, stdout); } else { printf ("\\x%02x", chr); } } printf ("\n"); } char * LSUP_buffer_as_str (const LSUP_Buffer *buf) { size_t i, str_size = 1; // terminating NUL // Calculate alloc size first. for (i = 0; i < buf->size; i++) { char chr = ((char*)buf->addr)[i]; if (isprint (chr)) str_size ++; else str_size += 4; // 4 characters for ASCII representation (\xNN). } log_trace ("Byte buffer str size: %lu", str_size); char *cstr = malloc (str_size); size_t cur = 0; // Position in target string. for (i = 0; i < str_size - 1; i++) { char chr = ((char*)buf->addr)[i]; if (isprint (chr)) { cstr[cur] = chr; cur ++; } else { sprintf (cstr + cur, "\\x%02x", chr); cur += 4; } } cstr[str_size - 1] = 0; // terminating NUL. return cstr; } void LSUP_buffer_done (LSUP_Buffer *buf) { if (LIKELY (buf)) free (buf->addr); } void LSUP_buffer_free (LSUP_Buffer *buf) { LSUP_buffer_done (buf); free (buf); } /* * Buffer triples. */ LSUP_BufferTriple * LSUP_btriple_new(LSUP_Buffer *s, LSUP_Buffer *p, LSUP_Buffer *o) { LSUP_BufferTriple *sspo = malloc (sizeof (*sspo)); if (!sspo) return NULL; if (UNLIKELY (LSUP_btriple_init (sspo, s, p, o))) { free (sspo); return NULL; } return sspo; } LSUP_rc LSUP_btriple_init ( LSUP_BufferTriple *sspo, LSUP_Buffer *s, LSUP_Buffer *p, LSUP_Buffer *o) { sspo->s = s; sspo->p = p; sspo->o = o; return LSUP_OK; } void LSUP_btriple_done (LSUP_BufferTriple *sspo) { if (UNLIKELY (!sspo)) return; LSUP_buffer_done (sspo->s); LSUP_buffer_done (sspo->p); LSUP_buffer_done (sspo->o); } void LSUP_btriple_free (LSUP_BufferTriple *sspo) { if (UNLIKELY (!sspo)) return; LSUP_buffer_free (sspo->s); LSUP_buffer_free (sspo->p); LSUP_buffer_free (sspo->o); free (sspo); } void LSUP_btriple_free_shallow (LSUP_BufferTriple *sspo) { if (UNLIKELY (!sspo)) return; sspo->s->addr = sspo->p->addr = sspo->o->addr = NULL; LSUP_btriple_free (sspo); } /* * Statics. */ static inline char unescape_char (const char c) { switch (c) { case 't': return '\t'; case 'b': return '\b'; case 'n': return '\n'; case 'r': return '\r'; case 'f': return '\f'; default: return c; } } /* Extern inline prototypes. */ LSUP_Key LSUP_buffer_hash (const LSUP_Buffer *buf); LSUP_Key LSUP_btriple_hash (const LSUP_BufferTriple *strp); LSUP_Buffer *LSUP_btriple_pos (const LSUP_BufferTriple *trp, LSUP_TriplePos n);