buffer.c revision 57429
1165535Sjkoshy/* 2165535Sjkoshy * 3165535Sjkoshy * buffer.c 4165535Sjkoshy * 5165535Sjkoshy * Author: Tatu Ylonen <ylo@cs.hut.fi> 6165535Sjkoshy * 7165535Sjkoshy * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 8165535Sjkoshy * All rights reserved 9165535Sjkoshy * 10165535Sjkoshy * Created: Sat Mar 18 04:15:33 1995 ylo 11165535Sjkoshy * 12165535Sjkoshy * Functions for manipulating fifo buffers (that can grow if needed). 13165535Sjkoshy * 14165535Sjkoshy */ 15165535Sjkoshy 16165535Sjkoshy#include "includes.h" 17165535SjkoshyRCSID("$Id: buffer.c,v 1.4 1999/11/24 19:53:44 markus Exp $"); 18165535Sjkoshy 19165535Sjkoshy#include "xmalloc.h" 20165535Sjkoshy#include "buffer.h" 21165535Sjkoshy#include "ssh.h" 22165535Sjkoshy 23165535Sjkoshy/* Initializes the buffer structure. */ 24165535Sjkoshy 25165535Sjkoshyvoid 26165535Sjkoshybuffer_init(Buffer *buffer) 27165535Sjkoshy{ 28165535Sjkoshy buffer->alloc = 4096; 29165535Sjkoshy buffer->buf = xmalloc(buffer->alloc); 30165535Sjkoshy buffer->offset = 0; 31165535Sjkoshy buffer->end = 0; 32165535Sjkoshy} 33165535Sjkoshy 34165535Sjkoshy/* Frees any memory used for the buffer. */ 35165535Sjkoshy 36165535Sjkoshyvoid 37165535Sjkoshybuffer_free(Buffer *buffer) 38165535Sjkoshy{ 39165535Sjkoshy memset(buffer->buf, 0, buffer->alloc); 40165535Sjkoshy xfree(buffer->buf); 41165535Sjkoshy} 42165535Sjkoshy 43165535Sjkoshy/* 44165535Sjkoshy * Clears any data from the buffer, making it empty. This does not actually 45165535Sjkoshy * zero the memory. 46165535Sjkoshy */ 47165535Sjkoshy 48165535Sjkoshyvoid 49165535Sjkoshybuffer_clear(Buffer *buffer) 50165535Sjkoshy{ 51165535Sjkoshy buffer->offset = 0; 52165535Sjkoshy buffer->end = 0; 53165535Sjkoshy} 54165535Sjkoshy 55165535Sjkoshy/* Appends data to the buffer, expanding it if necessary. */ 56165535Sjkoshy 57165535Sjkoshyvoid 58165535Sjkoshybuffer_append(Buffer *buffer, const char *data, unsigned int len) 59165535Sjkoshy{ 60165535Sjkoshy char *cp; 61165535Sjkoshy buffer_append_space(buffer, &cp, len); 62165535Sjkoshy memcpy(cp, data, len); 63165535Sjkoshy} 64165535Sjkoshy 65165535Sjkoshy/* 66165535Sjkoshy * Appends space to the buffer, expanding the buffer if necessary. This does 67165535Sjkoshy * not actually copy the data into the buffer, but instead returns a pointer 68165535Sjkoshy * to the allocated region. 69165535Sjkoshy */ 70165535Sjkoshy 71165535Sjkoshyvoid 72165535Sjkoshybuffer_append_space(Buffer *buffer, char **datap, unsigned int len) 73165535Sjkoshy{ 74165535Sjkoshy /* If the buffer is empty, start using it from the beginning. */ 75165535Sjkoshy if (buffer->offset == buffer->end) { 76165535Sjkoshy buffer->offset = 0; 77165535Sjkoshy buffer->end = 0; 78165535Sjkoshy } 79165535Sjkoshyrestart: 80165535Sjkoshy /* If there is enough space to store all data, store it now. */ 81165535Sjkoshy if (buffer->end + len < buffer->alloc) { 82165535Sjkoshy *datap = buffer->buf + buffer->end; 83165535Sjkoshy buffer->end += len; 84165535Sjkoshy return; 85165535Sjkoshy } 86165535Sjkoshy /* 87165535Sjkoshy * If the buffer is quite empty, but all data is at the end, move the 88165535Sjkoshy * data to the beginning and retry. 89165535Sjkoshy */ 90165535Sjkoshy if (buffer->offset > buffer->alloc / 2) { 91165535Sjkoshy memmove(buffer->buf, buffer->buf + buffer->offset, 92165535Sjkoshy buffer->end - buffer->offset); 93165535Sjkoshy buffer->end -= buffer->offset; 94165535Sjkoshy buffer->offset = 0; 95165535Sjkoshy goto restart; 96165535Sjkoshy } 97165535Sjkoshy /* Increase the size of the buffer and retry. */ 98165535Sjkoshy buffer->alloc += len + 32768; 99165535Sjkoshy buffer->buf = xrealloc(buffer->buf, buffer->alloc); 100165535Sjkoshy goto restart; 101165535Sjkoshy} 102165535Sjkoshy 103165535Sjkoshy/* Returns the number of bytes of data in the buffer. */ 104165535Sjkoshy 105165535Sjkoshyunsigned int 106165535Sjkoshybuffer_len(Buffer *buffer) 107165535Sjkoshy{ 108165535Sjkoshy return buffer->end - buffer->offset; 109165535Sjkoshy} 110165535Sjkoshy 111165535Sjkoshy/* Gets data from the beginning of the buffer. */ 112165535Sjkoshy 113165535Sjkoshyvoid 114165535Sjkoshybuffer_get(Buffer *buffer, char *buf, unsigned int len) 115165535Sjkoshy{ 116165535Sjkoshy if (len > buffer->end - buffer->offset) 117165535Sjkoshy fatal("buffer_get trying to get more bytes than in buffer"); 118165535Sjkoshy memcpy(buf, buffer->buf + buffer->offset, len); 119165535Sjkoshy buffer->offset += len; 120165535Sjkoshy} 121165535Sjkoshy 122165535Sjkoshy/* Consumes the given number of bytes from the beginning of the buffer. */ 123165535Sjkoshy 124165535Sjkoshyvoid 125165535Sjkoshybuffer_consume(Buffer *buffer, unsigned int bytes) 126165535Sjkoshy{ 127165535Sjkoshy if (bytes > buffer->end - buffer->offset) 128165535Sjkoshy fatal("buffer_get trying to get more bytes than in buffer"); 129165535Sjkoshy buffer->offset += bytes; 130165535Sjkoshy} 131165535Sjkoshy 132165535Sjkoshy/* Consumes the given number of bytes from the end of the buffer. */ 133165535Sjkoshy 134165535Sjkoshyvoid 135165535Sjkoshybuffer_consume_end(Buffer *buffer, unsigned int bytes) 136165535Sjkoshy{ 137 if (bytes > buffer->end - buffer->offset) 138 fatal("buffer_get trying to get more bytes than in buffer"); 139 buffer->end -= bytes; 140} 141 142/* Returns a pointer to the first used byte in the buffer. */ 143 144char * 145buffer_ptr(Buffer *buffer) 146{ 147 return buffer->buf + buffer->offset; 148} 149 150/* Dumps the contents of the buffer to stderr. */ 151 152void 153buffer_dump(Buffer *buffer) 154{ 155 int i; 156 unsigned char *ucp = (unsigned char *) buffer->buf; 157 158 for (i = buffer->offset; i < buffer->end; i++) 159 fprintf(stderr, " %02x", ucp[i]); 160 fprintf(stderr, "\n"); 161} 162