Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
9332a57be2 | |||
1f684819a4 | |||
b1d0950b71 | |||
6eea614d6c | |||
81756b45dd | |||
|
44f7aba37b | ||
|
68aa01d300 | ||
|
fb41052802 | ||
|
822146bf90 | ||
|
d0723c4a76 | ||
|
6451c66518 | ||
baa1574746 | |||
0a9ff172a5 | |||
|
b6dba50071 | ||
|
81bfa9eecc |
@ -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)
|
0.0.1 (24-nov-2017)
|
||||||
* initial version with all functions done
|
* initial version with all functions done
|
||||||
* tired from reuse this code and ... now it's lib
|
* tired from reuse this code and ... now it's lib
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
## Sample for libndbuf automaken stuff
|
## 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
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
SUBDIRS = include
|
SUBDIRS = include man
|
||||||
|
|
||||||
clean-local:
|
clean-local:
|
||||||
|
|
||||||
|
46
README
46
README
@ -1,30 +1,28 @@
|
|||||||
libndbuf: Network designed buffer ops library
|
libndbuf: Network-oriented buffer operations library
|
||||||
----------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
1. What the shit is that ?
|
1. What is it?
|
||||||
This is a quite small library to manipulate with binary packed buffers
|
A small C library providing a simple API to read and write typed values
|
||||||
in a normal network manner (i.e. bigendian). It might be useful to
|
to/from buffers with correct endianness handling.
|
||||||
apply for network packet creating/parsing.
|
|
||||||
Anyway, originally this code was resided in my different other *small*
|
|
||||||
projects - and i hate copy-paste -- well, that's why it gone to
|
|
||||||
this quite small library.
|
|
||||||
|
|
||||||
2. API
|
2. Purpose
|
||||||
Check out include directory...
|
Make parsing and building network packets easy and concise. The API is
|
||||||
btw, might be later i will write manpages, but for now didn't see any
|
intended to act like a binary printf/scanf for packet fields.
|
||||||
sense for those effort.
|
|
||||||
Generally speaking - all is quite simple - create ndbuf_t structure fill
|
Example:
|
||||||
it in printf() style, read with sscanf() style, take raw data pointer and ...
|
|
||||||
send it somewhere whatever bla bla - you get a point.
|
Packet layout:
|
||||||
|
<16-bit><8-bit><32-bit><raw data>
|
||||||
|
|
||||||
|
Reading with a single call:
|
||||||
|
ndbuf_escan(buf, "wbdR", &a16, &a8, &a32, &data_ptr)
|
||||||
|
|
||||||
|
The same style is used to build packets.
|
||||||
|
|
||||||
3. Future plans
|
3. Future plans
|
||||||
Fix bugs (but ... there are no bugs found, since this code was heavly used
|
* Improve the API ergonomics (better support for preallocated buffers).
|
||||||
already, but ... report me if found).
|
* Add convenience helpers and safer bounds checks.
|
||||||
Write manpages (in my few projects those API is like a part of POSIX -
|
* Possibly extend format specifiers and documentation.
|
||||||
still cannot remember all).
|
|
||||||
Maybe will add a new functions (useful ones).
|
|
||||||
|
|
||||||
4. Contact
|
4. Contact
|
||||||
That's simple -
|
Email: alex@vapaa.xyz
|
||||||
Email/XMPP: alex@vapaa.xyz
|
|
||||||
|
|
||||||
|
@ -16,4 +16,5 @@ AC_OUTPUT([
|
|||||||
Makefile
|
Makefile
|
||||||
libndbuf.pc
|
libndbuf.pc
|
||||||
include/Makefile
|
include/Makefile
|
||||||
|
man/Makefile
|
||||||
])
|
])
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
* (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
|
* (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
|
||||||
* (c) Alexander Vdolainen 2017 <alex@vapaa.xyz>
|
* (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
|
* 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
|
* by the Free Software Foundation, either version 2.1 of the License, or
|
||||||
* (at your option) any later version.
|
* (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
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
* See the GNU Lesser General Public License for more details.
|
* See the GNU Lesser General Public License for more details.
|
||||||
@ -27,16 +27,33 @@
|
|||||||
|
|
||||||
#define NDBUF_TERMINAT 0xdeadbeef
|
#define NDBUF_TERMINAT 0xdeadbeef
|
||||||
|
|
||||||
|
/* List of supported flags: */
|
||||||
#define NDBUF_BURN (1 << 1) /* burn buffer data before free */
|
#define NDBUF_BURN (1 << 1) /* burn buffer data before free */
|
||||||
#define NDBUF_NREA (1 << 2) /* non reallocatable buffer */
|
#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 {
|
typedef struct __rawdatabuffer_type {
|
||||||
char *raw;
|
char *raw;
|
||||||
|
union {
|
||||||
|
void (*freebuf)(char *);
|
||||||
|
const struct ndbuf_memops *mop;
|
||||||
|
};
|
||||||
uint32_t rlength; /* raw buffer allocated length */
|
uint32_t rlength; /* raw buffer allocated length */
|
||||||
uint32_t ulength; /* length of used allocated space */
|
uint32_t ulength; /* length of used allocated space */
|
||||||
uint32_t curr; /* cursor for read/write operations */
|
uint32_t curr; /* cursor for read/write operations */
|
||||||
int flags;
|
size_t blk_size;
|
||||||
void (*freebuf)(char *);
|
uint32_t flags;
|
||||||
} ndbuf_t;
|
} ndbuf_t;
|
||||||
|
|
||||||
/* variadic macro workaround */
|
/* variadic macro workaround */
|
||||||
@ -67,12 +84,15 @@ typedef struct __rawdatabuffer_type {
|
|||||||
/* allocate raw buffer with defaults preallocation */
|
/* allocate raw buffer with defaults preallocation */
|
||||||
ndbuf_t *ndbuf_new(void);
|
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);
|
ndbuf_t *ndbuf_new_palloc(uint32_t);
|
||||||
|
|
||||||
/* create ndbuf from raw buffer */
|
/* create ndbuf from raw buffer */
|
||||||
ndbuf_t *ndbuf_new_frombuf(char *buf, size_t buf_len, void (*freebuf)(char *));
|
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 */
|
/* free all allocated space and buffer itself */
|
||||||
void ndbuf_free(ndbuf_t *);
|
void ndbuf_free(ndbuf_t *);
|
||||||
|
|
||||||
@ -158,4 +178,7 @@ int ndbuf_cmp(ndbuf_t *, ndbuf_t *);
|
|||||||
*/
|
*/
|
||||||
int ndbuf_memopt(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__ */
|
#endif /* __NDBUF_H__ */
|
||||||
|
@ -7,7 +7,7 @@ includedir=@includedir@
|
|||||||
|
|
||||||
Name: libndbuf
|
Name: libndbuf
|
||||||
Description: Network designed binary buffer pack/unpack library
|
Description: Network designed binary buffer pack/unpack library
|
||||||
Version: @LIBNDBUF_VERSION@
|
Version: @VERSION@
|
||||||
Requires:
|
Requires:
|
||||||
Libs: -L${libdir} -lndbuf
|
Libs: -L${libdir} -lndbuf
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
5
man/Makefile.am
Normal file
5
man/Makefile.am
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
man_MANS = ndbuf_new.3 ndbuf_new_palloc.3 ndbuf_new_wmops.3 ndbuf_new_frombuf.3 \
|
||||||
|
ndbuf_free.3 ndbuf_free_item.3 ndbuf_read_raw.3 ndbuf_read_u8.3 ndbuf_read_u16.3 \
|
||||||
|
ndbuf_read_u32.3 ndbuf_read_u64.3 ndbuf_write_raw.3 ndbuf_write_u8.3 ndbuf_write_u16.3 \
|
||||||
|
ndbuf_write_u32.3 ndbuf_write_u64.3
|
||||||
|
|
1
man/ndbuf_free.3
Symbolic link
1
man/ndbuf_free.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_new.3
|
1
man/ndbuf_free_item.3
Symbolic link
1
man/ndbuf_free_item.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_new.3
|
156
man/ndbuf_new.3
Normal file
156
man/ndbuf_new.3
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
.TH NDBUF_NEW 3 "15 September 2018" "NDBUF" "Binary buffers lib manual"
|
||||||
|
.SH NAME
|
||||||
|
ndbuf_new, ndbuf_new_palloc, ndbuf_new_frombuf, ndbuf_new_wmops, ndbuf_free - allocate and free buffer structure
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B "#include <ndbuf/ndbuf.h>"
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
ndbuf_t *ndbuf_new(void);
|
||||||
|
ndbuf_t *ndbuf_new_palloc(uint32_t len);
|
||||||
|
ndbuf_t *ndbuf_new_frombuf(char *buf, size_t buf_len,
|
||||||
|
void (*freebuf)(char *));
|
||||||
|
ndbuf_t *ndbuf_new_wmops(const struct ndbuf_memops *mops,
|
||||||
|
const size_t block_size);
|
||||||
|
void ndbuf_free(ndbuf_t *b);
|
||||||
|
void ndbuf_free_item(ndbuf_t *b, void *item, size_t item_size);
|
||||||
|
.PP
|
||||||
|
struct ndbuf_memops {
|
||||||
|
.br
|
||||||
|
void *(*alloc)(size_t);
|
||||||
|
.br
|
||||||
|
uint32_t (*zero)(void *, size_t);
|
||||||
|
.br
|
||||||
|
void (*free)(void *);
|
||||||
|
.br
|
||||||
|
};
|
||||||
|
.fi
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The
|
||||||
|
.B ndbuf_new
|
||||||
|
family of functions create and initialize an
|
||||||
|
.B ndbuf_t
|
||||||
|
structure using different allocation and memory-operation options. These routines simplify handling raw network-oriented buffers while providing hooks for custom memory management and secure wiping.
|
||||||
|
.PP
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_new()
|
||||||
|
Allocate and return a newly initialized
|
||||||
|
.B ndbuf_t
|
||||||
|
using library defaults. A default memory chunk is preallocated. No special flags are set.
|
||||||
|
.PP
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_new_palloc(uint32_t len)
|
||||||
|
Allocate and return a new
|
||||||
|
.B ndbuf_t
|
||||||
|
with an initial buffer of the specified length (in bytes). Other defaults apply; no special flags are set.
|
||||||
|
.PP
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_new_frombuf(char *buf, size_t buf_len, void (*freebuf)(char *))
|
||||||
|
Create a
|
||||||
|
.B ndbuf_t
|
||||||
|
that uses the provided buffer pointer
|
||||||
|
.I buf
|
||||||
|
of length
|
||||||
|
.I buf_len
|
||||||
|
as its underlying storage. If
|
||||||
|
.I freebuf
|
||||||
|
is a valid pointer to the function, it will be called to free the buffer when the ndbuf is destroyed. The returned ndbuf will have the
|
||||||
|
.B NDBUF_NREA
|
||||||
|
flag set, indicating the buffer is non-reallocatable. See
|
||||||
|
.BR ndbuf_setflags(3)
|
||||||
|
for flag details.
|
||||||
|
.PP
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_new_wmops(const struct ndbuf_memops *mops, const size_t block_size)
|
||||||
|
Create a
|
||||||
|
.B ndbuf_t
|
||||||
|
that uses the caller-provided memory-operation callbacks and a custom block size. The
|
||||||
|
.I mops
|
||||||
|
structure must provide the following function pointers:
|
||||||
|
.IP
|
||||||
|
.B alloc(size_t)
|
||||||
|
Function to allocate a memory block of the given size.
|
||||||
|
.IP
|
||||||
|
.B zero(void *, size_t)
|
||||||
|
Function to zero or overwrite a memory region; used when the
|
||||||
|
.B NDBUF_BURN
|
||||||
|
flag is set to securely erase memory.
|
||||||
|
.IP
|
||||||
|
.B free(void *)
|
||||||
|
Free a previously allocated memory block.
|
||||||
|
.IP
|
||||||
|
No special flags are set by this call.
|
||||||
|
.PP
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_free(ndbuf_t *b)
|
||||||
|
Free the
|
||||||
|
.I ndbuf_t
|
||||||
|
structure and, unless prevented by flags or missing free callbacks, free the associated buffer data. The underlying buffer is not freed if:
|
||||||
|
.IP
|
||||||
|
The
|
||||||
|
.B NDBUF_NREA
|
||||||
|
flag is set and no
|
||||||
|
.I freebuf
|
||||||
|
callback was provided in
|
||||||
|
.B ndbuf_new_frombuf().
|
||||||
|
.IP
|
||||||
|
The
|
||||||
|
.B NDBUF_RORB
|
||||||
|
flag is set.
|
||||||
|
.PP
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_free_item(ndbuf_t *b, void item, size_t item_size)
|
||||||
|
Free an item previously allocated via the library's escan function. If the
|
||||||
|
.B NDBUF_BURN
|
||||||
|
flag is set and
|
||||||
|
.I item_size
|
||||||
|
is non-zero, the buffer will be securely zeroed (via
|
||||||
|
.B zero()
|
||||||
|
or
|
||||||
|
.B memset()
|
||||||
|
) before being freed. This function uses the default memory ops unless custom ops were provided at creation.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
On success the
|
||||||
|
.B ndbuf_new
|
||||||
|
family of functions returns a pointer to the newly created
|
||||||
|
.B ndbuf_t.
|
||||||
|
On failure they return
|
||||||
|
.B NULL.
|
||||||
|
No specific
|
||||||
|
.I errno
|
||||||
|
value is set by these functions.
|
||||||
|
.SH ERRORS
|
||||||
|
These functions return NULL on allocation or initialization failure. Callers should check the return value before use.
|
||||||
|
.SH EXAMPLES
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
/ Create a default buffer */
|
||||||
|
ndbuf_t *b = ndbuf_new();
|
||||||
|
if (!b) { / handle error */ }
|
||||||
|
|
||||||
|
/* Create buffer from existing memory */
|
||||||
|
char *buf = malloc(256);
|
||||||
|
ndbuf_t *b2 = ndbuf_new_frombuf(buf, 256, free);
|
||||||
|
|
||||||
|
/* Create buffer with custom memory ops */
|
||||||
|
struct ndbuf_memops mops = { custom_alloc, custom_zero, custom_free };
|
||||||
|
ndbuf_t *b3 = ndbuf_new_wmops(&mops, 4096);
|
||||||
|
.fi
|
||||||
|
.SH RATIONALE
|
||||||
|
The
|
||||||
|
.B ndbuf_new_wmops()
|
||||||
|
function is useful for environments requiring special memory handling (for example, preventing pages from being swapped, using locked memory, or providing a custom zeroing routine to avoid compiler optimizations).
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR ndbuf_setflags(3),
|
||||||
|
.BR ndbuf_escan(3)
|
||||||
|
.SH COPYRIGHT
|
||||||
|
This software licensed under GNU LGPL v2.1 or later. See COPYING for further details.
|
||||||
|
.PP
|
||||||
|
(c) Authors of libndbuf 2017-2018 <http://vapaa.xyz>
|
||||||
|
.SH AUTHOR
|
||||||
|
Alexander Vdolainen (alex@vapaa.xyz)
|
1
man/ndbuf_new_frombuf.3
Symbolic link
1
man/ndbuf_new_frombuf.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_new.3
|
1
man/ndbuf_new_palloc.3
Symbolic link
1
man/ndbuf_new_palloc.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_new.3
|
1
man/ndbuf_new_wmops.3
Symbolic link
1
man/ndbuf_new_wmops.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_new.3
|
92
man/ndbuf_read_raw.3
Normal file
92
man/ndbuf_read_raw.3
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
.TH NDBUF_READ_RAW 3 "15 September 2018" "NDBUF" "Binary buffers lib manual"
|
||||||
|
.SH NAME
|
||||||
|
ndbuf_read_u8, ndbuf_read_u16, ndbuf_read_u32, ndbuf_read_u64,
|
||||||
|
ndbuf_read_raw - read data of specified length and type
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B "#include <ndbuf/ndbuf.h>"
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
uint32_t ndbuf_read_u8(ndbuf_t *b, uint8_t *val);
|
||||||
|
uint32_t ndbuf_read_u16(ndbuf_t *b, uint16_t *val);
|
||||||
|
uint32_t ndbuf_read_u32(ndbuf_t *b, uint32_t *val);
|
||||||
|
uint32_t ndbuf_read_u64(ndbuf_t *b, uint64_t *val);
|
||||||
|
uint32_t ndbuf_read_raw(ndbuf_t *b, void *dst, uint32_t len);
|
||||||
|
.fi
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The ndbuf_read_ family copies data from an
|
||||||
|
.B ndbuf_t
|
||||||
|
instance into caller-provided storage. On success each function returns the number of bytes read; on error it returns 0.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_read_u8(ndbuf_t *b, uint8_t *val)
|
||||||
|
Read one unsigned 8‑bit value from the current buffer position into
|
||||||
|
.I val
|
||||||
|
and advance the buffer cursor by one byte. Returned value is the number of bytes read (1) or 0 on error.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_read_u16(ndbuf_t *b, uint16_t *val)
|
||||||
|
Read one unsigned 16‑bit value, store it into
|
||||||
|
.I val
|
||||||
|
and advance the cursor by two bytes. Returns 2 on success or 0 on error.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_read_u32(ndbuf_t *b, uint32_t *val)
|
||||||
|
Read one unsigned 32‑bit value, store into
|
||||||
|
.I val
|
||||||
|
and advance the cursor by four bytes. Returns 4 on success or 0 on error.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_read_u64(ndbuf_t *b, uint64_t *val)
|
||||||
|
Read one unsigned 64‑bit value, store into
|
||||||
|
.I val
|
||||||
|
and advance the cursor by eight bytes. Returns 8 on success or 0 on error.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_read_raw(ndbuf_t *b, void *dst, uint32_t len)
|
||||||
|
Copy
|
||||||
|
.I len
|
||||||
|
bytes of raw data from the buffer to
|
||||||
|
.I dst
|
||||||
|
and advance the cursor by
|
||||||
|
.I len. The caller must ensure
|
||||||
|
.I dst
|
||||||
|
points to memory at least
|
||||||
|
.I len
|
||||||
|
bytes long. Returns the number of bytes copied or 0 on error.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
On success each function returns the number of bytes read. On error they return 0; no specific
|
||||||
|
.I errno
|
||||||
|
value is set.
|
||||||
|
.SH ERRORS
|
||||||
|
Functions return 0 when the requested read would exceed the available data, when
|
||||||
|
.I b
|
||||||
|
is NULL, or on other internal errors. Callers must validate the return value before using output data.
|
||||||
|
.SH RATIONALE
|
||||||
|
Use these functions when you need a local copy of numeric or raw data. For zero-copy parsing or formatted
|
||||||
|
extraction consider the
|
||||||
|
.BR ndbuf_escan(3)
|
||||||
|
family instead.
|
||||||
|
.SH EXAMPLES
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
/* Read values from buffer */
|
||||||
|
uint8_t a8;
|
||||||
|
uint16_t a16;
|
||||||
|
uint32_t a32;
|
||||||
|
if (ndbuf_read_u8(b, &a8) != 1) { /* handle error */ }
|
||||||
|
if (ndbuf_read_u16(b, &a16) != 2) { /* handle error */ }
|
||||||
|
if (ndbuf_read_u32(b, &a32) != 4) { /* handle error */ }
|
||||||
|
|
||||||
|
/* Read raw payload */
|
||||||
|
char payload[128];
|
||||||
|
if (ndbuf_read_raw(b, payload, sizeof(payload)) != sizeof(payload)) { /* handle error */ }
|
||||||
|
.fi
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR ndbuf_write_raw(3),
|
||||||
|
.BR ndbuf_escan(3)
|
||||||
|
.SH COPYRIGHT
|
||||||
|
This software licensed under GNU LGPL v2.1 or later. See COPYING for further details.
|
||||||
|
.PP
|
||||||
|
(c) Authors of libndbuf 2017-2018 <http://vapaa.xyz>
|
||||||
|
.SH AUTHOR
|
||||||
|
Alexander Vdolainen (alex@vapaa.xyz)
|
1
man/ndbuf_read_u16.3
Symbolic link
1
man/ndbuf_read_u16.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_read_raw.3
|
1
man/ndbuf_read_u32.3
Symbolic link
1
man/ndbuf_read_u32.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_read_raw.3
|
1
man/ndbuf_read_u64.3
Symbolic link
1
man/ndbuf_read_u64.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_read_raw.3
|
1
man/ndbuf_read_u8.3
Symbolic link
1
man/ndbuf_read_u8.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_read_raw.3
|
77
man/ndbuf_write_raw.3
Normal file
77
man/ndbuf_write_raw.3
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
.TH NDBUF_WRITE_RAW 3 "15 September 2018" "NDBUF" "Binary buffers lib manual"
|
||||||
|
.SH NAME
|
||||||
|
ndbuf_write_u8, ndbuf_write_u16, ndbuf_write_u32, ndbuf_write_u64,
|
||||||
|
ndbuf_write_raw - write data to the buffer of specified length and type
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B "#include <ndbuf/ndbuf.h>"
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
uint32_t ndbuf_write_u8(ndbuf_t *b, uint8_t val);
|
||||||
|
uint32_t ndbuf_write_u16(ndbuf_t *b, uint16_t val);
|
||||||
|
uint32_t ndbuf_write_u32(ndbuf_t *b, uint32_t val);
|
||||||
|
uint32_t ndbuf_write_u64(ndbuf_t *b, uint64_t val);
|
||||||
|
uint32_t ndbuf_write_raw(ndbuf_t *b, void *src, uint32_t len);
|
||||||
|
.fi
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The ndbuf_write_ family writes data to an
|
||||||
|
.B ndbuf_t
|
||||||
|
instance from caller-provided storage. On success each function returns the number of bytes written; on error it returns 0.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_write_u8(ndbuf_t *b, uint8_t val)
|
||||||
|
Write one unsigned 8‑bit value to the current buffer position from
|
||||||
|
.I val
|
||||||
|
and advance the buffer cursor by one byte. Returned value is the number of bytes written (1) or 0 on error.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_write_u16(ndbuf_t *b, uint16_t val)
|
||||||
|
Writes one unsigned 16‑bit value, from
|
||||||
|
.I val
|
||||||
|
and advance the cursor by two bytes. Returns 2 on success or 0 on error.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_write_u32(ndbuf_t *b, uint32_t val)
|
||||||
|
Write one unsigned 32‑bit value, from
|
||||||
|
.I val
|
||||||
|
and advance the cursor by four bytes. Returns 4 on success or 0 on error.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_write_u64(ndbuf_t *b, uint64_t val)
|
||||||
|
Write one unsigned 64‑bit value, from
|
||||||
|
.I val
|
||||||
|
and advance the cursor by eight bytes. Returns 8 on success or 0 on error.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B ndbuf_read_raw(ndbuf_t *b, void *dst, uint32_t len)
|
||||||
|
Copy
|
||||||
|
.I len
|
||||||
|
from
|
||||||
|
.I dst
|
||||||
|
to the buffer and advance the cursor by
|
||||||
|
.I len. The caller must ensure
|
||||||
|
.I dst
|
||||||
|
points to memory at least
|
||||||
|
.I len
|
||||||
|
bytes long. Returns the number of bytes copied or 0 on error.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
On success each function returns the number of bytes read. On error they return 0; no specific
|
||||||
|
.I errno
|
||||||
|
value is set.
|
||||||
|
.SH ERRORS
|
||||||
|
Functions return 0 when the requested read would exceed the available data, when
|
||||||
|
.I b
|
||||||
|
is NULL, or on other internal errors. Callers must validate the return value before using output data.
|
||||||
|
.SH RATIONALE
|
||||||
|
None
|
||||||
|
.SH EXAMPLES
|
||||||
|
None
|
||||||
|
.PP
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR ndbuf_read_raw(3),
|
||||||
|
.BR ndbuf_print(3)
|
||||||
|
.SH COPYRIGHT
|
||||||
|
This software licensed under GNU LGPL v2.1 or later. See COPYING for further details.
|
||||||
|
.PP
|
||||||
|
(c) Authors of libndbuf 2017-2018 <http://vapaa.xyz>
|
||||||
|
.SH AUTHOR
|
||||||
|
Alexander Vdolainen (alex@vapaa.xyz)
|
1
man/ndbuf_write_u16.3
Symbolic link
1
man/ndbuf_write_u16.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_write_raw.3
|
1
man/ndbuf_write_u32.3
Symbolic link
1
man/ndbuf_write_u32.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_write_raw.3
|
1
man/ndbuf_write_u64.3
Symbolic link
1
man/ndbuf_write_u64.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_write_raw.3
|
1
man/ndbuf_write_u8.3
Symbolic link
1
man/ndbuf_write_u8.3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ndbuf_write_raw.3
|
274
ndbuf.c
274
ndbuf.c
@ -2,14 +2,14 @@
|
|||||||
* Networking binary buffers pack/unpack library
|
* Networking binary buffers pack/unpack library
|
||||||
*
|
*
|
||||||
* (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
|
* (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
|
* 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
|
* by the Free Software Foundation, either version 2.1 of the License, or
|
||||||
* (at your option) any later version.
|
* (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
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
* See the GNU Lesser General Public License for more details.
|
* 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
|
#ifdef WORDS_BIGENDIAN
|
||||||
return n;
|
return n;
|
||||||
#else /* WORDS_BIGENDIAN */
|
#else /* WORDS_BIGENDIAN */
|
||||||
return (((uint64_t)(n) << 56) | \
|
return (uint64_t)(((uint64_t)(n) << 56) | \
|
||||||
(((uint64_t)(n) << 40) & 0xff000000000000ULL) | \
|
(((uint64_t)(n) << 40) & 0xff000000000000ULL) | \
|
||||||
(((uint64_t)(n) << 24) & 0xff0000000000ULL) | \
|
(((uint64_t)(n) << 24) & 0xff0000000000ULL) | \
|
||||||
(((uint64_t)(n) << 8) & 0xff00000000ULL) | \
|
(((uint64_t)(n) << 8) & 0xff00000000ULL) | \
|
||||||
@ -104,16 +104,51 @@ ndbuf_t *ndbuf_new_palloc(uint32_t alen)
|
|||||||
return b;
|
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 */
|
/* free all allocated space and buffer itself */
|
||||||
void ndbuf_free(ndbuf_t *b)
|
void ndbuf_free(ndbuf_t *b)
|
||||||
{
|
{
|
||||||
|
const struct ndbuf_memops *o = NULL;
|
||||||
if(!b) return;
|
if(!b) return;
|
||||||
|
|
||||||
if((b->flags & NDBUF_BURN) && b->raw)
|
if(b->flags & NDBUF_UCMO) o = b->mop;
|
||||||
memset(b->raw, 0, b->rlength);
|
|
||||||
|
|
||||||
if((b->flags & NDBUF_NREA) && b->freebuf) b->freebuf(b->raw);
|
if(o) {
|
||||||
else if(b->raw) free(b->raw);
|
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));
|
if(b->flags & NDBUF_BURN) memset(b, 0, sizeof(ndbuf_t));
|
||||||
free(b);
|
free(b);
|
||||||
@ -210,23 +245,37 @@ static int __rdb_grow(ndbuf_t *b, uint32_t len)
|
|||||||
{
|
{
|
||||||
uint32_t rlen;
|
uint32_t rlen;
|
||||||
char *ne = NULL;
|
char *ne = NULL;
|
||||||
|
const struct ndbuf_memops *o = NULL;
|
||||||
|
size_t bs = b->blk_size;
|
||||||
|
|
||||||
if(!len) return -1;
|
if(!len) return -1;
|
||||||
if(b->rlength + len > NDBUF_MAXLENGTH) return -1;
|
if(b->rlength + len > NDBUF_MAXLENGTH) return -1;
|
||||||
|
|
||||||
rlen = len +
|
if(b->flags & NDBUF_UCMO) o = b->mop;
|
||||||
(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;
|
if(b->rlength + rlen > NDBUF_MAXLENGTH) rlen = len;
|
||||||
|
|
||||||
rlen += b->rlength;
|
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);
|
memcpy(ne, b->raw, b->ulength);
|
||||||
|
|
||||||
if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength);
|
if(o) {
|
||||||
free(b->raw);
|
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->raw = ne;
|
||||||
b->rlength = rlen;
|
b->rlength = rlen;
|
||||||
|
|
||||||
@ -287,12 +336,25 @@ uint32_t ndbuf_write_u64(ndbuf_t *b, uint64_t uu)
|
|||||||
return sizeof(uint64_t);
|
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 */
|
/* write raw data with the given length */
|
||||||
uint32_t ndbuf_write_raw(ndbuf_t *b, void *wi, uint32_t len)
|
uint32_t ndbuf_write_raw(ndbuf_t *b, void *wi, uint32_t len)
|
||||||
{
|
{
|
||||||
if(!b || !b->raw) return 0;
|
if(!b || !b->raw) return 0;
|
||||||
if(!wi || !len) return 0;
|
if(!wi || !len) return 0;
|
||||||
|
if(__ndbuf_is_ro(b)) return 0; /* read only buffer */
|
||||||
|
|
||||||
if(b->ulength + len >= b->rlength) {
|
if(b->ulength + len >= b->rlength) {
|
||||||
|
if(__ndbuf_is_nrea(b)) return 0; /* non reallocatable buffer */
|
||||||
if(__rdb_grow(b, len)) return 0;
|
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)
|
uint32_t ndbuf_write_raw_head(ndbuf_t *b, void *wi, uint32_t len)
|
||||||
{
|
{
|
||||||
char *ne;
|
char *ne;
|
||||||
|
const struct ndbuf_memops *o = NULL;
|
||||||
uint32_t rlen;
|
uint32_t rlen;
|
||||||
|
size_t bs = b->blk_size;
|
||||||
|
|
||||||
if(!b || !b->raw) return 0;
|
if(!b || !b->raw) return 0;
|
||||||
if(!wi || !len) return 0;
|
if(!wi || !len) return 0;
|
||||||
|
if(__ndbuf_is_ro(b)) return 0; /* read only buffer */
|
||||||
|
|
||||||
if(b->ulength + len > b->rlength) {
|
if(b->ulength + len > b->rlength) {
|
||||||
|
if(__ndbuf_is_nrea(b)) return 0; /* non reallocatable buffer */
|
||||||
/* allocate a new one and copy it right */
|
/* allocate a new one and copy it right */
|
||||||
if(b->rlength + len > NDBUF_MAXLENGTH) return -1;
|
if(b->rlength + len > NDBUF_MAXLENGTH) return -1;
|
||||||
|
|
||||||
rlen = len +
|
rlen = len + (len%bs != 0 ? (bs - len%bs) : 0);
|
||||||
(len%DEFAULT_PREALLOC_SIZE != 0 ? (DEFAULT_PREALLOC_SIZE - len%DEFAULT_PREALLOC_SIZE) : 0);
|
|
||||||
if(b->rlength + rlen > NDBUF_MAXLENGTH) rlen = len;
|
if(b->rlength + rlen > NDBUF_MAXLENGTH) rlen = len;
|
||||||
|
|
||||||
rlen += b->rlength;
|
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);
|
memcpy((void *)ne + len, b->raw, b->ulength);
|
||||||
|
|
||||||
if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength);
|
if(o) {
|
||||||
free(b->raw);
|
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->raw = ne;
|
||||||
b->rlength = rlen;
|
b->rlength = rlen;
|
||||||
} else {
|
} else {
|
||||||
@ -339,8 +420,14 @@ uint32_t ndbuf_write_raw_head(ndbuf_t *b, void *wi, uint32_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* parse */
|
/* 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)
|
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;
|
va_list ap_copy;
|
||||||
union {
|
union {
|
||||||
uint8_t *_u8;
|
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;
|
ndbuf_t **_rdb;
|
||||||
} d;
|
} d;
|
||||||
const char *t, *last;
|
const char *t, *last;
|
||||||
uint32_t len, clen;
|
|
||||||
int r, count;
|
int r, count;
|
||||||
|
|
||||||
va_copy(ap_copy, ap);
|
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;
|
r = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* FIXME: Document the following line in manpages %limits% */
|
||||||
if(clen > NDBUF_MAXLENGTH) goto __errrbread;
|
if(clen > NDBUF_MAXLENGTH) goto __errrbread;
|
||||||
if((*d._cstr = malloc(clen + sizeof(char))) == NULL) {
|
|
||||||
r = -ENOMEM;
|
if(__is_moless(fo)) {
|
||||||
break;
|
*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;
|
r = 0;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
@ -414,14 +508,20 @@ int ndbuf_escan_va(ndbuf_t *b, const char *fmt, int argc, va_list ap)
|
|||||||
*d._dp = NULL;
|
*d._dp = NULL;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if((*d._dp = malloc(clen)) == NULL) {
|
if(__is_moless(fo)) {
|
||||||
r = -ENOMEM;
|
*d._dp = b->raw + b->curr;
|
||||||
break;
|
} else {
|
||||||
}
|
if(__is_usermo(fo)) *d._dp = b->mop->alloc(clen);
|
||||||
len = ndbuf_read_raw(b, *d._dp, clen);
|
else *d._dp = malloc(clen);
|
||||||
if(len != clen) {
|
if(*d._dp == NULL) {
|
||||||
free(*d._dp);
|
r = -ENOMEM;
|
||||||
goto __errrbread;
|
break;
|
||||||
|
}
|
||||||
|
len = ndbuf_read_raw(b, *d._dp, clen);
|
||||||
|
if(len != clen) {
|
||||||
|
free(*d._dp);
|
||||||
|
goto __errrbread;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
d._dp = NULL;
|
d._dp = NULL;
|
||||||
r = 0;
|
r = 0;
|
||||||
@ -435,19 +535,25 @@ int ndbuf_escan_va(ndbuf_t *b, const char *fmt, int argc, va_list ap)
|
|||||||
r = -1;
|
r = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if((*d._dp = malloc(clen)) == NULL) {
|
if(__is_moless(fo)) {
|
||||||
r = -ENOMEM;
|
*d._dp = b->raw + b->curr;
|
||||||
break;
|
} else {
|
||||||
}
|
if(__is_usermo(fo)) *d._dp = b->mop->alloc(clen);
|
||||||
len = ndbuf_read_raw(b, *d._dp, clen);
|
else *d._dp = malloc(clen);
|
||||||
if(len != clen) {
|
if(*d._dp == NULL) {
|
||||||
free(*d._dp);
|
r = -ENOMEM;
|
||||||
goto __errrbread;
|
break;
|
||||||
|
}
|
||||||
|
len = ndbuf_read_raw(b, *d._dp, clen);
|
||||||
|
if(len != clen) {
|
||||||
|
free(*d._dp);
|
||||||
|
goto __errrbread;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
d._dp = NULL;
|
d._dp = NULL;
|
||||||
r = 0;
|
r = 0;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R': /* FIXME: what about moless and user defined ops ? */
|
||||||
d._rdb = va_arg(ap, ndbuf_t **);
|
d._rdb = va_arg(ap, ndbuf_t **);
|
||||||
*d._rdb = NULL;
|
*d._rdb = NULL;
|
||||||
|
|
||||||
@ -498,9 +604,14 @@ int ndbuf_escan_va(ndbuf_t *b, const char *fmt, int argc, va_list ap)
|
|||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
d._cstr = va_arg(ap_copy, char **);
|
d._cstr = va_arg(ap_copy, char **);
|
||||||
if(*d._cstr) {
|
if(*d._cstr && !__is_moless(fo)) {
|
||||||
memset(*d._cstr, 0, strlen(*d._cstr));
|
if(__is_usermo(fo)) {
|
||||||
free(*d._cstr);
|
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;
|
break;
|
||||||
case 'R':
|
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);
|
(void)va_arg(ap_copy, size_t);
|
||||||
case 'P':
|
case 'P':
|
||||||
d._dp = va_arg(ap_copy, void **);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
(void)va_arg(ap_copy, void *);
|
(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;
|
uint32_t len = 0, clen;
|
||||||
int r, count;
|
int r, count;
|
||||||
|
|
||||||
|
if(__ndbuf_is_ro(b)) return 0; /* read only buffer */
|
||||||
|
|
||||||
for(t = fmt, count = 0; *t != '\0'; t++, count++) {
|
for(t = fmt, count = 0; *t != '\0'; t++, count++) {
|
||||||
if(count > argc && argc != -1) return 0;
|
if(count > argc && argc != -1) return 0;
|
||||||
switch(*t) {
|
switch(*t) {
|
||||||
@ -705,6 +821,8 @@ void ndbuf_setflags(ndbuf_t *b, int af)
|
|||||||
{
|
{
|
||||||
if(!b) return;
|
if(!b) return;
|
||||||
|
|
||||||
|
if(((af & NDBUF_BURN) && (b->flags & NDBUF_UCMO)) && !b->mop->zero) return;
|
||||||
|
|
||||||
b->flags |= af;
|
b->flags |= af;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -715,6 +833,8 @@ void ndbuf_exflags(ndbuf_t *b, int nf)
|
|||||||
{
|
{
|
||||||
if(!b) return;
|
if(!b) return;
|
||||||
|
|
||||||
|
if(b->flags & NDBUF_UCMO) nf |= NDBUF_UCMO;
|
||||||
|
|
||||||
b->flags = nf;
|
b->flags = nf;
|
||||||
|
|
||||||
return;
|
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
|
/* 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),
|
* will return 0 on success (or in case if it doesn't required),
|
||||||
* ENOMEM or other error if fails
|
* ENOMEM or other error if fails
|
||||||
|
* TODO: ? make this buffer non reallocable ?
|
||||||
*/
|
*/
|
||||||
int ndbuf_memopt(ndbuf_t *b)
|
int ndbuf_memopt(ndbuf_t *b)
|
||||||
{
|
{
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
size_t bs = b->blk_size;
|
||||||
char *ne;
|
char *ne;
|
||||||
|
const struct ndbuf_memops *o = NULL;
|
||||||
|
|
||||||
if(!b || !b->raw) return EINVAL;
|
if(!b || !b->raw) return EINVAL;
|
||||||
|
|
||||||
if((b->rlength - b->ulength) > DEFAULT_PREALLOC_SIZE) {
|
if((b->rlength - b->ulength) > bs) {
|
||||||
len = b->ulength +
|
len = b->ulength +
|
||||||
(b->ulength%DEFAULT_PREALLOC_SIZE != 0 ?
|
(b->ulength%bs != 0 ? (bs - b->ulength%bs) : 0);
|
||||||
(DEFAULT_PREALLOC_SIZE - b->ulength%DEFAULT_PREALLOC_SIZE) : 0);
|
|
||||||
if(!(ne = malloc(len))) return ENOMEM;
|
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);
|
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->raw = ne;
|
||||||
b->rlength = len;
|
b->rlength = len;
|
||||||
}
|
}
|
||||||
@ -774,4 +913,21 @@ int ndbuf_memopt(ndbuf_t *b)
|
|||||||
return 0;
|
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
|
#undef DEFAULT_PREALLOC_SIZE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user