Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

220 lines
5.5 KiB

/*
* Module: buffer.c
* Author: Mark I. Himelstein, Himelsoft, Inc.
* Purpose: manage varying length buffers for holding unknown sized
* sections
*/
#include "conv.h"
#undef data /* used locally */
extern int verbose;
/* buffer structure plays double duty. It is both the head
* and space header-- it wasn't worth making two structures.
*/
typedef struct buffer_s {
/* used by head */
char *current_data; /* current space we are filling */
long total; /* total bytes written */
struct buffer_s *last; /* last buffer */
long size; /* size for allocating new buffers */
/* used by space header */
char *data; /* data for this space header */
long left; /* in current space */
struct buffer_s *next; /* next buffer */
} buffer_s;
static char *
buffer_allocate_data(long size)
{
char * data;
data = (char *)malloc(size);
if (data == 0) {
fatal("cannot allocate char * structure\n");
} /* if */
return data;
} /* buffer_allocate_data */
extern struct buffer_s *
buffer_create(long allocate_size)
{
struct buffer_s *buf;
buf = (buffer_s *)calloc(sizeof(buffer_s), 1);
if (buf == 0) {
fatal("cannot allocate buffer structure\n");
} /* if */
buf->size = allocate_size;
buf->data = buffer_allocate_data(buf->size);
buf->current_data = buf->data;
buf->left = buf->size;
buf->last = buf;
return buf;
} /* buffer_create */
static void
buffer_check_for_space(
struct buffer_s *buf)
{
if (buf->left == 0) {
buf->last->next = buffer_create(buf->size);
buf->last = buf->last->next;
buf->current_data = buf->last->data;
buf->left = buf->last->left;
} /* if */
} /* buffer_check_for_space */
extern void
buffer_put(
struct buffer_s *buf,
char * src,
int bytes)
{
while (buf->left < bytes) {
int current_buffer_bytes; /* keep track of how many we sent */
current_buffer_bytes = buf->left;
buffer_put(buf, src, current_buffer_bytes);
src += current_buffer_bytes;
bytes -= current_buffer_bytes;
} /* if */
memcpy(buf->current_data, src, bytes);
buf->current_data += bytes;
buf->total += bytes;
buf->left -= bytes;
buffer_check_for_space(buf);
} /* buffer_put */
extern char *
buffer_ptr(
struct buffer_s *buf)
{
/* return ptr to next location */
return buf->current_data;
} /* buffer_ptr */
extern void
buffer_unput(
struct buffer_s *buf,
char *dest,
long bytes)
{
if ((buf->left + bytes) > buf->size) {
fatal("tried to unput over buffer boundary\n");
} /* if */
buf->current_data -= bytes;
memcpy(dest, buf->current_data, bytes);
buf->left += bytes;
buf->total -= bytes;
} /* buffer_unput */
extern void
buffer_seek_put(
struct buffer_s *buf,
char * dest,
char * src,
int bytes)
{
/* dest was returned from buffer_ptr, no need for caller to
* know the details.
*/
buf;
memcpy(dest, src, bytes);
} /* buffer_seek_put */
extern long
buffer_total(struct buffer_s *buf)
{
return buf->total;
} /* buffer_total */
extern void
buffer_put_value(
struct buffer_s *buf,
unsigned long value,
long size,
long vlength)
{
/* byte order independent holding vessels */
unsigned short two_bytes;
unsigned char one_byte;
unsigned long four_bytes;
struct {
unsigned char last;
unsigned three_bytes:24;
} yuck;
switch (size) {
case VARYING:
one_byte = (unsigned char)vlength;
buffer_put(buf, (char *)&one_byte, 1);
buffer_put(buf, (char *)value, vlength);
VERBOSE_PRINTF("(%d) \"%.*s\"\n", vlength, vlength, value);
break;
case 1:
one_byte = (unsigned char)value;
buffer_put(buf, (char *)&one_byte, 1);
VERBOSE_PRINTF("0x%x\n", value);
break;
case 2:
two_bytes = (unsigned short)value;
buffer_put(buf, (char *)&two_bytes, 2);
VERBOSE_PRINTF("0x%x\n", value);
break;
case 3:
buffer_unput(buf, &yuck.last, 1);
yuck.three_bytes = value;
buffer_put(buf, (char *)&yuck, 4);
VERBOSE_PRINTF("(0x%x) 0x%x\n", yuck.last, value);
break;
case 4:
four_bytes = value;
buffer_put(buf, (char *)&four_bytes, 4);
VERBOSE_PRINTF("0x%x\n", value);
break;
default:
fatal("not expecting arg size of %d\n", size);
} /* switch */
} /* buffer_put_value */
extern unsigned long
buffer_write(
struct buffer_s *buf_arg,
FILE *file)
{
struct buffer_s *buf = buf_arg;
unsigned long last_count = buf->size - buf->left;
while (buf->next) {
if (fwrite(buf->data, buf->size, 1, file) != 1) {
fatal("cannot write symbol or type buffer\n");
} /* if */
buf = buf->next;
} /* while */
if (last_count && fwrite(buf->data, last_count, 1, file) != 1) {
fatal("cannot write symbol or type buffer\n");
} /* if */
return buf_arg->total;
} /* buffer_write */