diff --git a/include/ndbuf/ndbuf.h b/include/ndbuf/ndbuf.h index 386413c..87184f9 100644 --- a/include/ndbuf/ndbuf.h +++ b/include/ndbuf/ndbuf.h @@ -5,12 +5,12 @@ * (c) Alexander Vdolainen 2016 * (c) Alexander Vdolainen 2017 * - * libtbusd is free software: you can redistribute it and/or modify it + * libndbuf is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 2.1 of the License, or * (at your option) any later version. * - * libtbusd is distributed in the hope that it will be useful, but + * libndbuf is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. @@ -27,10 +27,15 @@ #define NDBUF_TERMINAT 0xdeadbeef +/* List of supported flags: */ #define NDBUF_BURN (1 << 1) /* burn buffer data before free */ #define NDBUF_NREA (1 << 2) /* non reallocatable buffer */ #define NDBUF_UCMO (1 << 3) /* user defined memops functions */ #define NDBUF_RORB (1 << 4) /* read-only buffer */ +#define NDBUF_MOLS (1 << 5) /* "memory-ops"-less escan i.e. return + * pointers to the raw buffer itself, + * instead of alloc/memcpy + */ struct ndbuf_memops { void *(*alloc)(size_t); diff --git a/ndbuf.c b/ndbuf.c index 643a306..c3deaf8 100644 --- a/ndbuf.c +++ b/ndbuf.c @@ -2,14 +2,14 @@ * Networking binary buffers pack/unpack library * * (c) Alexander Vdolainen 2016 - * (c) Alexander Vdolainen 2017 + * (c) Alexander Vdolainen 2017, 2018 * - * libtbusd is free software: you can redistribute it and/or modify it + * libndbuf is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 2.1 of the License, or * (at your option) any later version. * - * libtbusd is distributed in the hope that it will be useful, but + * libndbuf is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. @@ -420,8 +420,14 @@ uint32_t ndbuf_write_raw_head(ndbuf_t *b, void *wi, uint32_t len) } /* parse */ +#define __is_moless(x) ((x) & NDBUF_MOLS) ? 1 : 0 +#define __is_usermo(x) ((x) & NDBUF_UCMO) ? 1 : 0 + int ndbuf_escan_va(ndbuf_t *b, const char *fmt, int argc, va_list ap) { + register uint32_t fo = b->flags; + register uint32_t len; + uint32_t clen; va_list ap_copy; union { uint8_t *_u8; @@ -433,7 +439,6 @@ int ndbuf_escan_va(ndbuf_t *b, const char *fmt, int argc, va_list ap) ndbuf_t **_rdb; } d; const char *t, *last; - uint32_t len, clen; int r, count; va_copy(ap_copy, ap); @@ -474,18 +479,26 @@ int ndbuf_escan_va(ndbuf_t *b, const char *fmt, int argc, va_list ap) r = -1; break; } + /* FIXME: Document the following line in manpages %limits% */ if(clen > NDBUF_MAXLENGTH) goto __errrbread; - if((*d._cstr = malloc(clen + sizeof(char))) == NULL) { - r = -ENOMEM; - break; - } - len = ndbuf_read_raw(b, *d._cstr, clen); - if(len != clen) { - free(*d._cstr); - goto __errrbread; + + if(__is_moless(fo)) { + *d._cstr = b->raw + b->curr; + } else { + if(__is_usermo(fo)) *d._cstr = b->mop->alloc(clen + sizeof(char)); + else *d._cstr = malloc(clen + sizeof(char)); + if(*d._cstr == NULL) { + r = -ENOMEM; + break; + } + len = ndbuf_read_raw(b, *d._cstr, clen); + if(len != clen) { + free(*d._cstr); + goto __errrbread; + } + (*d._cstr)[len] = '\0'; + d._cstr = NULL; } - (*d._cstr)[len] = '\0'; - d._cstr = NULL; r = 0; break; case 'p': @@ -495,14 +508,20 @@ int ndbuf_escan_va(ndbuf_t *b, const char *fmt, int argc, va_list ap) *d._dp = NULL; count++; - if((*d._dp = malloc(clen)) == NULL) { - r = -ENOMEM; - break; - } - len = ndbuf_read_raw(b, *d._dp, clen); - if(len != clen) { - free(*d._dp); - goto __errrbread; + if(__is_moless(fo)) { + *d._dp = b->raw + b->curr; + } else { + if(__is_usermo(fo)) *d._dp = b->mop->alloc(clen); + else *d._dp = malloc(clen); + if(*d._dp == NULL) { + r = -ENOMEM; + break; + } + len = ndbuf_read_raw(b, *d._dp, clen); + if(len != clen) { + free(*d._dp); + goto __errrbread; + } } d._dp = NULL; r = 0; @@ -516,19 +535,25 @@ int ndbuf_escan_va(ndbuf_t *b, const char *fmt, int argc, va_list ap) r = -1; break; } - if((*d._dp = malloc(clen)) == NULL) { - r = -ENOMEM; - break; - } - len = ndbuf_read_raw(b, *d._dp, clen); - if(len != clen) { - free(*d._dp); - goto __errrbread; + if(__is_moless(fo)) { + *d._dp = b->raw + b->curr; + } else { + if(__is_usermo(fo)) *d._dp = b->mop->alloc(clen); + else *d._dp = malloc(clen); + if(*d._dp == NULL) { + r = -ENOMEM; + break; + } + len = ndbuf_read_raw(b, *d._dp, clen); + if(len != clen) { + free(*d._dp); + goto __errrbread; + } } d._dp = NULL; r = 0; break; - case 'R': + case 'R': /* FIXME: what about moless and user defined ops ? */ d._rdb = va_arg(ap, ndbuf_t **); *d._rdb = NULL; @@ -579,9 +604,14 @@ int ndbuf_escan_va(ndbuf_t *b, const char *fmt, int argc, va_list ap) break; case 's': d._cstr = va_arg(ap_copy, char **); - if(*d._cstr) { - memset(*d._cstr, 0, strlen(*d._cstr)); - free(*d._cstr); + if(*d._cstr && !__is_moless(fo)) { + if(__is_usermo(fo)) { + b->mop->zero(*d._cstr, strlen(*d._cstr)); + b->mop->free(*d._cstr); + } else { + memset(*d._cstr, 0, strlen(*d._cstr)); + free(*d._cstr); + } } break; case 'R': @@ -592,7 +622,10 @@ int ndbuf_escan_va(ndbuf_t *b, const char *fmt, int argc, va_list ap) (void)va_arg(ap_copy, size_t); case 'P': d._dp = va_arg(ap_copy, void **); - if(*d._dp) free(*d._dp); + if(*d._dp && !__is_moless(fo)) { + if(__is_usermo(fo)) b->mop->free(*d._dp); + else free(*d._dp); + } break; default: (void)va_arg(ap_copy, void *);