#include "volksdata/buffer.h" /* * * Inline extern prototypes * * */ VOLK_Buffer *VOLK_buffer_new (const unsigned char *data, const size_t size); VOLK_rc VOLK_buffer_init ( VOLK_Buffer *buf, const size_t size, const unsigned char *data); bool VOLK_buffer_eq (const VOLK_Buffer *buf1, const VOLK_Buffer *buf2); int VOLK_buffer_cmp (const VOLK_Buffer *buf1, const VOLK_Buffer *buf2); static inline char unescape_char (const char c); /* * * API * * */ VOLK_rc VOLK_buffer_init ( VOLK_Buffer *buf, const size_t size, const unsigned char *data) { // Do not rely on glibc realloc to handle zero size. See man 3 realloc - // Nonportable behavior. if (size == 0) { if (buf->addr) { free (buf->addr); buf->addr = NULL; } } else { // If buf->addr is NULL, realloc == malloc. This is portable. unsigned char *tmp = realloc (buf->addr, size); if (UNLIKELY (size > 0 && tmp == NULL)) return VOLK_MEM_ERR; buf->addr = tmp; } buf->size = size; if (data && buf->addr) memcpy (buf->addr, data, buf->size); return VOLK_OK; } void VOLK_buffer_print (const VOLK_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 * VOLK_buffer_as_str (const VOLK_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 VOLK_buffer_done (VOLK_Buffer *buf) { if (LIKELY (buf) && !(buf->flags & VOLK_BUF_BORROWED)) free (buf->addr); } void VOLK_buffer_free (VOLK_Buffer *buf) { VOLK_buffer_done (buf); free (buf); } /* * Buffer triples. */ VOLK_BufferTriple * VOLK_btriple_new(VOLK_Buffer *s, VOLK_Buffer *p, VOLK_Buffer *o) { VOLK_BufferTriple *sspo = malloc (sizeof (*sspo)); if (!sspo) return NULL; if (UNLIKELY (VOLK_btriple_init (sspo, s, p, o))) { free (sspo); return NULL; } return sspo; } VOLK_rc VOLK_btriple_init ( VOLK_BufferTriple *sspo, VOLK_Buffer *s, VOLK_Buffer *p, VOLK_Buffer *o) { sspo->s = s; sspo->p = p; sspo->o = o; return VOLK_OK; } void VOLK_btriple_done (VOLK_BufferTriple *sspo) { if (UNLIKELY (!sspo)) return; VOLK_buffer_done (sspo->s); VOLK_buffer_done (sspo->p); VOLK_buffer_done (sspo->o); } void VOLK_btriple_free (VOLK_BufferTriple *sspo) { if (UNLIKELY (!sspo)) return; VOLK_buffer_free (sspo->s); VOLK_buffer_free (sspo->p); VOLK_buffer_free (sspo->o); 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. */ VOLK_Key VOLK_buffer_hash (const VOLK_Buffer *buf); VOLK_Key VOLK_btriple_hash (const VOLK_BufferTriple *strp); VOLK_Buffer *VOLK_btriple_pos (const VOLK_BufferTriple *trp, VOLK_TriplePos n);