Compare commits

...

10 Commits

Author SHA1 Message Date
Alexander Vdolainen
44f7aba37b Added: ndbuf_free_item manpage; 2018-09-18 19:11:03 +03:00
Alexander Vdolainen
68aa01d300 Added: ndbuf_free_item() function to free in a proper way e.g.
free allocated stuff via escan function.
2018-09-17 20:29:03 +03:00
Alexander Vdolainen
fb41052802 Added: new flag NDBUF_MOLS - if applied it will use allocless/memcpyless
escan e.g. just setup pointers to appropriate values within a raw
buffer memory piece.
2018-09-17 20:15:25 +03:00
Alexander Vdolainen
822146bf90 Version update: new things are added, time to increase version number; 2018-09-17 19:19:55 +03:00
Alexander Vdolainen
d0723c4a76 Added: Manpages directory and manpages for:
ndbuf_new(), ndbuf_new_frombuf(), ndbuf_new_wmops(),
	ndbuf_new_palloc(), ndbuf_new_free();
2018-09-17 18:38:37 +03:00
Alexander Vdolainen
6451c66518 Added: NDBUF_RORB flag is a read-only aware flag. Set this to avoid
writes to read-only buffers. E.g. use
ndbuf_setflags (b, NDBUF_RORB);
Fixes: More checks for non-reallocatable buffer are added;
2018-09-17 16:59:59 +03:00
baa1574746 Added possibility to use user defined memory ops:
Now u can create a special ndbuf with your custom memory operations,
 this is useful to keep ndbuf in a special mapped areas for a:
  - keep it secure (example lock pages to avoid your info going to swap)
  - using your own custom optimized allocator for your own block sizes
 Function: ndbuf_t *ndbuf_new_wmops(const struct ndbuf_memops *, const size_t);
  Args:
   1. Pointer to yout ops:
    struct ndbuf_memops {
     void *(*alloc)(size_t);
     uint32_t (*zero)(void *, size_t);
     void (*free)(void *ptr);
    };
   2. Size of chunk to grow buffer. if <= default value will be set.
2018-08-05 03:19:36 +03:00
0a9ff172a5 Fixed ret type warning; 2018-08-05 00:51:22 +03:00
Alexander Vdolainen
b6dba50071 NEWS updated; test commit (for sync); 2018-07-26 17:42:20 +03:00
Alexander Vdolainen
81bfa9eecc Fixed pkgconfig template file (version variable); 2018-07-26 16:05:46 +03:00
15 changed files with 405 additions and 68 deletions

View File

@ -1,3 +1,9 @@
0.0.2 (15-nov-2018)
* Added possibility to use user defined memory ops with:
ndbuf_t *ndbuf_new_wmops(const struct ndbuf_memops *, const size_t);
* Fixed bug with pkgconfig %VERSION% value
0.0.1 (24-nov-2017)
* initial version with all functions done
* tired from reuse this code and ... now it's lib

View File

@ -1,8 +1,9 @@
## Sample for libndbuf automaken stuff
## (c) alex@vapaa.xyz
## Distributed under GNU LGPL v2.1 or later
## Originally written by Alexander Vdolainen <alex@vapaa.xyz> (c) 2017
## Process this file with automake to produce Makefile.in
SUBDIRS = include
SUBDIRS = include man
clean-local:

2
NEWS
View File

@ -0,0 +1,2 @@
NEWS template
-------------

View File

@ -1,2 +1,2 @@
0.0.1
0.0.2

View File

@ -16,4 +16,5 @@ AC_OUTPUT([
Makefile
libndbuf.pc
include/Makefile
man/Makefile
])

View File

@ -5,12 +5,12 @@
* (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
* (c) Alexander Vdolainen 2017 <alex@vapaa.xyz>
*
* 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,16 +27,33 @@
#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);
uint32_t (*zero)(void *, size_t);
void (*free)(void *ptr);
};
typedef struct __rawdatabuffer_type {
char *raw;
union {
void (*freebuf)(char *);
const struct ndbuf_memops *mop;
};
uint32_t rlength; /* raw buffer allocated length */
uint32_t ulength; /* length of used allocated space */
uint32_t curr; /* cursor for read/write operations */
int flags;
void (*freebuf)(char *);
size_t blk_size;
uint32_t flags;
} ndbuf_t;
/* variadic macro workaround */
@ -67,12 +84,15 @@ typedef struct __rawdatabuffer_type {
/* allocate raw buffer with defaults preallocation */
ndbuf_t *ndbuf_new(void);
/* will do the same as ndbuf_new but will allocate given length */
/* will do the same as ndbuf_new but will pre-allocate with the given length */
ndbuf_t *ndbuf_new_palloc(uint32_t);
/* create ndbuf from raw buffer */
ndbuf_t *ndbuf_new_frombuf(char *buf, size_t buf_len, void (*freebuf)(char *));
/* create a new buffer with user defined memops */
ndbuf_t *ndbuf_new_wmops(const struct ndbuf_memops *, const size_t);
/* free all allocated space and buffer itself */
void ndbuf_free(ndbuf_t *);
@ -158,4 +178,7 @@ int ndbuf_cmp(ndbuf_t *, ndbuf_t *);
*/
int ndbuf_memopt(ndbuf_t *);
/* free in a right way: freing allocated memory during escan */
void ndbuf_free_item(ndbuf_t *b, void *ip, size_t is);
#endif /* __NDBUF_H__ */

View File

@ -7,7 +7,7 @@ includedir=@includedir@
Name: libndbuf
Description: Network designed binary buffer pack/unpack library
Version: @LIBNDBUF_VERSION@
Version: @VERSION@
Requires:
Libs: -L${libdir} -lndbuf
Cflags: -I${includedir}

2
man/Makefile.am Normal file
View File

@ -0,0 +1,2 @@
man_MANS = ndbuf_new.3 ndbuf_new_palloc.3 ndbuf_new_wmops.3 ndbuf_new_frombuf.3 \
ndbuf_free.3 ndbuf_free_item.3

1
man/ndbuf_free.3 Symbolic link
View File

@ -0,0 +1 @@
ndbuf_new.3

1
man/ndbuf_free_item.3 Symbolic link
View File

@ -0,0 +1 @@
ndbuf_new.3

141
man/ndbuf_new.3 Normal file
View File

@ -0,0 +1,141 @@
.TH NDBUF_NEW 3 "15 September 2018" "NDBUF" "Binary buffers lib manual"
.SH NAME
ndbuf_new \- Create a new raw buffer with library defaults
.br
ndbuf_new_palloc \- Create a new raw buffer with predefined length
.br
ndbuf_new_frombuf \- Create a new raw buffer with given data
.br
ndbuf_new_wmops \- Create a new raw buffer with user-defined memory ops
.br
ndbuf_free \- Free raw buffer structure
.br
.SH SYNOPSIS
.B #include <ndbuf/ndbuf.h>
.sp
ndbuf_t *ndbuf_new(void);
ndbuf_t *ndbuf_new_palloc(uint32_t);
ndbuf_t *ndbuf_new_frombuf(char *buf, size_t buf_len, void (*freebuf)(char *));
ndbuf_t *ndbuf_new_wmops(const struct ndbuf_memops *, const size_t);
void ndbuf_free(ndbuf_t *);
void ndbuf_free_item(ndbuf_t *b, void *ip, size_t is);
struct ndbuf_memops {
.br
void *(*alloc)(size_t);
.br
uint32_t (*zero)(void *, size_t);
.br
void (*free)(void *ptr);
.br
};
.br
.sp
.SH DESCRIPTION
.B ndbuf_new
family of functions are used to create
.B ndbuf_t
structure with a different options.
.br
.br
.B ndbuf_new()
will create a
.B ndbuf_t
with defaults values and default memory chunk preallocated. No special flags are assigned during the creation.
.br
.br
.B ndbuf_new_palloc(uint32_t)
will create a
.B ndbuf_t
with defaults values, but buffer will be allocated with the given lenght. No special flags are assigned during the call.
.br
.br
.B ndbuf_new_frombuf(char *buf, size_t buf_len, void (*freebuf)(char *))
will create a
.B ndbuf_t
with buffer point to *buf and is assume the length of this buffer is buf_len, function freebuf will be used during
.B ndbuf_t
freeing if provided. A few flags will be set:
.br
.B NDBUF_NREA
means non-reallocatable buffer. See also
.B ndbuf_setflags(3)
man page for further flags exaplanations.
.br
.br
.B ndbuf_new_wmops(const struct ndbuf_memops *, const size_t)
is used to create a
.B ndbuf_t
with a custom provided memory options and custom memory block size. Provided structure should has a few functions pointers:
.br
.B alloc(size_t)
is used to allocate a memory block
.br
.B zero(void *, size_t)
is used to zero/fill freed or newly allocated memory if
.B NDBUF_BURN
flag is set.
.br
.B free(void *)
is used to free allocated memory.
.br
No specific flags are set upon a call.
.br
.br
.B ndbuf_free(ndbuf_t *)
is used to free a corresponding
.B ndbuf_t
structure, and connected raw buffer data as well, excepting the following cases:
.br
.B NDBUF_NREA
flag is set and no
.B freebuf()
function pointer is provided.
.br
.B NDBUF_RORB
flag is set.
.br
.br
.B void ndbuf_free_item(ndbuf_t*, void*, size_t)
will free allocated item via escan function, if flag
.B NDBUF_BURN
is set and size in't 0 memset() or zero() custom function will be called prior to free. This function is using default memory allocation/deallocation functions or (if provided) custom ones.
.br
.SH RETURN VALUE
.B ndbuf_new
family of functions returns a pointer to newly created
.B ndbuf_t
structure or
.B NULL
otherwise (if any error occurs, or invalid options are given).
.br
No specific errno code is set in case of error.
.br
.SH BUGS
Not known yet.
.SH EXAMPLE
None.
.SH APPLICATION USAGE
None.
.SH RATIONALE
.B ndbuf_new_wmops()
is recommended to use in specific environments i.e. when users are required to store and process all data buffers in a secure way (use special memory allocation to avoid memory pages swappnig, avoid memset() optimization etc ...).
.SH SEE ALSO
.BI ndbuf_setflags(3)
.SH COPYRIGHT
This software licensed under GNU LGPL v2.1 or later. See COPYING for further details.
.br
(c) Authors of libndbuf 2017-2018 <http://vapaa.xyz>
.SH AUTHOR
Alexander Vdolainen (alex@vapaa.xyz)

1
man/ndbuf_new_frombuf.3 Symbolic link
View File

@ -0,0 +1 @@
ndbuf_new.3

1
man/ndbuf_new_palloc.3 Symbolic link
View File

@ -0,0 +1 @@
ndbuf_new.3

1
man/ndbuf_new_wmops.3 Symbolic link
View File

@ -0,0 +1 @@
ndbuf_new.3

274
ndbuf.c
View File

@ -2,14 +2,14 @@
* Networking binary buffers pack/unpack library
*
* (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
* (c) Alexander Vdolainen 2017 <alex@vapaa.xyz>
* (c) Alexander Vdolainen 2017, 2018 <alex@vapaa.xyz>
*
* 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.
@ -34,7 +34,7 @@ static inline uint64_t ntohll(uint64_t n)
#ifdef WORDS_BIGENDIAN
return n;
#else /* WORDS_BIGENDIAN */
return (((uint64_t)(n) << 56) | \
return (uint64_t)(((uint64_t)(n) << 56) | \
(((uint64_t)(n) << 40) & 0xff000000000000ULL) | \
(((uint64_t)(n) << 24) & 0xff0000000000ULL) | \
(((uint64_t)(n) << 8) & 0xff00000000ULL) | \
@ -104,16 +104,51 @@ ndbuf_t *ndbuf_new_palloc(uint32_t alen)
return b;
}
ndbuf_t *ndbuf_new_wmops(const struct ndbuf_memops *o, const size_t blk_len)
{
ndbuf_t *b = NULL;
if(!o) return NULL;
else { /* avoid nil calls */
if(!o->alloc || !o->free) return NULL;
}
if(!(b = malloc(sizeof(ndbuf_t)))) return NULL;
else memset(b, 0, sizeof(ndbuf_t));
if(blk_len <= 0) b->blk_size = DEFAULT_PREALLOC_SIZE;
if(!(b->raw = o->alloc(b->blk_size))) {
free(b);
return NULL;
} else {
b->rlength = b->blk_size;
b->ulength = b->curr = 0;
b->mop = o;
b->flags |= NDBUF_UCMO;
}
return b;
}
/* free all allocated space and buffer itself */
void ndbuf_free(ndbuf_t *b)
{
const struct ndbuf_memops *o = NULL;
if(!b) return;
if((b->flags & NDBUF_BURN) && b->raw)
memset(b->raw, 0, b->rlength);
if(b->flags & NDBUF_UCMO) o = b->mop;
if((b->flags & NDBUF_NREA) && b->freebuf) b->freebuf(b->raw);
else if(b->raw) free(b->raw);
if(o) {
if((b->flags & NDBUF_BURN) && o->zero) o->zero((void *)b->raw, b->rlength);
o->free(b->raw);
} else {
if((b->flags & NDBUF_BURN) && b->raw)
memset(b->raw, 0, b->rlength);
if((b->flags & NDBUF_NREA) && b->freebuf) b->freebuf(b->raw);
else if(b->raw) free(b->raw);
}
if(b->flags & NDBUF_BURN) memset(b, 0, sizeof(ndbuf_t));
free(b);
@ -210,23 +245,37 @@ static int __rdb_grow(ndbuf_t *b, uint32_t len)
{
uint32_t rlen;
char *ne = NULL;
const struct ndbuf_memops *o = NULL;
size_t bs = b->blk_size;
if(!len) return -1;
if(b->rlength + len > NDBUF_MAXLENGTH) return -1;
rlen = len +
(len%DEFAULT_PREALLOC_SIZE != 0 ? (DEFAULT_PREALLOC_SIZE - len%DEFAULT_PREALLOC_SIZE) : 0);
if(b->flags & NDBUF_UCMO) o = b->mop;
rlen = len + (len%bs != 0 ? (bs - len%bs) : 0);
if(b->rlength + rlen > NDBUF_MAXLENGTH) rlen = len;
rlen += b->rlength;
if(!(ne = malloc(rlen))) return -1;
if(o) ne = (char *)o->alloc(rlen);
else ne = malloc(rlen);
if(b->flags & NDBUF_BURN) memset(ne, 0, rlen);
if(!ne) return -1;
if(b->flags & NDBUF_BURN) {
if(o) o->zero((void *)ne, rlen);
else memset(ne, 0, rlen);
}
memcpy(ne, b->raw, b->ulength);
if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength);
free(b->raw);
if(o) {
if(b->flags & NDBUF_BURN) o->zero((void *)b->raw, b->rlength);
o->free((void *)b->raw);
} else {
if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength);
free(b->raw);
}
b->raw = ne;
b->rlength = rlen;
@ -287,12 +336,25 @@ uint32_t ndbuf_write_u64(ndbuf_t *b, uint64_t uu)
return sizeof(uint64_t);
}
static inline int __ndbuf_is_ro(ndbuf_t *b)
{
return (b->flags & NDBUF_RORB) ? 1 : 0;
}
static inline int __ndbuf_is_nrea(ndbuf_t *b)
{
return (b->flags & NDBUF_NREA) ? 1 : 0;
}
/* write raw data with the given length */
uint32_t ndbuf_write_raw(ndbuf_t *b, void *wi, uint32_t len)
{
if(!b || !b->raw) return 0;
if(!wi || !len) return 0;
if(__ndbuf_is_ro(b)) return 0; /* read only buffer */
if(b->ulength + len >= b->rlength) {
if(__ndbuf_is_nrea(b)) return 0; /* non reallocatable buffer */
if(__rdb_grow(b, len)) return 0;
}
@ -306,27 +368,46 @@ uint32_t ndbuf_write_raw(ndbuf_t *b, void *wi, uint32_t len)
uint32_t ndbuf_write_raw_head(ndbuf_t *b, void *wi, uint32_t len)
{
char *ne;
const struct ndbuf_memops *o = NULL;
uint32_t rlen;
size_t bs = b->blk_size;
if(!b || !b->raw) return 0;
if(!wi || !len) return 0;
if(__ndbuf_is_ro(b)) return 0; /* read only buffer */
if(b->ulength + len > b->rlength) {
if(__ndbuf_is_nrea(b)) return 0; /* non reallocatable buffer */
/* allocate a new one and copy it right */
if(b->rlength + len > NDBUF_MAXLENGTH) return -1;
rlen = len +
(len%DEFAULT_PREALLOC_SIZE != 0 ? (DEFAULT_PREALLOC_SIZE - len%DEFAULT_PREALLOC_SIZE) : 0);
rlen = len + (len%bs != 0 ? (bs - len%bs) : 0);
if(b->rlength + rlen > NDBUF_MAXLENGTH) rlen = len;
rlen += b->rlength;
if(!(ne = malloc(rlen))) return -1;
if(b->flags & NDBUF_BURN) memset(ne, 0, rlen);
if(b->flags & NDBUF_UCMO) o = b->mop;
if(o) ne = (char *)o->alloc(rlen);
else ne = malloc(rlen);
if(!ne) return -1;
if(b->flags & NDBUF_BURN) {
if(o) o->zero((void *)ne, rlen);
else memset(ne, 0, rlen);
}
memcpy((void *)ne + len, b->raw, b->ulength);
if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength);
free(b->raw);
if(o) {
if(b->flags & NDBUF_BURN) o->zero((void *)b->raw, b->rlength);
o->free((void *)b->raw);
} else {
if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength);
free(b->raw);
}
b->raw = ne;
b->rlength = rlen;
} else {
@ -339,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;
@ -352,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);
@ -393,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;
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;
}
len = ndbuf_read_raw(b, *d._cstr, clen);
if(len != clen) {
free(*d._cstr);
goto __errrbread;
}
(*d._cstr)[len] = '\0';
d._cstr = NULL;
r = 0;
break;
case 'p':
@ -414,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;
@ -435,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;
@ -498,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':
@ -511,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 *);
@ -552,6 +666,8 @@ uint32_t ndbuf_print_va(ndbuf_t *b, const char *fmt, int argc, va_list ap)
uint32_t len = 0, clen;
int r, count;
if(__ndbuf_is_ro(b)) return 0; /* read only buffer */
for(t = fmt, count = 0; *t != '\0'; t++, count++) {
if(count > argc && argc != -1) return 0;
switch(*t) {
@ -705,6 +821,8 @@ void ndbuf_setflags(ndbuf_t *b, int af)
{
if(!b) return;
if(((af & NDBUF_BURN) && (b->flags & NDBUF_UCMO)) && !b->mop->zero) return;
b->flags |= af;
return;
@ -715,6 +833,8 @@ void ndbuf_exflags(ndbuf_t *b, int nf)
{
if(!b) return;
if(b->flags & NDBUF_UCMO) nf |= NDBUF_UCMO;
b->flags = nf;
return;
@ -749,24 +869,43 @@ int ndbuf_cmp(ndbuf_t *b1, ndbuf_t *b2)
/* let the buffer to use actually used bytes, not all allocated space
* will return 0 on success (or in case if it doesn't required),
* ENOMEM or other error if fails
* TODO: ? make this buffer non reallocable ?
*/
int ndbuf_memopt(ndbuf_t *b)
{
uint32_t len;
size_t bs = b->blk_size;
char *ne;
const struct ndbuf_memops *o = NULL;
if(!b || !b->raw) return EINVAL;
if((b->rlength - b->ulength) > DEFAULT_PREALLOC_SIZE) {
if((b->rlength - b->ulength) > bs) {
len = b->ulength +
(b->ulength%DEFAULT_PREALLOC_SIZE != 0 ?
(DEFAULT_PREALLOC_SIZE - b->ulength%DEFAULT_PREALLOC_SIZE) : 0);
if(!(ne = malloc(len))) return ENOMEM;
(b->ulength%bs != 0 ? (bs - b->ulength%bs) : 0);
if(b->flags & NDBUF_UCMO) o = b->mop;
if(o) ne = (char *)o->alloc(len);
else ne = malloc(len);
if(!ne) return ENOMEM;
if(b->flags & NDBUF_BURN) {
if(o) o->zero((void *)ne, len);
else memset(ne, 0, len);
}
if(b->flags & NDBUF_BURN) memset(ne, 0, len);
memcpy(ne, b->raw, b->ulength);
if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->ulength);
free(b->raw);
if(o) {
if(b->flags & NDBUF_BURN) o->zero((void *)b->raw, b->rlength);
o->free((void *)b->raw);
} else {
if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength);
free(b->raw);
}
b->raw = ne;
b->rlength = len;
}
@ -774,4 +913,21 @@ int ndbuf_memopt(ndbuf_t *b)
return 0;
}
void ndbuf_free_item(ndbuf_t *b, void *ip, size_t is)
{
if(!b || !ip) return;
if(__is_moless(b->flags)) return;
if(__is_usermo(b->flags)) {
if((b->flags & NDBUF_BURN) && (is > 0)) b->mop->zero(ip, is);
b->mop->free(ip);
} else {
if((b->flags & NDBUF_BURN) && (is > 0)) memset(ip, 0, is);
free(ip);
}
return;
}
#undef DEFAULT_PREALLOC_SIZE