Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
wwstring.cpp
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.cpp $*
26 * *
27 * Author:: Patrick Smith *
28 * *
29 * $Modtime:: 12/13/01 10:48p $*
30 * *
31 * $Revision:: 17 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37#include "wwstring.h"
38#include "win.h"
39#include "wwmemlog.h"
40#include "mutex.h"
41#include <stdio.h>
42
43
45// Static member initialzation
47
48FastCriticalSectionClass StringClass::m_Mutex;
49
50TCHAR StringClass::m_NullChar = 0;
51TCHAR * StringClass::m_EmptyString = &m_NullChar;
52
53//
54// A trick to optimize strings that are allocated from the stack and used only temporarily
55//
56// For alignment reasons we need twice as large block...
57char StringClass::m_TempStrings[(StringClass::MAX_TEMP_STRING*2)*StringClass::MAX_TEMP_BYTES];
58
59unsigned StringClass::ReservedMask=0;
60
62//
63// Get_String
64//
66void
67StringClass::Get_String (int length, bool is_temp)
68{
70
71 if (!is_temp && length == 0) {
72 m_Buffer = m_EmptyString;
73 return;
74 }
75
76 TCHAR *string = NULL;
77
78 //
79 // Should we attempt to use a temp buffer for this string?
80 //
81 if (is_temp && length <= MAX_TEMP_LEN && ReservedMask!=ALL_TEMP_STRINGS_USED_MASK) {
82
83 //
84 // Make sure no one else is requesting a temp pointer
85 // at the same time we are. There is a slight possibility that another
86 // thread stole the last available buffer in between the if sentence and
87 // the mutex lock, but that is a feature by design and doesn't cause
88 // anything bad to happen.
89 //
91
92 //
93 // Try to find an available temporary buffer
94 //
95 // TODO: Don't loop, there are better ways
96 unsigned mask=1;
97 for (int index = 0; index < MAX_TEMP_STRING; index ++, mask<<=1) {
98 unsigned mask=1<<index;
99 if (!(ReservedMask&mask)) {
100 ReservedMask|=mask;
101
102 //
103 // Grab this unused buffer for our string
104 //
105 unsigned temp_string=reinterpret_cast<unsigned>(m_TempStrings);
106 temp_string+=MAX_TEMP_BYTES*MAX_TEMP_STRING;
107 temp_string&=~(MAX_TEMP_BYTES*MAX_TEMP_STRING-1);
108 temp_string+=index*MAX_TEMP_BYTES;
109 temp_string+=sizeof(_HEADER); // The buffer contains header as well, and it needs to be at the start
110 string=reinterpret_cast<char*>(temp_string);
111
112 Set_Buffer_And_Allocated_Length (string, MAX_TEMP_LEN);
113 break;
114 }
115 }
116 }
117
118 if (string == NULL) {
119
120 //
121 // Allocate a new string as necessary
122 //
123 if (length > 0) {
124 Set_Buffer_And_Allocated_Length (Allocate_Buffer (length), length);
125 } else {
126 Free_String ();
127 }
128 }
129}
130
131
133//
134// Resize
135//
137void
138StringClass::Resize (int new_len)
139{
141
142 int allocated_len = Get_Allocated_Length ();
143 if (new_len > allocated_len) {
144
145 //
146 // Allocate the new buffer and copy the contents of our current
147 // string.
148 //
149 TCHAR *new_buffer = Allocate_Buffer (new_len);
150 _tcscpy (new_buffer, m_Buffer);
151
152 //
153 // Switch to the new buffer
154 //
155 Set_Buffer_And_Allocated_Length (new_buffer, new_len);
156 }
157
158 return ;
159}
160
161
163//
164// Uninitialised_Grow
165//
167void
168StringClass::Uninitialised_Grow (int new_len)
169{
171
172 int allocated_len = Get_Allocated_Length ();
173 if (new_len > allocated_len) {
174
175 //
176 // Switch to a newly allocated buffer
177 //
178 TCHAR *new_buffer = Allocate_Buffer (new_len);
179 Set_Buffer_And_Allocated_Length (new_buffer, new_len);
180 }
181
182 //
183 // Whenever this function is called, clear the cached length
184 //
185 Store_Length (0);
186 return ;
187}
188
189
191//
192// Uninitialised_Grow
193//
195void
196StringClass::Free_String (void)
197{
198 if (m_Buffer != m_EmptyString) {
199
200 unsigned buffer_base=reinterpret_cast<unsigned>(m_Buffer-sizeof (StringClass::_HEADER));
201 unsigned temp_base=reinterpret_cast<unsigned>(m_TempStrings+MAX_TEMP_BYTES*MAX_TEMP_STRING);
202
203 if ((buffer_base>>11)==(temp_base>>11)) {
204 m_Buffer[0] = 0;
205
206 //
207 // Make sure no one else is changing the reserved mask
208 // at the same time we are.
209 //
211
212 unsigned index=(buffer_base/MAX_TEMP_BYTES)&(MAX_TEMP_STRING-1);
213 unsigned mask=1<<index;
214 ReservedMask&=~mask;
215 }
216 else {
217
218 //
219 // String wasn't temporary, so free the memory
220 //
221 char *buffer = ((char *)m_Buffer) - sizeof (StringClass::_HEADER);
222 delete [] buffer;
223 }
224
225 //
226 // Reset the buffer
227 //
228 m_Buffer = m_EmptyString;
229 }
230
231 return ;
232}
233
234
236//
237// Format
238//
240int _cdecl
241StringClass::Format_Args (const TCHAR *format, const va_list & arg_list )
242{
243 //
244 // Make a guess at the maximum length of the resulting string
245 //
246 TCHAR temp_buffer[512] = { 0 };
247 int retval = 0;
248
249 //
250 // Format the string
251 //
252 #ifdef _UNICODE
253 retval = _vsnwprintf (temp_buffer, 512, format, arg_list);
254 #else
255 retval = _vsnprintf (temp_buffer, 512, format, arg_list);
256 #endif
257
258 //
259 // Copy the string into our buffer
260 //
261 (*this) = temp_buffer;
262
263 return retval;
264}
265
266
268//
269// Format
270//
272int _cdecl
273StringClass::Format (const TCHAR *format, ...)
274{
275 va_list arg_list;
276 va_start (arg_list, format);
277
278 //
279 // Make a guess at the maximum length of the resulting string
280 //
281 TCHAR temp_buffer[512] = { 0 };
282 int retval = 0;
283
284 //
285 // Format the string
286 //
287 #ifdef _UNICODE
288 retval = _vsnwprintf (temp_buffer, 512, format, arg_list);
289 #else
290 retval = _vsnprintf (temp_buffer, 512, format, arg_list);
291 #endif
292
293 //
294 // Copy the string into our buffer
295 //
296 (*this) = temp_buffer;
297
298 va_end (arg_list);
299 return retval;
300}
301
302
304//
305// Release_Resources
306//
308void
310{
311 Free_String();
312}
313
314
316// Copy_Wide
317//
319bool StringClass::Copy_Wide (const WCHAR *source)
320{
321 if (source != NULL) {
322
323 int length;
324 BOOL unmapped;
325
326 length = WideCharToMultiByte (CP_ACP, 0 , source, -1, NULL, 0, NULL, &unmapped);
327 if (length > 0) {
328
329 // Convert.
330 WideCharToMultiByte (CP_ACP, 0, source, -1, Get_Buffer (length), length, NULL, NULL);
331
332 // Update length.
333 Store_Length (length - 1);
334 }
335
336 // Were all characters successfully mapped?
337 return (!unmapped);
338 }
339
340 // Failure.
341 return (false);
342}
#define NULL
Definition BaseType.h:92
#define BOOL
Definition Wnd_File.h:57
friend class LockClass
Definition mutex.h:174
int _cdecl Format(const TCHAR *format,...)
Definition wwstring.cpp:273
int _cdecl Format_Args(const TCHAR *format, const va_list &arg_list)
Definition wwstring.cpp:241
TCHAR * Get_Buffer(int new_length)
Definition wwstring.h:549
void Release_Resources(void)
Definition wwstring.cpp:309
bool Copy_Wide(const WCHAR *source)
Definition wwstring.cpp:319
else return(RetVal)
char buffer[1024]
@ MEM_STRINGS
Definition wwmemlog.h:66
#define WWMEMLOG(category)
Definition wwmemlog.h:183