3 changed files with 301 additions and 1 deletions
-
3lib/Makefile.am
-
231lib/sbuffer.c
-
68lib/sbuffer.h
@ -1,6 +1,7 @@ |
|||
noinst_LIBRARIES = libfmail.a |
|||
|
|||
libfmail_a_SOURCES = err.compat.h compat.h xmem.c xmem.h |
|||
libfmail_a_SOURCES = err.compat.h compat.h xmem.c xmem.h \
|
|||
sbuffer.c sbuffer.h |
|||
|
|||
libfmail_a_LIBADD = $(LIBOBJS) |
|||
|
|||
|
@ -0,0 +1,231 @@ |
|||
/* |
|||
* sbuffer - Incenp.org Notch Library: string buffer module |
|||
* Copyright (C) 2011 Damien Goutte-Gattat |
|||
* |
|||
* 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/>. |
|||
*/ |
|||
|
|||
#ifdef HAVE_CONFIG_H |
|||
#include <config.h> |
|||
#endif |
|||
|
|||
#include <sbuffer.h> |
|||
#include <stdio.h> |
|||
#include <errno.h> |
|||
#include <string.h> |
|||
|
|||
#ifdef EXIT_ON_ENOMEM |
|||
#include <xmem.h> |
|||
#endif |
|||
|
|||
struct string_buffer_t |
|||
{ |
|||
char *buffer; |
|||
size_t len; |
|||
size_t size; |
|||
size_t block; |
|||
}; |
|||
|
|||
#define AVAILABLE_SIZE(s) ((s)->size - (s)->len) |
|||
#define CURSOR(s) ((s)->buffer + (s)->len) |
|||
|
|||
#ifdef EXIT_ON_NOMEM |
|||
|
|||
#define GROW(s,l) \ |
|||
do { \ |
|||
(s)->size = ((((s)->len + (l)) / (s)->block) + 1) * (s)->block; \ |
|||
(s)->buffer = xrealloc((s)->buffer, (s)->len); \ |
|||
} while ( 0 ) |
|||
|
|||
#else |
|||
|
|||
#define GROW(s,l) \ |
|||
do { \ |
|||
size_t ns = ((((s)->len + (l)) / (s)->block) + 1) * (s)->block; \ |
|||
char *np = realloc((s)->buffer, ns); \ |
|||
if ( ! np ) \ |
|||
return -1; \ |
|||
(s)->buffer = np; \ |
|||
(s)->size = ns; \ |
|||
} while ( 0 ) |
|||
|
|||
#endif |
|||
|
|||
string_buffer_t * |
|||
sb_new(size_t block_size) |
|||
{ |
|||
string_buffer_t *s; |
|||
|
|||
if ( ! block_size ) |
|||
block_size = 128; |
|||
|
|||
#ifdef EXIT_ON_ENOMEM |
|||
s = xmalloc(sizeof(*s)); |
|||
s->block = s->size = block_size; |
|||
s->buffer = xmalloc(block_size); |
|||
sb_empty(s); |
|||
#else |
|||
if ( (s = malloc(sizeof(*s))) ) { |
|||
s->block = s->size = block_size; |
|||
if ( (s->buffer = malloc(block_size)) ) |
|||
sb_empty(s); |
|||
else { |
|||
free(s); |
|||
s = NULL; |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
return s; |
|||
} |
|||
|
|||
void |
|||
sb_free(string_buffer_t *s) |
|||
{ |
|||
if ( s ) { |
|||
free(s->buffer); |
|||
free(s); |
|||
} |
|||
} |
|||
|
|||
const char * |
|||
sb_get(string_buffer_t *s) |
|||
{ |
|||
return s ? s->buffer : NULL; |
|||
} |
|||
|
|||
char * |
|||
sb_get_copy(string_buffer_t *s) |
|||
{ |
|||
char *str = NULL; |
|||
|
|||
if ( s ) { |
|||
#ifdef EXIT_ON_ENOMEM |
|||
str = xmalloc(s->len + 1); |
|||
#else |
|||
if ( ! (str = malloc(s->len + 1)) ) |
|||
return NULL; |
|||
#endif |
|||
strncpy(str, s->buffer, s->len); |
|||
} |
|||
|
|||
return str; |
|||
} |
|||
|
|||
size_t |
|||
sb_len(string_buffer_t *s) |
|||
{ |
|||
return s ? s->len : 0; |
|||
} |
|||
|
|||
int |
|||
sb_empty(string_buffer_t *s) |
|||
{ |
|||
if ( ! s ) { |
|||
errno = EINVAL; |
|||
return -1; |
|||
} |
|||
|
|||
s->buffer[0] = '\0'; |
|||
s->len = 0; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
sb_addc(string_buffer_t *s, char c) |
|||
{ |
|||
if ( ! s ) { |
|||
errno = EINVAL; |
|||
return -1; |
|||
} |
|||
|
|||
if ( AVAILABLE_SIZE(s) < 1 ) |
|||
GROW(s, 1); |
|||
|
|||
*(s->buffer + s->len++) = c; |
|||
*(s->buffer + s->len) = '\0'; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
sb_add(string_buffer_t *s, const char *buffer) |
|||
{ |
|||
if ( ! buffer ) { |
|||
errno = EINVAL; |
|||
return -1; |
|||
} |
|||
|
|||
return sb_addn(s, buffer, strlen(buffer)); |
|||
} |
|||
|
|||
int |
|||
sb_addn(string_buffer_t *s, const char *buffer, size_t len) |
|||
{ |
|||
if ( ! s || ! buffer ) { |
|||
errno = EINVAL; |
|||
return -1; |
|||
} |
|||
|
|||
if ( AVAILABLE_SIZE(s) < len ) |
|||
GROW(s, len); |
|||
|
|||
strncat(CURSOR(s), buffer, len); |
|||
s->len += len; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
sb_vaddf(string_buffer_t *s, const char *fmt, va_list ap) |
|||
{ |
|||
int written; |
|||
|
|||
if ( ! s || ! fmt ) { |
|||
errno = EINVAL; |
|||
return -1; |
|||
} |
|||
|
|||
written = vsnprintf(CURSOR(s), AVAILABLE_SIZE(s), fmt, ap); |
|||
if ( written >= AVAILABLE_SIZE(s) ) { |
|||
va_list aq; |
|||
|
|||
GROW(s, written); |
|||
va_copy(aq, ap); |
|||
vsprintf(CURSOR(s), fmt, aq); |
|||
va_end(aq); |
|||
} |
|||
s->len += written; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
sb_addf(string_buffer_t *s, const char *fmt, ...) |
|||
{ |
|||
int ret; |
|||
va_list ap; |
|||
|
|||
if ( ! s || ! fmt ) { |
|||
errno = EINVAL; |
|||
return -1; |
|||
} |
|||
|
|||
va_start(ap, fmt); |
|||
ret = sb_vaddf(s, fmt, ap); |
|||
va_end(ap); |
|||
|
|||
return ret; |
|||
} |
@ -0,0 +1,68 @@ |
|||
/* |
|||
* sbuffer - Incenp.org Notch Library: string buffer module |
|||
* Copyright (C) 2011 Damien Goutte-Gattat |
|||
* |
|||
* 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/>. |
|||
*/ |
|||
|
|||
#ifndef ICP20110203_SBUFFER_H |
|||
#define ICP20110203_SBUFFER_H |
|||
|
|||
#include <stdlib.h> |
|||
#include <stdarg.h> |
|||
|
|||
#ifdef __cpluscplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
typedef struct string_buffer_t string_buffer_t; |
|||
|
|||
string_buffer_t * |
|||
sb_new(size_t); |
|||
|
|||
void |
|||
sb_free(string_buffer_t *); |
|||
|
|||
const char * |
|||
sb_get(string_buffer_t *); |
|||
|
|||
char * |
|||
sb_get_copy(string_buffer_t *); |
|||
|
|||
size_t |
|||
sb_len(string_buffer_t *); |
|||
|
|||
int |
|||
sb_empty(string_buffer_t *); |
|||
|
|||
int |
|||
sb_addc(string_buffer_t *, char); |
|||
|
|||
int |
|||
sb_add(string_buffer_t *, const char *); |
|||
|
|||
int |
|||
sb_addn(string_buffer_t *, const char *, size_t); |
|||
|
|||
int |
|||
sb_vaddf(string_buffer_t *, const char *, va_list); |
|||
|
|||
int |
|||
sb_addf(string_buffer_t *, const char *, ...); |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif /* !ICP20110203_SBUFFER_H */ |
Write
Preview
Loading…
Cancel
Save
Reference in new issue