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