mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 14:28:40 +02:00
179 lines
5.0 KiB
C
179 lines
5.0 KiB
C
/***************************************************************/
|
|
/* */
|
|
/* DYNBUF.C */
|
|
/* */
|
|
/* Implementation of functions for manipulating dynamic */
|
|
/* buffers. */
|
|
/* */
|
|
/* This file is part of REMIND. */
|
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
|
/* */
|
|
/***************************************************************/
|
|
|
|
#include "config.h"
|
|
#include "dynbuf.h"
|
|
#include "err.h"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
/**********************************************************************
|
|
%FUNCTION: DBufMakeRoom
|
|
%ARGUMENTS:
|
|
dbuf -- pointer to a dynamic buffer
|
|
n -- size to expand to
|
|
%RETURNS:
|
|
OK if all went well; E_NO_MEM if out of memory
|
|
%DESCRIPTION:
|
|
Doubles the size of dynamic buffer until it has room for at least
|
|
'n' characters, not including trailing '\0'
|
|
**********************************************************************/
|
|
static int DBufMakeRoom(DynamicBuffer *dbuf, size_t n)
|
|
{
|
|
/* Double size until it's greater than n (strictly > to leave room
|
|
for trailing '\0' */
|
|
size_t size = dbuf->allocatedLen;
|
|
char *buf;
|
|
|
|
if (size > n) return OK;
|
|
|
|
while (size <= n) {
|
|
size *= 2;
|
|
}
|
|
|
|
/* Allocate memory */
|
|
buf = malloc(size);
|
|
if (!buf) return E_NO_MEM;
|
|
|
|
/* Copy contents */
|
|
strcpy(buf, dbuf->buffer);
|
|
|
|
/* Free contents if necessary */
|
|
if (dbuf->buffer != dbuf->staticBuf) free(dbuf->buffer);
|
|
dbuf->buffer = buf;
|
|
dbuf->allocatedLen = size;
|
|
return OK;
|
|
}
|
|
|
|
/**********************************************************************
|
|
%FUNCTION: DBufInit
|
|
%ARGUMENTS:
|
|
dbuf -- pointer to a dynamic buffer
|
|
%RETURNS:
|
|
Nothing
|
|
%DESCRIPTION:
|
|
Initializes a dynamic buffer
|
|
**********************************************************************/
|
|
void DBufInit(DynamicBuffer *dbuf)
|
|
{
|
|
dbuf->buffer = dbuf->staticBuf;
|
|
dbuf->len = 0;
|
|
dbuf->allocatedLen = DBUF_STATIC_SIZE;
|
|
dbuf->buffer[0] = 0;
|
|
}
|
|
|
|
/**********************************************************************
|
|
%FUNCTION: DBufPutcFN
|
|
%ARGUMENTS:
|
|
dbuf -- pointer to a dynamic buffer
|
|
c -- character to append to buffer
|
|
%RETURNS:
|
|
OK if all went well; E_NO_MEM if out of memory
|
|
%DESCRIPTION:
|
|
Appends a character to the buffer.
|
|
**********************************************************************/
|
|
int DBufPutcFN(DynamicBuffer *dbuf, char c)
|
|
{
|
|
if (dbuf->allocatedLen == dbuf->len+1) {
|
|
if (DBufMakeRoom(dbuf, dbuf->len+1) != OK) return E_NO_MEM;
|
|
}
|
|
dbuf->buffer[dbuf->len++] = c;
|
|
dbuf->buffer[dbuf->len] = 0;
|
|
return OK;
|
|
}
|
|
|
|
/**********************************************************************
|
|
%FUNCTION: DBufPuts
|
|
%ARGUMENTS:
|
|
dbuf -- pointer to a dynamic buffer
|
|
str -- string to append to buffer
|
|
%RETURNS:
|
|
OK if all went well; E_NO_MEM if out of memory
|
|
%DESCRIPTION:
|
|
Appends a string to the buffer.
|
|
**********************************************************************/
|
|
int DBufPuts(DynamicBuffer *dbuf, char const *str)
|
|
{
|
|
int l = strlen(str);
|
|
if (!l) return OK;
|
|
|
|
if (DBufMakeRoom(dbuf, dbuf->len+l) != OK) return E_NO_MEM;
|
|
strcpy((dbuf->buffer+dbuf->len), str);
|
|
dbuf->len += l;
|
|
return OK;
|
|
}
|
|
|
|
/**********************************************************************
|
|
%FUNCTION: DBufFree
|
|
%ARGUMENTS:
|
|
dbuf -- pointer to a dynamic buffer
|
|
%RETURNS:
|
|
Nothing
|
|
%DESCRIPTION:
|
|
Frees and reinitializes a dynamic buffer
|
|
**********************************************************************/
|
|
void DBufFree(DynamicBuffer *dbuf)
|
|
{
|
|
if (dbuf->buffer != dbuf->staticBuf) free(dbuf->buffer);
|
|
DBufInit(dbuf);
|
|
}
|
|
|
|
/**********************************************************************
|
|
%FUNCTION: DBufGets
|
|
%ARGUMENTS:
|
|
dbuf -- pointer to a dynamic buffer
|
|
fp -- file to read from
|
|
%RETURNS:
|
|
OK or E_NO_MEM
|
|
%DESCRIPTION:
|
|
Reads an entire line from a file and appends to dbuf. Does not include
|
|
trailing newline.
|
|
**********************************************************************/
|
|
int DBufGets(DynamicBuffer *dbuf, FILE *fp)
|
|
{
|
|
char tmp[256]; /* Safe to hard-code */
|
|
int busy = 1;
|
|
int l;
|
|
|
|
DBufFree(dbuf);
|
|
|
|
/* Try reading the first few bytes right into the buffer --
|
|
we can usually save some unnecessary copying */
|
|
|
|
*(dbuf->buffer) = 0;
|
|
if (fgets(dbuf->buffer, dbuf->allocatedLen, fp) == NULL) {
|
|
return OK;
|
|
}
|
|
if (!*(dbuf->buffer)) return OK;
|
|
dbuf->len = strlen(dbuf->buffer);
|
|
l = dbuf->len - 1;
|
|
if (dbuf->buffer[l] == '\n') {
|
|
dbuf->buffer[l] = 0;
|
|
dbuf->len = l;
|
|
return OK;
|
|
}
|
|
|
|
while(busy) {
|
|
*tmp = 0;
|
|
if (fgets(tmp, 256, fp) == NULL) return OK;
|
|
if (!*tmp) return OK;
|
|
l = strlen(tmp) - 1;
|
|
if (tmp[l] == '\n') {
|
|
tmp[l] = 0;
|
|
busy = 0;
|
|
}
|
|
if (DBufPuts(dbuf, tmp) != OK) return E_NO_MEM;
|
|
}
|
|
return OK;
|
|
}
|
|
|