Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
wwstring.h
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** 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 ***
21 ***********************************************************************************************
22 * *
23 * Project Name : WWSaveLoad *
24 * *
25 * $Archive:: /Commando/Code/wwlib/wwstring.h $*
26 * *
27 * Author:: Patrick Smith *
28 * *
29 * $Modtime:: 12/13/01 5:11p $*
30 * *
31 * $Revision:: 37 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37#if defined(_MSC_VER)
38#pragma once
39#endif
40
41#ifndef __WWSTRING_H
42#define __WWSTRING_H
43
44#include "always.h"
45#include "mutex.h"
46#include "win.h"
47#include <string.h>
48#include <stdarg.h>
49#include <tchar.h>
50#include "trim.h"
51#include "wwdebug.h"
52#ifdef _UNIX
53#include "osdep.h"
54#endif
55
56
57
59//
60// StringClass
61//
62// Note: This class is UNICODE friendly. That means it can be
63// compiled using either single-byte or double-byte strings. There
64// are no assumptions made as to the size of a character.
65//
66// Any method that takes a parameter with the word 'len' or 'length'
67// in it refers to a count of characters. If the name contains 'byte'
68// it is talking about the memory size.
69//
72{
73public:
74
76 // Public constructors/destructors
78 StringClass (bool hint_temporary);
79 StringClass (int initial_len = 0, bool hint_temporary = false);
80 StringClass (const StringClass &string, bool hint_temporary = false);
81 StringClass (const TCHAR *string, bool hint_temporary = false);
82 StringClass (TCHAR ch, bool hint_temporary = false);
83 StringClass (const WCHAR *string, bool hint_temporary = false);
84 ~StringClass (void);
85
87 // Public operators
89 bool operator== (const TCHAR *rvalue) const;
90 bool operator!= (const TCHAR *rvalue) const;
91
92 inline const StringClass &operator= (const StringClass &string);
93 inline const StringClass &operator= (const TCHAR *string);
94 inline const StringClass &operator= (TCHAR ch);
95 inline const StringClass &operator= (const WCHAR *string);
96
97 const StringClass &operator+= (const StringClass &string);
98 const StringClass &operator+= (const TCHAR *string);
99 const StringClass &operator+= (TCHAR ch);
100
101 friend StringClass operator+ (const StringClass &string1, const StringClass &string2);
102 friend StringClass operator+ (const TCHAR *string1, const StringClass &string2);
103 friend StringClass operator+ (const StringClass &string1, const TCHAR *string2);
104
105 bool operator < (const TCHAR *string) const;
106 bool operator <= (const TCHAR *string) const;
107 bool operator > (const TCHAR *string) const;
108 bool operator >= (const TCHAR *string) const;
109
110 const TCHAR & operator[] (int index) const;
111 TCHAR & operator[] (int index);
112 inline operator const TCHAR * (void) const;
113
115 // Public methods
117 int Compare (const TCHAR *string) const;
118 int Compare_No_Case (const TCHAR *string) const;
119
120 inline int Get_Length (void) const;
121 bool Is_Empty (void) const;
122
123 void Erase (int start_index, int char_count);
124 int _cdecl Format (const TCHAR *format, ...);
125 int _cdecl Format_Args (const TCHAR *format, const va_list & arg_list );
126
127 // Trim leading and trailing whitespace characters (values <= 32)
128 void Trim(void);
129
130 TCHAR * Get_Buffer (int new_length);
131 TCHAR * Peek_Buffer (void);
132 const TCHAR * Peek_Buffer (void) const;
133
134 bool Copy_Wide (const WCHAR *source);
135
137 // Static methods
139 void Release_Resources (void); //why was this static? -MW
140
141private:
142
144 // Private structures
146 typedef struct _HEADER
147 {
148 int allocated_length;
149 int length;
150 } HEADER;
151
153 // Private constants
155 // Note: Don't change these enums without withs checking the Get_String() and Free_String() function!
156 enum
157 {
158 MAX_TEMP_STRING = 8,
159 MAX_TEMP_LEN = 256-sizeof(_HEADER),
160 MAX_TEMP_BYTES = (MAX_TEMP_LEN * sizeof (TCHAR)) + sizeof (HEADER),
161 ALL_TEMP_STRINGS_USED_MASK = 0xff
162 };
163
165 // Private methods
167 void Get_String (int length, bool is_temp);
168 TCHAR * Allocate_Buffer (int length);
169 void Resize (int size);
170 void Uninitialised_Grow (int length);
171 void Free_String (void);
172
173 inline void Store_Length (int length);
174 inline void Store_Allocated_Length (int allocated_length);
175 inline HEADER * Get_Header (void) const;
176 int Get_Allocated_Length (void) const;
177
178 void Set_Buffer_And_Allocated_Length (TCHAR *buffer, int length);
179
181 // Private member data
183 TCHAR * m_Buffer;
184
186 // Static member data
188 static unsigned ReservedMask;
189 static char m_TempStrings[];
190
191 static FastCriticalSectionClass m_Mutex;
192
193 static TCHAR m_NullChar;
194 static TCHAR * m_EmptyString;
195};
196
198// operator=
200inline const StringClass &
202{
203 int len = string.Get_Length();
204 Uninitialised_Grow(len+1);
205 Store_Length(len);
206
207 ::memcpy (m_Buffer, string.m_Buffer, (len+1) * sizeof (TCHAR));
208 return (*this);
209
210}
211
213// operator=
215inline const StringClass &
216StringClass::operator= (const TCHAR *string)
217{
218 if (string != 0) {
219
220 int len = _tcslen (string);
221 Uninitialised_Grow (len+1);
222 Store_Length (len);
223
224 ::memcpy (m_Buffer, string, (len + 1) * sizeof (TCHAR));
225 }
226
227 return (*this);
228}
229
230
232// operator=
234inline const StringClass &
235StringClass::operator= (const WCHAR *string)
236{
237 if (string != 0) {
238 Copy_Wide (string);
239 }
240
241 return (*this);
242}
243
244
246// operator=
248inline const StringClass &
250{
251 Uninitialised_Grow (2);
252
253 m_Buffer[0] = ch;
254 m_Buffer[1] = m_NullChar;
255 Store_Length (1);
256
257 return (*this);
258}
259
261// StringClass
263inline
264StringClass::StringClass (bool hint_temporary)
265 : m_Buffer (m_EmptyString)
266{
267 Get_String (MAX_TEMP_LEN, hint_temporary);
268 m_Buffer[0] = m_NullChar;
269
270 return ;
271}
272
274// StringClass
276inline
277StringClass::StringClass (int initial_len, bool hint_temporary)
278 : m_Buffer (m_EmptyString)
279{
280 Get_String (initial_len, hint_temporary);
281 m_Buffer[0] = m_NullChar;
282
283 return ;
284}
285
287// StringClass
289inline
290StringClass::StringClass (TCHAR ch, bool hint_temporary)
291 : m_Buffer (m_EmptyString)
292{
293 Get_String (2, hint_temporary);
294 (*this) = ch;
295 return ;
296}
297
299// StringClass
301inline
302StringClass::StringClass (const StringClass &string, bool hint_temporary)
303 : m_Buffer (m_EmptyString)
304{
305 if (hint_temporary || (string.Get_Length()>0)) {
306 Get_String (string.Get_Length()+1, hint_temporary);
307 }
308
309 (*this) = string;
310 return ;
311}
312
314// StringClass
316inline
317StringClass::StringClass (const TCHAR *string, bool hint_temporary)
318 : m_Buffer (m_EmptyString)
319{
320 int len=string ? _tcsclen(string) : 0;
321 if (hint_temporary || len>0) {
322 Get_String (len+1, hint_temporary);
323 }
324
325 (*this) = string;
326 return ;
327}
328
330// StringClass
332inline
333StringClass::StringClass (const WCHAR *string, bool hint_temporary)
334 : m_Buffer (m_EmptyString)
335{
336 int len = string ? wcslen (string) : 0;
337 if (hint_temporary || len > 0) {
338 Get_String (len + 1, hint_temporary);
339 }
340
341 (*this) = string;
342 return ;
343}
344
346// ~StringClass
348inline
350{
351 Free_String ();
352 return ;
353}
354
355
357// Is_Empty
359inline bool
361{
362 return (m_Buffer[0] == m_NullChar);
363}
364
366// Compare
368inline int
369StringClass::Compare (const TCHAR *string) const
370{
371 return _tcscmp (m_Buffer, string);
372}
373
375// Compare_No_Case
377inline int
378StringClass::Compare_No_Case (const TCHAR *string) const
379{
380 return _tcsicmp (m_Buffer, string);
381}
382
384// operator[]
386inline const TCHAR &
388{
389 WWASSERT (index >= 0 && index < Get_Length ());
390 return m_Buffer[index];
391}
392
394// operator[]
396inline TCHAR &
398{
399 WWASSERT (index >= 0 && index < Get_Length ());
400 return m_Buffer[index];
401}
402
404// operator const TCHAR *
406inline
407StringClass::operator const TCHAR * (void) const
408{
409 return m_Buffer;
410}
411
413// operator==
415inline bool
416StringClass::operator== (const TCHAR *rvalue) const
417{
418 return (Compare (rvalue) == 0);
419}
420
422// operator!=
424inline bool
425StringClass::operator!= (const TCHAR *rvalue) const
426{
427 return (Compare (rvalue) != 0);
428}
429
431// operator <
433inline bool
434StringClass::operator < (const TCHAR *string) const
435{
436 return (_tcscmp (m_Buffer, string) < 0);
437}
438
440// operator <=
442inline bool
443StringClass::operator <= (const TCHAR *string) const
444{
445 return (_tcscmp (m_Buffer, string) <= 0);
446}
447
449// operator >
451inline bool
452StringClass::operator > (const TCHAR *string) const
453{
454 return (_tcscmp (m_Buffer, string) > 0);
455}
456
458// operator >=
460inline bool
461StringClass::operator >= (const TCHAR *string) const
462{
463 return (_tcscmp (m_Buffer, string) >= 0);
464}
465
466
468// Erase
470inline void
471StringClass::Erase (int start_index, int char_count)
472{
473 int len = Get_Length ();
474
475 if (start_index < len) {
476
477 if (start_index + char_count > len) {
478 char_count = len - start_index;
479 }
480
481 ::memmove ( &m_Buffer[start_index],
482 &m_Buffer[start_index + char_count],
483 (len - (start_index + char_count) + 1) * sizeof (TCHAR));
484
485 Store_Length( len - char_count );
486 }
487
488 return ;
489}
490
491
493// Trim leading and trailing whitespace characters (values <= 32)
495inline void StringClass::Trim(void)
496{
497 strtrim(m_Buffer);
498}
499
500
502// operator+=
504inline const StringClass &
505StringClass::operator+= (const TCHAR *string)
506{
507 WWASSERT (string != NULL);
508
509 int cur_len = Get_Length ();
510 int src_len = _tcslen (string);
511 int new_len = cur_len + src_len;
512
513 //
514 // Make sure our buffer is large enough to hold the new string
515 //
516 Resize (new_len + 1);
517 Store_Length (new_len);
518
519 //
520 // Copy the new string onto our the end of our existing buffer
521 //
522 ::memcpy (&m_Buffer[cur_len], string, (src_len + 1) * sizeof (TCHAR));
523 return (*this);
524}
525
527// operator+=
529inline const StringClass &
531{
532 int cur_len = Get_Length ();
533 Resize (cur_len + 2);
534
535 m_Buffer[cur_len] = ch;
536 m_Buffer[cur_len + 1] = m_NullChar;
537
538 if (ch != m_NullChar) {
539 Store_Length (cur_len + 1);
540 }
541
542 return (*this);
543}
544
546// Get_Buffer
548inline TCHAR *
550{
551 Uninitialised_Grow (new_length);
552
553 return m_Buffer;
554}
555
557// Peek_Buffer
559inline TCHAR *
561{
562 return m_Buffer;
563}
564
566// Peek_Buffer
568inline const TCHAR *
570{
571 return m_Buffer;
572}
573
575// operator+=
577inline const StringClass &
579{
580 int src_len = string.Get_Length();
581 if (src_len > 0) {
582 int cur_len = Get_Length ();
583 int new_len = cur_len + src_len;
584
585 //
586 // Make sure our buffer is large enough to hold the new string
587 //
588 Resize (new_len + 1);
589 Store_Length (new_len);
590
591 //
592 // Copy the new string onto our the end of our existing buffer
593 //
594 ::memcpy (&m_Buffer[cur_len], (const TCHAR *)string, (src_len + 1) * sizeof (TCHAR));
595 }
596
597 return (*this);
598}
599
601// operator+=
603inline StringClass
604operator+ (const StringClass &string1, const StringClass &string2)
605{
606 StringClass new_string(string1, true);
607 new_string += string2;
608 return new_string;
609}
610
612// operator+=
614inline StringClass
615operator+ (const TCHAR *string1, const StringClass &string2)
616{
617 StringClass new_string(string1, true);
618 new_string += string2;
619 return new_string;
620}
621
623// operator+=
625inline StringClass
626operator+ (const StringClass &string1, const TCHAR *string2)
627{
628 StringClass new_string(string1, true);
629 StringClass new_string2(string2, true);
630 new_string += new_string2;
631 return new_string;
632}
633
635// Get_Allocated_Length
636//
637// Return allocated size of the string buffer
639inline int
640StringClass::Get_Allocated_Length (void) const
641{
642 int allocated_length = 0;
643
644 //
645 // Read the allocated length from the header
646 //
647 if (m_Buffer != m_EmptyString) {
648 HEADER *header = Get_Header ();
649 allocated_length = header->allocated_length;
650 }
651
652 return allocated_length;
653}
654
656// Get_Length
657//
658// Return text legth. If length is not known calculate it, otherwise
659// just return the previously stored value (strlen tends to take
660// quite a lot cpu time if a lot of string combining operations are
661// performed.
663inline int
665{
666 int length = 0;
667
668 if (m_Buffer != m_EmptyString) {
669
670 //
671 // Read the length from the header
672 //
673 HEADER *header = Get_Header ();
674 length = header->length;
675
676 //
677 // Hmmm, a zero length was stored in the header,
678 // we better manually get the string length.
679 //
680 if (length == 0) {
681 length = _tcslen (m_Buffer);
682 ((StringClass *)this)->Store_Length (length);
683 }
684 }
685
686 return length;
687}
688
690// Set_Buffer_And_Allocated_Length
691//
692// Set buffer pointer and init size variable. Length is set to 0
693// as the contents of the new buffer are not necessarily defined.
695inline void
696StringClass::Set_Buffer_And_Allocated_Length (TCHAR *buffer, int length)
697{
698 Free_String ();
699 m_Buffer = buffer;
700
701 //
702 // Update the header (if necessary)
703 //
704 if (m_Buffer != m_EmptyString) {
705 Store_Allocated_Length (length);
706 Store_Length (0);
707 } else {
708 WWASSERT (length == 0);
709 }
710
711 return ;
712}
713
715// Allocate_Buffer
717inline TCHAR *
718StringClass::Allocate_Buffer (int length)
719{
720 //
721 // Allocate a buffer that is 'length' characters long, plus the
722 // bytes required to hold the header.
723 //
724 char *buffer = W3DNEWARRAY char[(sizeof (TCHAR) * length) + sizeof (StringClass::_HEADER)];
725
726 //
727 // Fill in the fields of the header
728 //
729 HEADER *header = reinterpret_cast<HEADER *>(buffer);
730 header->length = 0;
731 header->allocated_length = length;
732
733 //
734 // Return the buffer as if it was a TCHAR pointer
735 //
736 return reinterpret_cast<TCHAR *>(buffer + sizeof (StringClass::_HEADER));
737}
738
740// Get_Header
742inline StringClass::HEADER *
743StringClass::Get_Header (void) const
744{
745 return reinterpret_cast<HEADER *>(((char *)m_Buffer) - sizeof (StringClass::_HEADER));
746}
747
749// Store_Allocated_Length
751inline void
752StringClass::Store_Allocated_Length (int allocated_length)
753{
754 if (m_Buffer != m_EmptyString) {
755 HEADER *header = Get_Header ();
756 header->allocated_length = allocated_length;
757 } else {
758 WWASSERT (allocated_length == 0);
759 }
760
761 return ;
762}
763
765// Store_Length
766//
767// Set length... The caller of this (private) function better
768// be sure that the len is correct.
770inline void
771StringClass::Store_Length (int length)
772{
773 if (m_Buffer != m_EmptyString) {
774 HEADER *header = Get_Header ();
775 header->length = length;
776 } else {
777 WWASSERT (length == 0);
778 }
779
780 return ;
781}
782
783#endif //__WWSTRING_H
784
#define NULL
Definition BaseType.h:92
#define WWASSERT
#define W3DNEWARRAY
Definition always.h:110
const StringClass & operator+=(const StringClass &string)
Definition wwstring.h:578
void Trim(void)
Definition wwstring.h:495
const StringClass & operator=(const StringClass &string)
Definition wwstring.h:201
StringClass(bool hint_temporary)
Definition wwstring.h:264
int Compare(const TCHAR *string) const
Definition wwstring.h:369
int _cdecl Format(const TCHAR *format,...)
Definition wwstring.cpp:273
~StringClass(void)
Definition wwstring.h:349
bool operator>(const TCHAR *string) const
Definition wwstring.h:452
void Erase(int start_index, int char_count)
Definition wwstring.h:471
bool operator>=(const TCHAR *string) const
Definition wwstring.h:461
int _cdecl Format_Args(const TCHAR *format, const va_list &arg_list)
Definition wwstring.cpp:241
bool operator==(const TCHAR *rvalue) const
Definition wwstring.h:416
TCHAR * Get_Buffer(int new_length)
Definition wwstring.h:549
bool Is_Empty(void) const
Definition wwstring.h:360
bool operator!=(const TCHAR *rvalue) const
Definition wwstring.h:425
int Get_Length(void) const
Definition wwstring.h:664
bool operator<(const TCHAR *string) const
Definition wwstring.h:434
int Compare_No_Case(const TCHAR *string) const
Definition wwstring.h:378
TCHAR * Peek_Buffer(void)
Definition wwstring.h:560
void Release_Resources(void)
Definition wwstring.cpp:309
friend StringClass operator+(const StringClass &string1, const StringClass &string2)
Definition wwstring.h:604
bool operator<=(const TCHAR *string) const
Definition wwstring.h:443
bool Copy_Wide(const WCHAR *source)
Definition wwstring.cpp:319
const TCHAR & operator[](int index) const
Definition wwstring.h:387
LOCALEFILE_HEADERCHUNK HEADER
Definition locale.cpp:83
else return(RetVal)
char buffer[1024]
char * strtrim(char *buffer)
Definition trim.cpp:60
StringClass operator+(const StringClass &string1, const StringClass &string2)
Definition wwstring.h:604