/* ** Command & Conquer Renegade(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 . */ /****************************************************************************\ * 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 #include #include #include #include #include "wstring.h" #define PADSIZE 32 // include a little padding on alloc for future growth Wstring::Wstring() : str(NULL), strsize(0) { } Wstring::Wstring(IN char *string):str(NULL), strsize(0) { set(string); } Wstring::Wstring(IN Wstring &other):str(NULL), strsize(0) { if (other.str!=NULL) { str=new char[strlen(other.str)+PADSIZE+1]; strsize=strlen(other.str)+PADSIZE+1; strcpy(str,other.str); } } Wstring::~Wstring() { clear(); } bool Wstring::operator<(IN Wstring &other) RO { if (str == NULL && other.str == NULL) return false; if (str == NULL) return true; return ( strcmp(str, other.str) < 0 ); } bit8 Wstring::operator==(IN char *other) RO { if ((str==NULL)&&(other==NULL)) return(TRUE); if(strcmp(str, other) != 0) return(FALSE); else return(TRUE); } bit8 Wstring::operator==(IN Wstring &other) RO { 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) RO { if(strcmp(str, other) != 0) return(TRUE); else return(FALSE); } bit8 Wstring::operator!=(IN Wstring &other) RO { 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=(IN 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) { uint32 len; if (s==NULL) // it's OK to cat nothing return(TRUE); // Determine the length of the resultant string. len = strlen(s) + 1; if(str) len += strlen(str); // Space check strgrow(len); strcat(str, s); return(TRUE); } bit8 Wstring::cat(uint32 size, IN char *s) { uint32 len; // Determine the length of the resultant string. len = size + 1; if(str) len += strlen(str); // Allocate memory for the new string. strgrow(len); strncat(str, s, size); str[len-1]=0; // make sure null term'd 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; 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); memmove(str+pos,str+pos+count,len-pos-count+1); 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; } return(removed); } void Wstring::removeSpaces(void) { removeChar(' '); removeChar('\t'); } void Wstring::clear(void) { if(str) delete[](str); strsize=0; str=NULL; } // This is usually used for raw storage instead of string ops... void Wstring::setSize(sint32 size) { clear(); if (size<0) return; str=new char[size]; strsize=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) RO { if(!str) return ""; return str; } char Wstring::get(uint32 index) RO { if(index < strlen(str)) return str[index]; return(0); } uint32 Wstring::length(void) RO { 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); strgrow(strlen(str)+strlen(instring)+1); memmove(str+pos+strlen(instring),str+pos,strlen(str)-pos+1); memmove(str+pos,instring,strlen(instring)); 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 temp[2]; temp[0]=k; temp[1]=0; return(insert(temp,pos)); } // Joe Howes (05/19/2000): This function inserts commas to nicely format a // large number (i.e. 1234567890 -> 1,234,567,890). It doesn't really care // if the string is really a number or not. bit8 Wstring::beautifyNumber() { int len = length(); int accum = 3 - (len % 3); int numcommas = 0; if( accum == 3 ) accum = -1; for(int i = 0; i < len; i++) { if( accum == 3 ) { insert(',', i + numcommas); numcommas++; } accum = ( accum == 3 || accum == -1 ) ? 1 : accum + 1; } 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(IN char *replaceThis,IN 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; strgrow(strlen(s)+1); 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; strgrow(size+1); strncpy(str,string,size); str[size]=0; return(TRUE); } // Added by Joe Howes. Takes a printf formatted string and a set of args. // The expanded string must not exceed 1k or twice the length of the format // string, whichever is larger. It would probably be better to traverse // the format string and properly calculate, the length so this will // work in all cases, but this should be good enough for 99% of Wstring usage. char Wstring::setFormatted(IN char *msg, ...) { if( msg == NULL || strlen(msg) <= 0 ) return FALSE; char* string; va_list args; int len = (strlen(msg) < 1024) ? 1024 : (strlen(msg)*2); string = new char[len]; va_start(args, msg); vsprintf(string, msg, args); va_end(args); set(string); delete[] string; return(TRUE); } // This function converts all alphabetical characters in the string to lower // case. void Wstring::toLower(void) { uint32 i; int strlength=length(); for(i = 0; i < (uint32)strlength; i++) { if((str[i] >= 'A') && (str[i] <= 'Z')) str[i] = (sint8)tolower(str[i]); } } // This function converts all alphabetical characters in the string to upper // case. void Wstring::toUpper(void) { uint32 i; int strlength=length(); for(i = 0; i < (uint32)strlength; i++) { if((str[i] >= 'a') && (str[i] <= 'z')) str[i] = (sint8)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) { strgrow(len+1); str[len]=0; 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) RO { int i; sint32 start; sint32 stop; if (offset<0) // check for bad input return(-1); for (i=offset; i<(int)length(); i++) { if(strchr(delim,str[i])==NULL) break; } if (i>=(int)length()) return(-1); start=i; for (; i<(int)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 >= (sint32)length()) return(-1); for (; i<(int)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); } // // Make sure there's AT LEAST length bytes in this string object // void Wstring::strgrow(int length) { if (str==NULL) { str=new char[length+PADSIZE]; str[0]=0; strsize=length+PADSIZE; return; } else if (strsize >= length) // no need to alloc more data return; else // bah, gotta grow... { char *newstr=new char[length+PADSIZE]; strsize=length+PADSIZE; strcpy(newstr,str); delete[](str); str=newstr; return; } }