1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-22 22:04:08 +03:00

s3-lib: add cbuf, a talloced character buffer

Signed-off-by: Michael Adam <obnox@samba.org>
This commit is contained in:
Gregor Beck 2010-09-20 14:33:21 +02:00 committed by Michael Adam
parent 9c2e89da10
commit e5bbc2be05
3 changed files with 524 additions and 2 deletions

View File

@ -1150,8 +1150,8 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_help.o \
$(LIBCLI_NETLOGON_OBJ) \
$(RPC_CLIENT_SCHANNEL_OBJ) \
rpc_client/init_netlogon.o \
rpc_client/init_samr.o
rpc_client/init_samr.o \
lib/cbuf.o
# these are not processed by make proto
NET_OBJ2 = utils/net_registry_util.o utils/net_help_common.o

287
source3/lib/cbuf.c Normal file
View File

@ -0,0 +1,287 @@
/*
* Samba Unix/Linux SMB client library
*
* Copyright (C) Gregor Beck 2010
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file cbuf.c
* @author Gregor Beck <gb@sernet.de>
* @date Aug 2010
*
* @brief A talloced character buffer.
*
*/
#include <assert.h>
#include "includes.h"
#include "cbuf.h"
struct cbuf {
char* buf;
size_t pos;
size_t size;
};
cbuf* cbuf_clear(cbuf* b)
{
cbuf_setpos(b, 0);
return b;
}
cbuf* cbuf_new(const void* ctx)
{
cbuf* s = talloc(ctx, cbuf);
if (s == NULL)
return NULL;
s->size = 32;
s->buf = talloc_size(s, s->size);
if (s->size && (s->buf == NULL)) {
talloc_free(s);
return NULL;
}
return cbuf_clear(s);
}
cbuf* cbuf_copy(const cbuf* b)
{
cbuf* s = talloc(talloc_parent(b), cbuf);
if (s == NULL) {
return NULL;
}
s->buf = talloc_memdup(s, b->buf, b->size); /* only up to pos? */
/* XXX shallow did not work, because realloc */
/* fails with multiple references */
/* s->buf = talloc_reference(s, b->buf); */
if (s->buf == NULL) {
cbuf_delete(s);
return NULL;
}
s->size = b->size;
s->pos = b->pos;
return s;
}
void cbuf_delete(cbuf* b)
{
talloc_free(b);
}
#define SWAP(A,B,T) do { \
T tmp = A; A = B; B = tmp; \
} while(0)
void cbuf_swap(cbuf* b1, cbuf* b2)
{
if (b1 == b2) {
return;
}
talloc_reparent(b1, b2, b1->buf);
talloc_reparent(b2, b1, b2->buf);
SWAP(b1->buf, b2->buf, char*);
SWAP(b1->pos, b2->pos, size_t);
SWAP(b1->size, b2->size, size_t);
}
cbuf* cbuf_takeover(cbuf* b1, cbuf* b2)
{
talloc_reparent(b2, b1, b2->buf);
b1->buf = b2->buf;
b1->pos = b2->pos;
b1->size = b2->size;
cbuf_delete(b2);
return b1;
}
cbuf* cbuf_swapptr(cbuf* b, char** ptr, size_t len)
{
SWAP(b->buf, *ptr, char*);
talloc_steal(b, b->buf);
b->size = talloc_get_size(b->buf);
b->pos = (len == -1) ? strlen(b->buf) : len;
assert(b->pos <= b->size);
return b;
}
cbuf* cbuf_resize(cbuf* b, size_t size)
{
char* save_buf = b->buf;
b->buf = talloc_realloc(b, b->buf, char, size);
if (b->buf == NULL) {
talloc_free(save_buf);
b->size = 0;
} else {
b->size = size;
}
b->pos = MIN(b->pos, b->size);
return b->buf ? b : NULL;
}
char* cbuf_reserve(cbuf* b, size_t len)
{
if(b->size < b->pos + len)
cbuf_resize(b, MAX(2*b->size, b->pos + len));
return b->buf ? b->buf + b->pos : NULL;
}
int cbuf_puts(cbuf* b, const char* str, size_t len)
{
char* dst;
if (b == NULL)
return 0;
if (len == -1) {
len=strlen(str);
}
dst = cbuf_reserve(b, len+1);
if (dst == NULL)
return -1;
memcpy(dst, str, len);
dst[len] = '\0'; /* just to ease debugging */
b->pos += len;
assert(b->pos < b->size);
return len;
}
int cbuf_putc(cbuf* b, char c) {
char* dst;
if (b == NULL)
return 0;
dst = cbuf_reserve(b, 2);
if (dst == NULL) {
return -1;
}
dst[0] = c;
dst[1] = '\0'; /* just to ease debugging */
b->pos++;
assert(b->pos < b->size);
return 1;
}
int cbuf_putdw(cbuf* b, uint32_t u) {
char* dst;
static const size_t LEN = sizeof(uint32_t);
if (b == NULL)
return 0;
dst = cbuf_reserve(b, LEN);
if (dst == NULL) {
return -1;
}
SIVAL(dst, 0, u);
b->pos += LEN;
assert(b->pos <= b->size); /* no NULL termination*/
return LEN;
}
size_t cbuf_getpos(const cbuf* b) {
assert(b->pos <= b->size);
return b->pos;
}
void cbuf_setpos(cbuf* b, size_t pos) {
assert(pos <= b->size);
b->pos = pos;
if (pos < b->size)
b->buf[pos] = '\0'; /* just to ease debugging */
}
char* cbuf_gets(cbuf* b, size_t idx) {
assert(idx <= b->pos);
if (cbuf_reserve(b, 1) == NULL)
return NULL;
b->buf[b->pos] = '\0';
return b->buf + idx;
}
int cbuf_printf(cbuf* b, const char* fmt, ...)
{
va_list args, args2;
int len;
char* dst = b->buf + b->pos;
const int avail = b->size - b->pos;
assert(avail >= 0);
va_start(args, fmt);
va_copy(args2, args);
len = vsnprintf(dst, avail, fmt, args);
if (len >= avail) {
dst = cbuf_reserve(b, len+1);
len = (dst != NULL) ? vsnprintf(dst, len+1, fmt, args2) : -1;
}
if (len > 0) {
b->pos += len;
}
va_end(args);
va_end(args2);
assert(b->pos <= b->size);
return len;
}
int cbuf_print_quoted_string(cbuf* ost, const char* s)
{
int n = 1;
cbuf_putc(ost,'"');
while(true) {
switch (*s) {
case '\0':
cbuf_putc(ost, '"');
return n+1;
case '"':
case '\\':
cbuf_putc(ost, '\\');
n++;
/* no break */
default:
cbuf_putc(ost, *s);
n++;
}
s++;
}
}

235
source3/lib/cbuf.h Normal file
View File

@ -0,0 +1,235 @@
/*
* Samba Unix/Linux SMB client library
* Copyright (C) Gregor Beck 2010
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file cbuf.h
* @author Gregor Beck <gb@sernet.de>
* @date Aug 2010
*
* @brief A talloced character buffer.
*
* A cbuf carries a write position and keeps track of its size.
*/
#ifndef __CBUF_H
#define __CBUF_H
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
struct cbuf;
typedef struct cbuf cbuf;
/**
* Create a new character buffer.
*
* @param talloc_ctx the talloc parent
*
* @return a new cbuf object, NULL on error
*/
cbuf* cbuf_new(const void* talloc_ctx);
/**
* Create a copy of a character buffer.
*
* @param b the cbuf to copy
* @return a new cbuf object, NULL on error
*/
cbuf* cbuf_copy(const cbuf* b);
/**
* Delete a character buffer.
* This invalidates b and free's the memory allocated.
* @warning don't talloc_free b directly, however freeing
* the parent works as expected
* @param b the cbuf to delete
*/
void cbuf_delete(cbuf* b);
/**
* Reset the buffer to initial state.
* Set the write positon to the start of buffer, effectivly
* clearing its contents. Doesn't free memory.
*
* @param b the buffer to clear
*
* @return b
*/
cbuf* cbuf_clear(cbuf* b);
/**
* Swap the contents of two buffers in O(1).
*
* @param b1 a character buffer
* @param b2 another character buffer
*/
void cbuf_swap(cbuf* b1, cbuf* b2);
/**
* Swap the contents of a buffer with a talloced string.
*
* @param b a character buffer
* @param ptr a pointer to a talloced string
* @param len size of string, -1 means strlen(*ptr)
*
* @return b
*/
cbuf* cbuf_swapptr(cbuf* b, char** ptr, size_t len);
/**
* Let a character buffer takeover the contents of another.
* This is equivalent to @code
* cbuf_swap(b1, b2);
* cbuf_delete(b2);
* @endcode
* @param b1 the destination
* @param b2 the victim
*
* @return b1
*/
cbuf* cbuf_takeover(cbuf* b1, cbuf* b2);
/**
* Resize a character buffer.
* This may free allocated memory.
*
* @param b the character buffer.
* @param size the new size
*
* @return b, NULL on error
*/
cbuf* cbuf_resize(cbuf* b, size_t size);
/**
* Reserve space in a character buffer.
* Assert there are at least len bytes following the current write position.
*
* @param b a character buffer
* @param len number of bytes to reserve.
*
* @return a pointer to the current write position, NULL on error
*/
char* cbuf_reserve(cbuf* b, size_t len);
/**
* Put a character into the buffer.
*
* @param b a charcter buffer, may be NULL.
* @param c a character
* @return number of charcters written ((b==NULL) ? 0 : 1)
*
* @retval -1 on error
*/
int cbuf_putc(cbuf* b, char c);
/**
* Put a string into the buffer.
*
* @param b a character buffer, may be NULL
* @param str a string
* @param len number of bytes to write, -1 means strlen(str)
*
* @return number of characters written, -1 on error
*/
int cbuf_puts(cbuf* b, const char* str, size_t len);
/* /\** */
/* * Put a string into the buffer, changing case. */
/* * */
/* * @param b a character buffer, may be NULL */
/* * @param str a string */
/* * @param len number of bytes to write, -1 means strlen(str) */
/* * @param c a character specifying case: */
/* * @li 'U' upper case */
/* * @li 'L' lower case */
/* * @li 'T' title case */
/* * @li 'P' preserve case */
/* * @return number of characters written, -1 on error */
/* *\/ */
/* int cbuf_puts_case(cbuf* b, const char* str, size_t len, char c); */
/**
* Put a uint32 into the buffer.
* Write in little endian order.
*
* @param b a character buffer, may be NULL
* @param u an uint32
*
* @return number of characters written, -1 on error
*/
int cbuf_putdw(cbuf* b, uint32_t u);
/**
* Print formated to a character buffer.
*
* @param b a charcter buffer
* @param fmt a printf format string
*
* @return number of characters written, negative on error
*/
int cbuf_printf(cbuf* b, const char* fmt, ...);
/**
* Get the current write position.
*
* @param b a character buffer.
*
* @return index of the next charcter to write.
*/
size_t cbuf_getpos(const cbuf* b);
/**
* Set the current write position of a buffer.
* Invalidates the buffer contents from on the new position.
*
* @param b a charcter buffer
* @param pos a position obtained by cbuf_getpos
*/
void cbuf_setpos(cbuf* b, size_t pos);
/**
* Get the buffer contents
* starting at idx.
* @pre @code idx <= cbuf_getpos(b) @endcode
* @param b a character buffer
* @param idx a position obtained by cbuf_getpos
*
* @return a NUL terminated string
*/
char* cbuf_gets(cbuf* b, size_t idx);
/**
* Print quoted string to stream.
*
* @todo check for ssputc failure
* @see srprs_quoted_string
*
* @param[out] ost outstream
* @param[in] s string
*
* @return numner of bytes written, -1 on error
*/
int cbuf_print_quoted_string(cbuf* ost, const char* s);
#endif /*__CBUF_H*/