buffer.c revision 60573
157429Smarkm/* 260573Skris * 357429Smarkm * buffer.c 460573Skris * 557429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 660573Skris * 757429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 857429Smarkm * All rights reserved 960573Skris * 1057429Smarkm * Created: Sat Mar 18 04:15:33 1995 ylo 1160573Skris * 1257429Smarkm * Functions for manipulating fifo buffers (that can grow if needed). 1360573Skris * 1457429Smarkm */ 1557429Smarkm 1657429Smarkm#include "includes.h" 1760573SkrisRCSID("$Id: buffer.c,v 1.6 2000/04/14 10:30:30 markus Exp $"); 1857429Smarkm 1957429Smarkm#include "xmalloc.h" 2057429Smarkm#include "buffer.h" 2157429Smarkm#include "ssh.h" 2257429Smarkm 2357429Smarkm/* Initializes the buffer structure. */ 2457429Smarkm 2560573Skrisvoid 2657429Smarkmbuffer_init(Buffer *buffer) 2757429Smarkm{ 2857429Smarkm buffer->alloc = 4096; 2957429Smarkm buffer->buf = xmalloc(buffer->alloc); 3057429Smarkm buffer->offset = 0; 3157429Smarkm buffer->end = 0; 3257429Smarkm} 3357429Smarkm 3457429Smarkm/* Frees any memory used for the buffer. */ 3557429Smarkm 3660573Skrisvoid 3757429Smarkmbuffer_free(Buffer *buffer) 3857429Smarkm{ 3957429Smarkm memset(buffer->buf, 0, buffer->alloc); 4057429Smarkm xfree(buffer->buf); 4157429Smarkm} 4257429Smarkm 4357429Smarkm/* 4457429Smarkm * Clears any data from the buffer, making it empty. This does not actually 4557429Smarkm * zero the memory. 4657429Smarkm */ 4757429Smarkm 4860573Skrisvoid 4957429Smarkmbuffer_clear(Buffer *buffer) 5057429Smarkm{ 5157429Smarkm buffer->offset = 0; 5257429Smarkm buffer->end = 0; 5357429Smarkm} 5457429Smarkm 5557429Smarkm/* Appends data to the buffer, expanding it if necessary. */ 5657429Smarkm 5760573Skrisvoid 5857429Smarkmbuffer_append(Buffer *buffer, const char *data, unsigned int len) 5957429Smarkm{ 6057429Smarkm char *cp; 6157429Smarkm buffer_append_space(buffer, &cp, len); 6257429Smarkm memcpy(cp, data, len); 6357429Smarkm} 6457429Smarkm 6557429Smarkm/* 6657429Smarkm * Appends space to the buffer, expanding the buffer if necessary. This does 6757429Smarkm * not actually copy the data into the buffer, but instead returns a pointer 6857429Smarkm * to the allocated region. 6957429Smarkm */ 7057429Smarkm 7160573Skrisvoid 7257429Smarkmbuffer_append_space(Buffer *buffer, char **datap, unsigned int len) 7357429Smarkm{ 7457429Smarkm /* If the buffer is empty, start using it from the beginning. */ 7557429Smarkm if (buffer->offset == buffer->end) { 7657429Smarkm buffer->offset = 0; 7757429Smarkm buffer->end = 0; 7857429Smarkm } 7957429Smarkmrestart: 8057429Smarkm /* If there is enough space to store all data, store it now. */ 8157429Smarkm if (buffer->end + len < buffer->alloc) { 8257429Smarkm *datap = buffer->buf + buffer->end; 8357429Smarkm buffer->end += len; 8457429Smarkm return; 8557429Smarkm } 8657429Smarkm /* 8757429Smarkm * If the buffer is quite empty, but all data is at the end, move the 8857429Smarkm * data to the beginning and retry. 8957429Smarkm */ 9057429Smarkm if (buffer->offset > buffer->alloc / 2) { 9157429Smarkm memmove(buffer->buf, buffer->buf + buffer->offset, 9257429Smarkm buffer->end - buffer->offset); 9357429Smarkm buffer->end -= buffer->offset; 9457429Smarkm buffer->offset = 0; 9557429Smarkm goto restart; 9657429Smarkm } 9757429Smarkm /* Increase the size of the buffer and retry. */ 9857429Smarkm buffer->alloc += len + 32768; 9957429Smarkm buffer->buf = xrealloc(buffer->buf, buffer->alloc); 10057429Smarkm goto restart; 10157429Smarkm} 10257429Smarkm 10357429Smarkm/* Returns the number of bytes of data in the buffer. */ 10457429Smarkm 10560573Skrisunsigned int 10657429Smarkmbuffer_len(Buffer *buffer) 10757429Smarkm{ 10857429Smarkm return buffer->end - buffer->offset; 10957429Smarkm} 11057429Smarkm 11157429Smarkm/* Gets data from the beginning of the buffer. */ 11257429Smarkm 11360573Skrisvoid 11457429Smarkmbuffer_get(Buffer *buffer, char *buf, unsigned int len) 11557429Smarkm{ 11657429Smarkm if (len > buffer->end - buffer->offset) 11760573Skris fatal("buffer_get: trying to get more bytes than in buffer"); 11857429Smarkm memcpy(buf, buffer->buf + buffer->offset, len); 11957429Smarkm buffer->offset += len; 12057429Smarkm} 12157429Smarkm 12257429Smarkm/* Consumes the given number of bytes from the beginning of the buffer. */ 12357429Smarkm 12460573Skrisvoid 12557429Smarkmbuffer_consume(Buffer *buffer, unsigned int bytes) 12657429Smarkm{ 12757429Smarkm if (bytes > buffer->end - buffer->offset) 12860573Skris fatal("buffer_consume: trying to get more bytes than in buffer"); 12957429Smarkm buffer->offset += bytes; 13057429Smarkm} 13157429Smarkm 13257429Smarkm/* Consumes the given number of bytes from the end of the buffer. */ 13357429Smarkm 13460573Skrisvoid 13557429Smarkmbuffer_consume_end(Buffer *buffer, unsigned int bytes) 13657429Smarkm{ 13757429Smarkm if (bytes > buffer->end - buffer->offset) 13860573Skris fatal("buffer_consume_end: trying to get more bytes than in buffer"); 13957429Smarkm buffer->end -= bytes; 14057429Smarkm} 14157429Smarkm 14257429Smarkm/* Returns a pointer to the first used byte in the buffer. */ 14357429Smarkm 14457429Smarkmchar * 14557429Smarkmbuffer_ptr(Buffer *buffer) 14657429Smarkm{ 14757429Smarkm return buffer->buf + buffer->offset; 14857429Smarkm} 14957429Smarkm 15057429Smarkm/* Dumps the contents of the buffer to stderr. */ 15157429Smarkm 15260573Skrisvoid 15357429Smarkmbuffer_dump(Buffer *buffer) 15457429Smarkm{ 15557429Smarkm int i; 15657429Smarkm unsigned char *ucp = (unsigned char *) buffer->buf; 15757429Smarkm 15857429Smarkm for (i = buffer->offset; i < buffer->end; i++) 15957429Smarkm fprintf(stderr, " %02x", ucp[i]); 16057429Smarkm fprintf(stderr, "\n"); 16157429Smarkm} 162