/* ** buffer.c ** ** See function descriptions in buffer.h ** Written by Peter Sutton, May 2007. */ #include "buffer.h" #include #include #include struct Buffer { char* data; /* Bytes being stored. Memory is of size 'capacity' */ int curPos; /* Current reading position in buffer */ int inUse; /* Number of bytes stored in buffer (writing pos) */ int capacity; /* Size of the data array */ }; /* Function used internally to grow the buffer */ static void buf_grow(Buffer* buf, int requiredEmptySpace) { if(buf->inUse + requiredEmptySpace >= buf->capacity) { /* Buffer data space is not large enough to hold this - extend it */ buf->capacity = buf->inUse + requiredEmptySpace + 1; buf->data = realloc(buf->data, buf->capacity); } } Buffer* buf_create(int initialSize) { Buffer* buf; buf = (Buffer*)malloc(sizeof(Buffer)); buf->data = malloc(initialSize); buf->curPos = 0; buf->inUse = 0; buf->capacity = initialSize; return buf; } void buf_append(Buffer* buf, char* data, int numBytes) { buf_grow(buf, numBytes); memcpy(buf->data + buf->inUse, data, numBytes); buf->inUse += numBytes; } int buf_append_from_fd(Buffer* buf, int fd, int maxBytes) { int numBytesRead; buf_grow(buf, maxBytes); numBytesRead = read(fd, buf->data + buf->inUse, maxBytes); if(numBytesRead > 0) { buf->inUse += numBytesRead; } return numBytesRead; } char* buf_get_data(Buffer* buf) { /* Null terminate the buffer */ buf->data[buf->inUse] = '\0'; return buf->data + buf->curPos; } void buf_delete(Buffer* buf) { if(buf) { free(buf->data); free(buf); } } int buf_num_bytes_stored(Buffer* buf) { return (buf->inUse - buf->curPos); } void buf_consume(Buffer* buf, int bytesConsumed) { buf->curPos += bytesConsumed; if(buf->curPos == buf->inUse) { /* Complete buffer has been read - reset buffer */ buf->curPos = 0; buf->inUse = 0; } } char* buf_extract_line(Buffer* buf) { int pos; char* returnValue; pos = buf->curPos; while(pos < buf->inUse && buf->data[pos] != '\n') { pos++; } if(buf->data[pos] != '\n') { /* Reached end of buffer without finding newline */ return NULL; } /* Have found newline - replace it by a null (along with any preceding \r) */ buf->data[pos] = '\0'; if(pos > buf->curPos && buf->data[pos-1] =='\r') { buf->data[pos-1] = '\0'; } /* Consume the data */ returnValue = buf->data + buf->curPos; buf->curPos = pos + 1; return returnValue; }