Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
widestring.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/widestring.h $*
26 * *
27 * Author:: Patrick Smith *
28 * *
29 * $Modtime:: 2/06/02 4:59p $*
30 * *
31 * $Revision:: 22 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37#if defined(_MSC_VER)
38#pragma once
39#endif
40
41#ifndef __WIDESTRING_H
42#define __WIDESTRING_H
43
44#include <string.h>
45#include <stdarg.h>
46#include "always.h"
47#include "wwdebug.h"
48#include "win.h"
49#include "wwstring.h"
50#include "trim.h"
51#include <wchar.h>
52#ifdef _UNIX
53#include "osdep.h"
54#endif
55
57//
58// WideStringClass
59//
60// This is a UNICODE (double-byte) version of StringClass. All
61// operations are performed on wide character strings.
62//
65{
66public:
67
69 // Public constructors/destructors
71 WideStringClass (int initial_len = 0, bool hint_temporary = false);
72 WideStringClass (const WideStringClass &string, bool hint_temporary = false);
73 WideStringClass (const WCHAR *string, bool hint_temporary = false);
74 WideStringClass (WCHAR ch, bool hint_temporary = false);
75 WideStringClass (const char *string, bool hint_temporary = false);
76 ~WideStringClass (void);
77
79 // Public operators
81 bool operator== (const WCHAR *rvalue) const;
82 bool operator!= (const WCHAR *rvalue) const;
83
84 inline const WideStringClass &operator= (const WideStringClass &string);
85 inline const WideStringClass &operator= (const WCHAR *string);
86 inline const WideStringClass &operator= (WCHAR ch);
87 inline const WideStringClass &operator= (const char *string);
88
89 const WideStringClass &operator+= (const WideStringClass &string);
90 const WideStringClass &operator+= (const WCHAR *string);
91 const WideStringClass &operator+= (WCHAR ch);
92
93 friend WideStringClass operator+ (const WideStringClass &string1, const WideStringClass &string2);
94 friend WideStringClass operator+ (const WCHAR *string1, const WideStringClass &string2);
95 friend WideStringClass operator+ (const WideStringClass &string1, const WCHAR *string2);
96
97 bool operator < (const WCHAR *string) const;
98 bool operator <= (const WCHAR *string) const;
99 bool operator > (const WCHAR *string) const;
100 bool operator >= (const WCHAR *string) const;
101
102 WCHAR operator[] (int index) const;
103 WCHAR& operator[] (int index);
104 operator const WCHAR * (void) const;
105
107 // Public methods
109 int Compare (const WCHAR *string) const;
110 int Compare_No_Case (const WCHAR *string) const;
111
112 inline int Get_Length (void) const;
113 bool Is_Empty (void) const;
114
115 void Erase (int start_index, int char_count);
116 int _cdecl Format (const WCHAR *format, ...);
117 int _cdecl Format_Args (const WCHAR *format, const va_list & arg_list );
118 bool Convert_From (const char *text);
119 bool Convert_To (StringClass &string);
120 bool Convert_To (StringClass &string) const;
121
122 // Trim leading and trailing whitespace (chars <= 32)
123 void Trim(void);
124
125 // Check if the string is composed of ANSI range characters. (0-255)
126 bool Is_ANSI(void);
127
128 WCHAR * Get_Buffer (int new_length);
129 WCHAR * Peek_Buffer (void);
130
132 // Static methods
134 static void Release_Resources (void);
135
136private:
137
139 // Private structures
141 typedef struct _HEADER
142 {
143 int allocated_length;
144 int length;
145 } HEADER;
146
148 // Private constants
150 enum
151 {
152 MAX_TEMP_STRING = 4,
153 MAX_TEMP_LEN = 256,
154 MAX_TEMP_BYTES = (MAX_TEMP_LEN * sizeof (WCHAR)) + sizeof (HEADER),
155 };
156
158 // Private methods
160 void Get_String (int length, bool is_temp);
161 WCHAR * Allocate_Buffer (int length);
162 void Resize (int size);
163 void Uninitialised_Grow (int length);
164 void Free_String (void);
165
166 inline void Store_Length (int length);
167 inline void Store_Allocated_Length (int allocated_length);
168 inline HEADER * Get_Header (void) const;
169 int Get_Allocated_Length (void) const;
170
171 void Set_Buffer_And_Allocated_Length (WCHAR *buffer, int length);
172
174 // Private member data
176 WCHAR * m_Buffer;
177
179 // Static member data
181 static char m_TempString1[MAX_TEMP_BYTES];
182 static char m_TempString2[MAX_TEMP_BYTES];
183 static char m_TempString3[MAX_TEMP_BYTES];
184 static char m_TempString4[MAX_TEMP_BYTES];
185 static WCHAR * m_FreeTempPtr[MAX_TEMP_STRING];
186 static WCHAR * m_ResTempPtr[MAX_TEMP_STRING];
187
188 static int m_UsedTempStringCount;
189 static FastCriticalSectionClass m_TempMutex;
190
191 static WCHAR m_NullChar;
192 static WCHAR * m_EmptyString;
193};
194
196// WideStringClass
198inline
199WideStringClass::WideStringClass (int initial_len, bool hint_temporary)
200 : m_Buffer (m_EmptyString)
201{
202 Get_String (initial_len, hint_temporary);
203 m_Buffer[0] = m_NullChar;
204
205 return ;
206}
207
209// WideStringClass
211inline
212WideStringClass::WideStringClass (WCHAR ch, bool hint_temporary)
213 : m_Buffer (m_EmptyString)
214{
215 Get_String (2, hint_temporary);
216 (*this) = ch;
217 return ;
218}
219
221// WideStringClass
223inline
224WideStringClass::WideStringClass (const WideStringClass &string, bool hint_temporary)
225 : m_Buffer (m_EmptyString)
226{
227 if (hint_temporary || (string.Get_Length()>1)) {
228 Get_String(string.Get_Length()+1, hint_temporary);
229 }
230
231 (*this) = string;
232 return ;
233}
234
236// WideStringClass
238inline
239WideStringClass::WideStringClass (const WCHAR *string, bool hint_temporary)
240 : m_Buffer (m_EmptyString)
241{
242 int len=string ? wcslen(string) : 0;
243 if (hint_temporary || len>0) {
244 Get_String (len+1, hint_temporary);
245 }
246
247 (*this) = string;
248 return ;
249}
250
251
253// WideStringClass
255inline
256WideStringClass::WideStringClass (const char *string, bool hint_temporary)
257 : m_Buffer (m_EmptyString)
258{
259 if (hint_temporary || (string && strlen(string)>0)) {
260 Get_String (strlen(string) + 1, hint_temporary);
261 }
262
263 (*this) = string;
264 return ;
265}
266
268// ~WideStringClass
270inline
272{
273 Free_String ();
274 return ;
275}
276
277
279// Is_Empty
281inline bool
283{
284 return (m_Buffer[0] == m_NullChar);
285}
286
288// Compare
290inline int
291WideStringClass::Compare (const WCHAR *string) const
292{
293 if (string) {
294 return wcscmp (m_Buffer, string);
295 }
296
297 return -1;
298}
299
301// Compare_No_Case
303inline int
304WideStringClass::Compare_No_Case (const WCHAR *string) const
305{
306 if (string) {
307 return _wcsicmp (m_Buffer, string);
308 }
309
310 return -1;
311}
312
314// operator[]
316inline WCHAR
318{
319 WWASSERT (index >= 0 && index < Get_Length ());
320 return m_Buffer[index];
321}
322
323inline WCHAR&
325{
326 WWASSERT (index >= 0 && index < Get_Length ());
327 return m_Buffer[index];
328}
329
331// operator const WCHAR *
333inline
334WideStringClass::operator const WCHAR * (void) const
335{
336 return m_Buffer;
337}
338
340// operator==
342inline bool
343WideStringClass::operator== (const WCHAR *rvalue) const
344{
345 return (Compare (rvalue) == 0);
346}
347
349// operator!=
351inline bool
352WideStringClass::operator!= (const WCHAR *rvalue) const
353{
354 return (Compare (rvalue) != 0);
355}
356
358// operator=
360inline const WideStringClass &
362{
363 return operator= ((const WCHAR *)string);
364}
365
367// operator <
369inline bool
370WideStringClass::operator < (const WCHAR *string) const
371{
372 if (string) {
373 return (wcscmp (m_Buffer, string) < 0);
374 }
375
376 return false;
377}
378
380// operator <=
382inline bool
383WideStringClass::operator <= (const WCHAR *string) const
384{
385 if (string) {
386 return (wcscmp (m_Buffer, string) <= 0);
387 }
388
389 return false;
390}
391
393// operator >
395inline bool
396WideStringClass::operator > (const WCHAR *string) const
397{
398 if (string) {
399 return (wcscmp (m_Buffer, string) > 0);
400 }
401
402 return true;
403}
404
406// operator >=
408inline bool
409WideStringClass::operator >= (const WCHAR *string) const
410{
411 if (string) {
412 return (wcscmp (m_Buffer, string) >= 0);
413 }
414
415 return true;
416}
417
418
420// Erase
422inline void
423WideStringClass::Erase (int start_index, int char_count)
424{
425 int len = Get_Length ();
426
427 if (start_index < len) {
428
429 if (start_index + char_count > len) {
430 char_count = len - start_index;
431 }
432
433 ::memmove ( &m_Buffer[start_index],
434 &m_Buffer[start_index + char_count],
435 (len - (start_index + char_count) + 1) * sizeof (WCHAR));
436
437 Store_Length( wcslen(m_Buffer) );
438 }
439
440 return ;
441}
442
444// Trim leading and trailing whitespace (chars <= 32)
446inline void WideStringClass::Trim(void)
447{
448 wcstrim(m_Buffer);
449 int len = wcslen(m_Buffer);
450 Store_Length(len);
451}
452
453
455// operator=
457inline const WideStringClass &
458WideStringClass::operator= (const WCHAR *string)
459{
460 if (string) {
461 int len = wcslen (string);
462 Uninitialised_Grow (len + 1);
463 Store_Length (len);
464
465 ::memcpy (m_Buffer, string, (len + 1) * sizeof (WCHAR));
466 }
467
468 return (*this);
469}
470
472// operator=
474inline const WideStringClass &
476{
477 Convert_From(string);
478 return (*this);
479}
480
482// operator=
484inline const WideStringClass &
486{
487 Uninitialised_Grow (2);
488
489 m_Buffer[0] = ch;
490 m_Buffer[1] = m_NullChar;
491 Store_Length (1);
492
493 return (*this);
494}
495
497// operator+=
499inline const WideStringClass &
501{
502 if (string) {
503 int cur_len = Get_Length ();
504 int src_len = wcslen (string);
505 int new_len = cur_len + src_len;
506
507 //
508 // Make sure our buffer is large enough to hold the new string
509 //
510 Resize (new_len + 1);
511 Store_Length (new_len);
512
513 //
514 // Copy the new string onto our the end of our existing buffer
515 //
516 ::memcpy (&m_Buffer[cur_len], string, (src_len + 1) * sizeof (WCHAR));
517 }
518
519 return (*this);
520}
521
523// operator+=
525inline const WideStringClass &
527{
528 int cur_len = Get_Length ();
529 Resize (cur_len + 2);
530
531 m_Buffer[cur_len] = ch;
532 m_Buffer[cur_len + 1] = m_NullChar;
533
534 if (ch != m_NullChar) {
535 Store_Length (cur_len + 1);
536 }
537
538 return (*this);
539}
540
542// Get_Buffer
544inline WCHAR *
546{
547 Uninitialised_Grow (new_length);
548
549 return m_Buffer;
550}
551
553// Peek_Buffer
555inline WCHAR *
557{
558 return m_Buffer;
559}
560
562// operator+=
564inline const WideStringClass &
566{
567 int src_len = string.Get_Length();
568 if (src_len > 0) {
569 int cur_len = Get_Length ();
570 int new_len = cur_len + src_len;
571
572 //
573 // Make sure our buffer is large enough to hold the new string
574 //
575 Resize (new_len + 1);
576 Store_Length (new_len);
577
578 //
579 // Copy the new string onto our the end of our existing buffer
580 //
581 ::memcpy (&m_Buffer[cur_len], (const WCHAR *)string, (src_len + 1) * sizeof (WCHAR));
582 }
583
584 return (*this);
585}
586
588// operator+=
590inline WideStringClass
591operator+ (const WideStringClass &string1, const WideStringClass &string2)
592{
593 WideStringClass new_string(string1, true);
594 new_string += string2;
595 return new_string;
596}
597
599// operator+=
601inline WideStringClass
602operator+ (const WCHAR *string1, const WideStringClass &string2)
603{
604 WideStringClass new_string(string1, true);
605 new_string += string2;
606 return new_string;
607}
608
610// operator+=
612inline WideStringClass
613operator+ (const WideStringClass &string1, const WCHAR *string2)
614{
615 WideStringClass new_string(string1, true);
616 new_string += string2;
617 return new_string;
618}
619
621// Get_Allocated_Length
622//
623// Return allocated size of the string buffer
625inline int
626WideStringClass::Get_Allocated_Length (void) const
627{
628 int allocated_length = 0;
629
630 //
631 // Read the allocated length from the header
632 //
633 if (m_Buffer != m_EmptyString) {
634 HEADER *header = Get_Header ();
635 allocated_length = header->allocated_length;
636 }
637
638 return allocated_length;
639}
640
642// Get_Length
643//
644// Return text legth. If length is not known calculate it, otherwise
645// just return the previously stored value (strlen tends to take
646// quite a lot cpu time if a lot of string combining operations are
647// performed.
649inline int
651{
652 int length = 0;
653
654 if (m_Buffer != m_EmptyString) {
655
656 //
657 // Read the length from the header
658 //
659 HEADER *header = Get_Header ();
660 length = header->length;
661
662 //
663 // Hmmm, a zero length was stored in the header,
664 // we better manually get the string length.
665 //
666 if (length == 0) {
667 length = wcslen (m_Buffer);
668 ((WideStringClass *)this)->Store_Length (length);
669 }
670 }
671
672 return length;
673}
674
676// Set_Buffer_And_Allocated_Length
677//
678// Set buffer pointer and init size variable. Length is set to 0
679// as the contents of the new buffer are not necessarily defined.
681inline void
682WideStringClass::Set_Buffer_And_Allocated_Length (WCHAR *buffer, int length)
683{
684 Free_String ();
685 m_Buffer = buffer;
686
687 //
688 // Update the header (if necessary)
689 //
690 if (m_Buffer != m_EmptyString) {
691 Store_Allocated_Length (length);
692 Store_Length (0);
693 } else {
694 WWASSERT (length == 0);
695 }
696
697 return ;
698}
699
701// Allocate_Buffer
703inline WCHAR *
704WideStringClass::Allocate_Buffer (int length)
705{
706 //
707 // Allocate a buffer that is 'length' characters long, plus the
708 // bytes required to hold the header.
709 //
710 char *buffer = W3DNEWARRAY char[(sizeof (WCHAR) * length) + sizeof (WideStringClass::_HEADER)];
711
712 //
713 // Fill in the fields of the header
714 //
715 HEADER *header = reinterpret_cast<HEADER *>(buffer);
716 header->length = 0;
717 header->allocated_length = length;
718
719 //
720 // Return the buffer as if it was a WCHAR pointer
721 //
722 return reinterpret_cast<WCHAR *>(buffer + sizeof (WideStringClass::_HEADER));
723}
724
726// Get_Header
728inline WideStringClass::HEADER *
729WideStringClass::Get_Header (void) const
730{
731 return reinterpret_cast<HEADER *>(((char *)m_Buffer) - sizeof (WideStringClass::_HEADER));
732}
733
735// Store_Allocated_Length
737inline void
738WideStringClass::Store_Allocated_Length (int allocated_length)
739{
740 if (m_Buffer != m_EmptyString) {
741 HEADER *header = Get_Header ();
742 header->allocated_length = allocated_length;
743 } else {
744 WWASSERT (allocated_length == 0);
745 }
746
747 return ;
748}
749
751// Store_Length
752//
753// Set length... The caller of this (private) function better
754// be sure that the len is correct.
756inline void
757WideStringClass::Store_Length (int length)
758{
759 if (m_Buffer != m_EmptyString) {
760 HEADER *header = Get_Header ();
761 header->length = length;
762 } else {
763 WWASSERT (length == 0);
764 }
765
766 return ;
767}
768
770// Convert_To
772inline bool
774{
775 return (string.Copy_Wide (m_Buffer));
776}
777
778
779inline bool
781{
782 return (string.Copy_Wide (m_Buffer));
783}
784
785#endif //__WIDESTRING_H
786
#define WWASSERT
#define W3DNEWARRAY
Definition always.h:110
~WideStringClass(void)
Definition widestring.h:271
bool Is_ANSI(void)
bool operator>(const WCHAR *string) const
Definition widestring.h:396
int Get_Length(void) const
Definition widestring.h:650
int _cdecl Format(const WCHAR *format,...)
int _cdecl Format_Args(const WCHAR *format, const va_list &arg_list)
friend WideStringClass operator+(const WideStringClass &string1, const WideStringClass &string2)
Definition widestring.h:591
bool Convert_To(StringClass &string)
Definition widestring.h:773
bool Convert_From(const char *text)
WCHAR * Peek_Buffer(void)
Definition widestring.h:556
void Trim(void)
Definition widestring.h:446
WCHAR operator[](int index) const
Definition widestring.h:317
const WideStringClass & operator+=(const WideStringClass &string)
Definition widestring.h:565
bool operator<(const WCHAR *string) const
Definition widestring.h:370
static void Release_Resources(void)
WCHAR * Get_Buffer(int new_length)
Definition widestring.h:545
void Erase(int start_index, int char_count)
Definition widestring.h:423
int Compare_No_Case(const WCHAR *string) const
Definition widestring.h:304
WideStringClass(int initial_len=0, bool hint_temporary=false)
Definition widestring.h:199
bool operator==(const WCHAR *rvalue) const
Definition widestring.h:343
bool Is_Empty(void) const
Definition widestring.h:282
int Compare(const WCHAR *string) const
Definition widestring.h:291
bool operator<=(const WCHAR *string) const
Definition widestring.h:383
bool operator>=(const WCHAR *string) const
Definition widestring.h:409
const WideStringClass & operator=(const WideStringClass &string)
Definition widestring.h:361
bool operator!=(const WCHAR *rvalue) const
Definition widestring.h:352
LOCALEFILE_HEADERCHUNK HEADER
Definition locale.cpp:83
else return(RetVal)
char buffer[1024]
wchar_t * wcstrim(wchar_t *buffer)
Definition trim.cpp:88
WideStringClass operator+(const WideStringClass &string1, const WideStringClass &string2)
Definition widestring.h:591