CnC_Red_Alert/LAUNCHER/WSTRING.CPP

612 lines
12 KiB
C++

/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************\
* C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *
******************************************************************************
Project Name: Carpenter (The RedAlert ladder creator)
File Name : string.cpp
Author : Neal Kettler
Start Date : June 1, 1997
Last Update : June 17, 1997
A fairly typical string class. This string class always copies any input
string to it's own memory (for assignment or construction).
\***************************************************************************/
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "wstring.h"
Wstring::Wstring():str(NULL)
{ }
Wstring::Wstring(IN char *string):str(NULL)
{ set(string); }
Wstring::Wstring(IN const Wstring &other):str(NULL)
{
if (other.str!=NULL)
{
str=new char[strlen(other.str)+1];
strcpy(str,other.str);
}
}
Wstring::~Wstring()
{ clear(); }
bit8 Wstring::operator==(IN char *other)
{
if ((str==NULL)&&(other==NULL))
return(TRUE);
if(strcmp(str, other) != 0)
return(FALSE);
else
return(TRUE);
}
bit8 Wstring::operator==(IN Wstring &other)
{
if((str == NULL) && (other.str == NULL))
return(TRUE);
if((str == NULL) || (other.str == NULL))
return(FALSE);
if(strcmp(str, other.str) != 0)
return(FALSE);
else
return(TRUE);
}
bit8 Wstring::operator!=(IN char *other)
{
if(strcmp(str, other) != 0)
return(TRUE);
else
return(FALSE);
}
bit8 Wstring::operator!=(IN Wstring &other)
{
if((str == NULL) && (other.str == NULL))
return(FALSE);
if((str == NULL) || (other.str == NULL))
return(TRUE);
if(strcmp(str, other.str) != 0)
return(TRUE);
else
return(FALSE);
}
Wstring &Wstring::operator=(char *other)
{
set(other);
return(*this);
}
Wstring &Wstring::operator=(IN Wstring &other)
{
if(*this == other)
return(*this);
set(other.get());
return(*this);
}
bit8 Wstring::cat(IN char *s)
{
char *oldStr;
uint32 len;
if (s==NULL) // it's OK to cat nothing
return(TRUE);
// Save the contents of the string.
oldStr = str;
// Determine the length of the resultant string.
len = strlen(s) + 1;
if(oldStr)
len += strlen(oldStr);
// Allocate memory for the new string.
if(!(str = new char[(len * sizeof(char))]))
{
str = oldStr;
return(FALSE);
}
// Copy the contents of the old string and concatenate the passed
// string.
if(oldStr) strcpy(str, oldStr);
else str[0] = 0;
strcat(str, s);
// delete the old string.
if(oldStr)
delete[](oldStr);
return(TRUE);
}
bit8 Wstring::cat(uint32 size, IN char *s)
{
char *oldStr;
uint32 len;
// Save the contents of the string.
oldStr = str;
// Determine the length of the resultant string.
len = size + 1;
if(oldStr)
len += strlen(oldStr);
// Allocate memory for the new string.
if(!(str = new char[(len * sizeof(char))]))
{
str = oldStr;
return(FALSE);
}
// Copy the contents of the old string and concatenate the passed
// string.
if(oldStr)
strcpy(str, oldStr);
else
str[0] = 0;
strncat(str, s, size);
// delete the old string.
if(oldStr)
delete[](oldStr);
return(TRUE);
}
bit8 Wstring::cat(IN Wstring &other)
{
return cat(other.get());
}
Wstring &Wstring::operator+=(IN char *string)
{
cat(string);
return(*this);
}
Wstring &Wstring::operator+=(IN Wstring &other)
{
cat(other.get());
return(*this);
}
Wstring Wstring::operator+(IN char *string)
{
Wstring temp = *this;
temp.cat(string);
return(temp);
}
Wstring Wstring::operator+(IN Wstring &s)
{
Wstring temp = *this;
temp.cat(s);
return(temp);
}
//
// This function deletes 'count' characters indexed by `pos' from the Wstring.
// If `pos'+'count' is > the length of the array, the last 'count' characters
// of the string are removed. If an error occurs, FALSE is returned.
// Otherwise, TRUE is returned. Note: count has a default value of 1.
//
//
char Wstring::remove(sint32 pos,sint32 count)
{
char *s;
sint32 len;
if (!str)
return(FALSE);
len = (sint32)strlen(str);
if(pos+count > len)
pos = len - count;
if (pos < 0)
{
count+=pos; // If they remove before 0, ignore up till beginning
pos=0;
}
if (count<=0)
return(FALSE);
if(!(s = new char[len-count+1]))
{
//ErrorMessage(SET_EM, "Insufficient memory to modify Wstring.");
return(FALSE);
}
///////DBGMSG("Wstring::remove POS: "<<pos<<" LEN: "<<len);
// put nulls on both ends of substring to be removed
str[pos] = 0;
str[pos+count-1] = 0;
strcpy(s, str);
strcat(s, &(str[pos + count]));
delete[](str);
str = s;
return(TRUE);
}
// Remove all instances of a char from the string
bit8 Wstring::removeChar(char c)
{
int len=0;
char *cptr=NULL;
bit8 removed=FALSE;
if (str==NULL)
return(FALSE);
len=strlen(str);
while ((cptr=strchr(str,c)) !=NULL)
{
memmove(cptr,cptr+1,len-1-((int)(cptr-str)));
len--;
str[len]=0;
removed=TRUE;
}
if (removed)
{
char *newStr=new char[strlen(str)+1];
strcpy(newStr,str);
delete[](str);
str=newStr;
}
return(removed);
}
void Wstring::removeSpaces(void)
{
removeChar(' ');
removeChar('\t');
}
void Wstring::clear(void)
{
if(str)
delete[](str);
str=NULL;
}
void Wstring::setSize(sint32 size)
{
clear();
if (size<0)
return;
str=new char[size];
memset(str,0,size);
}
void Wstring::cellCopy(char *dest, uint32 len)
{
uint32 i;
strncpy(dest, str, len);
for(i = (uint32)strlen(str); i < len; i++)
dest[i] = ' ';
dest[len] = 0;
}
char *Wstring::get(void)
{
if(!str)
return "";
return str;
}
char Wstring::get(uint32 index)
{
if(index < strlen(str))
return str[index];
return(0);
}
uint32 Wstring::length(void)
{
if(str == NULL)
return(0);
return((uint32)strlen(str));
}
// Insert at given position and shift old stuff to right
bit8 Wstring::insert(char *instring, uint32 pos)
{
if (str==NULL)
return(set(instring));
if (pos>strlen(str))
pos=strlen(str);
char *newstr=new char[strlen(str)+strlen(instring)+1];
memset(newstr,0,strlen(str)+strlen(instring)+1);
strcpy(newstr,str);
// move the old data out of the way
int bytes=strlen(str)+1-pos;
memmove(newstr+pos+strlen(instring),newstr+pos,bytes);
// move the new data into place
memmove(newstr+pos,instring,strlen(instring));
delete[](str);
str=newstr;
return(TRUE);
}
// This function inserts the character specified by `k' into the string at the
// position indexed by `pos'. If `pos' is >= the length of the string, it is
// appended to the string. If an error occurs, FALSE is returned. Otherwise,
// TRUE is returned.
bit8 Wstring::insert(char k, uint32 pos)
{
char *s;
uint32 len;
char c[2];
if(!str)
{
c[0] = k;
c[1] = 0;
return(set(c));
}
len = (uint32)strlen(str);
if(pos > len)
pos = len;
if(!(s = (char *)new char[(len + 2)]))
{
//ErrorMessage(SET_EM, "Insufficient memory to modify Wstring.");
return(FALSE);
}
c[0] = str[pos];
str[pos] = 0;
c[1] = 0;
strcpy(s, str);
str[pos] = c[0];
c[0] = k;
strcat(s, c);
strcat(s, &(str[pos]));
delete[](str);
str = s;
return(TRUE);
}
// This function replaces any occurences of the string pointed to by
// `replaceThis' with the string pointed to by `withThis'. If an error
// occurs, FALSE is returned. Otherwise, TRUE is returned.
bit8 Wstring::replace(char *replaceThis, char *withThis)
{
Wstring dest;
char *foundStr, *src;
uint32 len;
src=get();
while(src && src[0])
{
foundStr = strstr(src, replaceThis);
if(foundStr)
{
len = (uint32)foundStr - (uint32)src;
if(len)
{
if(!dest.cat(len, src))
return(FALSE);
}
if(!dest.cat(withThis))
return(FALSE);
src = foundStr + strlen(replaceThis);
}
else
{
if(!dest.cat(src))
return(FALSE);
src=NULL;
}
}
return(set(dest.get()));
}
bit8 Wstring::set(IN char *s)
{
uint32 len;
clear();
len = (uint32)strlen(s) + 1;
if(!(str = new char[len]))
{
//ErrorMessage(SET_EM, "Insufficient memory to set Wstring.");
return(FALSE);
}
strcpy(str, s);
return(TRUE);
}
bit8 Wstring::set(char c, uint32 index)
{
if(index >= (uint32)strlen(str))
return FALSE;
str[index] = c;
return TRUE;
}
char Wstring::set(uint32 size, IN char *string)
{
uint32 len;
clear();
len = size + 1;
if(!(str = new char[len]))
{
//ErrorMessage(SET_EM, "Insufficient memory to set Wstring.");
return(FALSE);
}
// Copy the bytes in the string, and NULL-terminate it.
strncpy(str, string, size);
str[size] = 0;
return(TRUE);
}
// This function converts all alphabetical characters in the string to lower
// case.
void Wstring::toLower(void)
{
uint32 i;
for(i = 0; i < length(); i++)
{
if((str[i] >= 'A') && (str[i] <= 'Z'))
str[i] = tolower(str[i]);
}
}
// This function converts all alphabetical characters in the string to upper
// case.
void Wstring::toUpper(void)
{
uint32 i;
for(i = 0; i < length(); i++)
{
if((str[i] >= 'a') && (str[i] <= 'z'))
str[i] = toupper(str[i]);
}
}
// This function truncates the string so its length will match the specified
// `len'. If an error occurs, FALSE is returned. Otherwise, TRUE is returned.
bit8 Wstring::truncate(uint32 len)
{
Wstring tmp;
if(!tmp.set(len, get()) || !set(tmp.get()))
return(FALSE);
return(TRUE);
}
// Truncate the string after the character 'c' (gets rid of 'c' as well)
// Do nothing if 'c' isn't in the string
bit8 Wstring::truncate(char c)
{
sint32 len;
if (str==NULL)
return(FALSE);
char *cptr=strchr(str,c);
if (cptr==NULL)
return(FALSE);
len=(sint32)(cptr-str);
truncate((uint32)len);
return(TRUE);
}
// Get a token from this string that's seperated by one or more
// chars from the 'delim' string , start at offset & return offset
sint32 Wstring::getToken(int offset,char *delim,Wstring &out)
{
int i;
sint32 start;
sint32 stop;
for (i=offset; i<length(); i++) {
if(strchr(delim,str[i])==NULL)
break;
}
if (i>=length())
return(-1);
start=i;
for (; i<length(); i++) {
if(strchr(delim,str[i])!=NULL)
break;
}
stop=i-1;
out.set(str+start);
out.truncate((uint32)stop-start+1);
return(stop+1);
}
// Get the first line of text after offset. Lines are terminated by '\r\n' or '\n'
sint32 Wstring::getLine(int offset, Wstring &out)
{
int i;
sint32 start;
sint32 stop;
start=i=offset;
if (start >= length())
return(-1);
for (; i<length(); i++) {
if(strchr("\r\n",str[i])!=NULL)
break;
}
stop=i;
if ((str[stop]=='\r')&&(str[stop+1]=='\n'))
stop++;
out.set(str+start);
out.truncate((uint32)stop-start+1);
return(stop+1);
}