324 lines
7.4 KiB
C
324 lines
7.4 KiB
C
/*-------------------------------------------------------------------------
|
|
D Y N S T R I N G
|
|
|
|
Implementation file for a dynamic string object.
|
|
Usage and copyright: see dynstring.h
|
|
|
|
Mark Koennecke, March 1998
|
|
-----------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include "dynstring.h"
|
|
|
|
#define DYNMAGIC 27031998
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
typedef struct __DynString {
|
|
int iMAGIC;
|
|
char *pBuffer;
|
|
int iTextLen;
|
|
int iBufferSize;
|
|
int iResize;
|
|
} DynString;
|
|
/*--------------------------------------------------------------------------*/
|
|
pDynString CreateDynString(int iInitial, int iResize)
|
|
{
|
|
pDynString pNew = NULL;
|
|
|
|
if (iInitial <= 0)
|
|
iInitial = 512;
|
|
if (iResize <= 0)
|
|
iResize = 512;
|
|
|
|
/* new memory */
|
|
pNew = (pDynString) malloc(sizeof(DynString));
|
|
if (!pNew) {
|
|
return NULL;
|
|
}
|
|
memset(pNew, 0, sizeof(DynString));
|
|
pNew->pBuffer = (char *) malloc(iInitial * sizeof(char));
|
|
if (!pNew->pBuffer) {
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
memset(pNew->pBuffer, 0, iInitial * sizeof(char));
|
|
|
|
/* initialise the rest */
|
|
pNew->iMAGIC = DYNMAGIC;
|
|
pNew->iBufferSize = iInitial;
|
|
pNew->iResize = iResize;
|
|
pNew->iTextLen = 0;
|
|
|
|
return pNew;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int Resize(pDynString self, int iRequested)
|
|
{
|
|
char *pNewBuffer;
|
|
int iNewSize;
|
|
|
|
if (iRequested < self->iBufferSize) {
|
|
return 1;
|
|
}
|
|
|
|
/* get new data space */
|
|
iNewSize = iRequested + self->iResize;
|
|
pNewBuffer = (char *) malloc(iNewSize * sizeof(char));
|
|
if (!pNewBuffer) {
|
|
return 0;
|
|
}
|
|
memset(pNewBuffer, 0, iNewSize);
|
|
|
|
/* copy data */
|
|
memcpy(pNewBuffer, self->pBuffer, self->iTextLen);
|
|
|
|
/* swap things around */
|
|
if (self->pBuffer) {
|
|
free(self->pBuffer);
|
|
}
|
|
self->pBuffer = pNewBuffer;
|
|
self->iBufferSize = iNewSize;
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int DynStringCapacity(pDynString self, int length)
|
|
{
|
|
if(self->iBufferSize < length){
|
|
return Resize(self,length);
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
void DeleteDynString(pDynString self)
|
|
{
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
if (self->pBuffer)
|
|
free(self->pBuffer);
|
|
|
|
self->iMAGIC = 0;
|
|
free(self);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int DynStringClear(pDynString self)
|
|
{
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
self->iTextLen = 0;
|
|
memset(self->pBuffer, 0, self->iBufferSize);
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int DynStringCopy(pDynString self, char *pText)
|
|
{
|
|
int iRequested, iRet;
|
|
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
if(pText == 0){
|
|
return 0;
|
|
}
|
|
iRequested = strlen(pText);
|
|
if (iRequested >= self->iBufferSize) {
|
|
iRet = Resize(self, iRequested);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
} else { /* safety: remove rubbish */
|
|
|
|
memset(self->pBuffer, 0, self->iBufferSize * sizeof(char));
|
|
}
|
|
strcpy(self->pBuffer, pText);
|
|
self->iTextLen = iRequested;
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int DynStringConcat(pDynString self, char *pText)
|
|
{
|
|
int iRequested, iRet;
|
|
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
iRequested = strlen(pText) + self->iTextLen;
|
|
if (iRequested >= self->iBufferSize) {
|
|
iRet = Resize(self, iRequested);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
strcpy(self->pBuffer + self->iTextLen, pText);
|
|
self->iTextLen = iRequested;
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int DynStringConcatLine(pDynString self, char *pText)
|
|
{
|
|
DynStringConcat(self,pText);
|
|
return DynStringConcatChar(self,'\n');
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int DynStringConcatChar(pDynString self, char c)
|
|
{
|
|
int iRequested, iRet;
|
|
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
iRequested = self->iTextLen + 1;
|
|
if (iRequested >= self->iBufferSize) {
|
|
iRet = Resize(self, iRequested);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
self->pBuffer[self->iTextLen] = c;
|
|
self->iTextLen++;
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
int DynStringConcatBytes(pDynString self, char *data, int datalen)
|
|
{
|
|
int iRequested, iRet;
|
|
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
iRequested = self->iTextLen + datalen;
|
|
if (iRequested >= self->iBufferSize) {
|
|
iRet = Resize(self, iRequested);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
memcpy(self->pBuffer + self->iTextLen,data,datalen);
|
|
self->iTextLen += datalen;
|
|
return 1;
|
|
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
int DynStringInsert(pDynString self, char *pText, int iPos)
|
|
{
|
|
int iRequested, iRet, iPush, iRest;
|
|
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
/* provide space */
|
|
iPush = strlen(pText);
|
|
iRequested = self->iTextLen + iPush;
|
|
if (iRequested >= self->iBufferSize) {
|
|
iRet = Resize(self, iRequested);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (iPos >= self->iTextLen) {
|
|
iPos = self->iTextLen;
|
|
} else {
|
|
if (iPos < 0) {
|
|
iPos = 0;
|
|
}
|
|
memmove(&self->pBuffer[iPos + iPush], &self->pBuffer[iPos], self->iTextLen + 1 - iPos);
|
|
}
|
|
|
|
memcpy(&self->pBuffer[iPos], pText, iPush);
|
|
self->iTextLen = iRequested;
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int DynStringReplace(pDynString self, char *pText, int iPos)
|
|
{
|
|
int iRequested, iRet;
|
|
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
iRequested = strlen(pText) + iPos;
|
|
if (iRequested >= self->iBufferSize) {
|
|
iRet = Resize(self, iRequested);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
memcpy(&self->pBuffer[iPos], pText, strlen(pText) * sizeof(char));
|
|
if (iRequested > self->iTextLen) {
|
|
self->iTextLen = iRequested;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
char *GetCharArray(pDynString self)
|
|
{
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
return self->pBuffer;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int GetDynStringLength(pDynString self)
|
|
{
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
return self->iTextLen;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int DynStringBackspace(pDynString self)
|
|
{
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
if (self->iTextLen > 0) {
|
|
self->pBuffer[self->iTextLen - 1] = '\0';
|
|
self->iTextLen--;
|
|
}
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
int DynStringShorten(pDynString self, int length)
|
|
{
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
if (length >= self->iTextLen || length < 0) {
|
|
return 0;
|
|
}
|
|
self->iTextLen = length;
|
|
self->pBuffer[length] = '\0';
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
char *Dyn2Cstring(pDynString self) {
|
|
char *result;
|
|
|
|
assert(self);
|
|
assert(self->iMAGIC == DYNMAGIC);
|
|
|
|
result = self->pBuffer;
|
|
|
|
free(self);
|
|
|
|
return result;
|
|
}
|