Mercurial > code
view buffer.c @ 99:d534fdcbb319
Remove #ifdef __cplusplus
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 13 Jan 2012 22:48:08 +0100 |
parents | b1a084c030c8 |
children | 37eef6776cc6 |
line wrap: on
line source
/* * buffer.c -- safe unlimited size string * * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include "buffer.h" static int buffer_grow(struct buffer *, size_t); /* * Create a new buffer with initial size `length'. If type is set to BUFFER_AUTO * the buffer will grow automatically increasing the size by `length' bytes. On * BUFFER_FIXED type the buffer won't grow. */ struct buffer * buffer_new(enum buffer_type type, int length) { struct buffer *buf; if ((buf = malloc(sizeof (struct buffer))) == NULL) return NULL; memset(buf, 0, sizeof (struct buffer)); buf->bsize = (length == 0) ? BUFFER_DEFAULT_BSIZE : length; buf->size = buf->bsize + 1; buf->type = type; if ((buf->text = calloc(buf->size, 1)) == NULL) { free(buf); return NULL; } return buf; } /* * Concatenate the string into the buffer. */ int buffer_strcat(struct buffer *buf, const char *str) { size_t length; length = strlen(str); if (buffer_grow(buf, length) < 0) return -1; if (buf->type == BUFFER_AUTO) length = buf->size - buf->length - 1; strncpy(buf->text + buf->length, str, length); buf->length = strlen(buf->text); return 0; } /* * Append the character `c' to the end of buffer. */ int buffer_putc(struct buffer *buf, char c) { if (buffer_grow(buf, 1) < 0) return -1; if (buf->type != BUFFER_AUTO && buf->size - buf->length - 1 <= 2) return -1; buf->text[buf->length++] = c; buf->text[buf->length] = '\0'; return 0; } /* * Concatenate the byte pointer into the buffer. */ int buffer_bcat(struct buffer *buf, const void *data, size_t size) { if (buffer_grow(buf, size) < 0) return -1; /* Do not truncate void pointer */ if (buf->type == BUFFER_AUTO && size > (buf->size - buf->length - 1)) return -1; memcpy(buf->text + buf->length, data, size); buf->length += size; return 0; } /* * Print into the buffer using va_list from stdarg.h */ int buffer_vprintf(struct buffer *buf, const char *fmt, va_list ap) { va_list ap_save; int nb, result = 1; /* * vsnprintf on windows returns -1 instead of the number of bytes that * should be printed... */ if (buf->type == BUFFER_AUTO) { do { va_copy(ap_save, ap); nb = vsnprintf(buf->text + buf->length, buf->size - buf->length - 1, fmt, ap_save); if (nb == -1 || (size_t) nb >= buf->size - buf->length - 1) { if (buffer_grow(buf, buf->size + buf->bsize)) result = -1; } else result = 0; } while (result == 1); va_end(ap_save); } else { result = 0; vsnprintf(buf->text + buf->length, buf->size - buf->length - 1, fmt, ap); } buf->length = strlen(buf->text); return result; } /* * Use printf(3) functions like to write into the buffer. */ int buffer_printf(struct buffer *buf, const char *fmt, ...) { va_list ap; int status; va_start(ap, fmt); status = buffer_vprintf(buf, fmt, ap); va_end(ap); return status; } /* * Reduce the data buffer to the exact size. Returns -1 on failure. */ int buffer_shrink(struct buffer *buf) { if ((buf->text = realloc(buf->text, buf->length + 1)) == NULL) { buf->size = 0; return -1; } buf->size = buf->length + 1; return 0; } /* * Returns the buffer data and then free the buffer object. */ char * buffer_end(struct buffer *buf) { char *text; buffer_shrink(buf); text = buf->text; free(buf); return text; } /* * Reset the struct buffer. */ void buffer_clear(struct buffer *buf) { memset(buf->text, 0, buf->size); buf->length = 0; } void buffer_free(struct buffer *buf) { buffer_clear(buf); if (buf->text) free(buf->text); free(buf); } /* * Functions that tries to extend the buffer to the `needed' size if the buffer * allows it. If the buffer is fixed size and there is not enough space the * functions returns -1 otherwise 0 is returned. */ static int buffer_grow(struct buffer *buf, size_t needed) { size_t newlen; if ((buf->size - buf->length) > needed) return 0; if (buf->type == BUFFER_AUTO) { newlen = buf->size; while (newlen - buf->length - 1 <= needed) newlen += buf->bsize; if ((buf->text = realloc(buf->text, newlen)) == NULL) { buf->size = 0; return -1; } buf->size = newlen; memset(buf->text + buf->length, 0, buf->size - buf->length); } return 0; }