Skip to content

Commit 99abffe

Browse files
committed
feat(string): Implement constructors for AsciiString, UnicodeString that take a string and max length (#1476)
1 parent cfb0667 commit 99abffe

File tree

4 files changed

+64
-12
lines changed

4 files changed

+64
-12
lines changed

Core/GameEngine/Include/Common/AsciiString.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ class AsciiString
148148
*/
149149
AsciiString(const char* s);
150150

151+
/**
152+
Constructor -- from a literal string and max length.
153+
*/
154+
AsciiString(const char* s, int len);
155+
151156
/**
152157
Destructor. Not too exciting... clean up the works and such.
153158
*/

Core/GameEngine/Include/Common/UnicodeString.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ class UnicodeString
148148
*/
149149
explicit UnicodeString(const WideChar* s);
150150

151+
/**
152+
Constructor -- from a literal string and max length.
153+
*/
154+
UnicodeString(const WideChar* s, int len);
155+
151156
/**
152157
Destructor. Not too exciting... clean up the works and such.
153158
*/

Core/GameEngine/Source/Common/System/AsciiString.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,20 @@ void AsciiString::ensureUniqueBufferOfSize(int numCharsNeeded, Bool preserveData
125125
{
126126
validate();
127127

128+
const int usableNumChars = numCharsNeeded - 1;
129+
128130
if (m_data &&
129131
m_data->m_refCount == 1 &&
130132
m_data->m_numCharsAllocated >= numCharsNeeded)
131133
{
132134
// no buffer manhandling is needed (it's already large enough, and unique to us)
133135
if (strToCopy)
136+
{
134137
// TheSuperHackers @fix Mauller 04/04/2025 Replace strcpy with safer memmove as memory regions can overlap when part of string is copied to itself
135-
memmove(m_data->peek(), strToCopy, strlen(strToCopy) + 1);
138+
DEBUG_ASSERTCRASH(usableNumChars <= strlen(strToCopy), ("strToCopy is too small"));
139+
memmove(m_data->peek(), strToCopy, usableNumChars);
140+
m_data->peek()[usableNumChars] = 0;
141+
}
136142
if (strToCat)
137143
strcat(m_data->peek(), strToCat);
138144
return;
@@ -157,7 +163,11 @@ void AsciiString::ensureUniqueBufferOfSize(int numCharsNeeded, Bool preserveData
157163
// do these BEFORE releasing the old buffer, so that self-copies
158164
// or self-cats will work correctly.
159165
if (strToCopy)
160-
strcpy(newData->peek(), strToCopy);
166+
{
167+
DEBUG_ASSERTCRASH(usableNumChars <= strlen(strToCopy), ("strToCopy is too small"));
168+
strncpy(newData->peek(), strToCopy, usableNumChars);
169+
newData->peek()[usableNumChars] = 0;
170+
}
161171
if (strToCat)
162172
strcat(newData->peek(), strToCat);
163173

@@ -186,11 +196,22 @@ void AsciiString::releaseBuffer()
186196
}
187197

188198
// -----------------------------------------------------
189-
AsciiString::AsciiString(const char* s) : m_data(0)
199+
AsciiString::AsciiString(const char* s) : m_data(NULL)
190200
{
191201
//DEBUG_ASSERTCRASH(isMemoryManagerOfficiallyInited(), ("Initializing AsciiStrings prior to main (ie, as static vars) can cause memory leak reporting problems. Are you sure you want to do this?"));
192-
int len = (s)?strlen(s):0;
193-
if (len)
202+
int len = s ? (int)strlen(s) : 0;
203+
if (len > 0)
204+
{
205+
ensureUniqueBufferOfSize(len + 1, false, s, NULL);
206+
}
207+
validate();
208+
}
209+
210+
// -----------------------------------------------------
211+
AsciiString::AsciiString(const char* s, int len) : m_data(NULL)
212+
{
213+
len = min(s ? (int)strlen(s) : 0, len);
214+
if (len > 0)
194215
{
195216
ensureUniqueBufferOfSize(len + 1, false, s, NULL);
196217
}
@@ -375,7 +396,7 @@ void AsciiString::truncateBy(const Int charCount)
375396
const size_t len = strlen(peek());
376397
if (len > 0)
377398
{
378-
ensureUniqueBufferOfSize(len+1, true, NULL, NULL);
399+
ensureUniqueBufferOfSize(len + 1, true, NULL, NULL);
379400
size_t count = charCount;
380401
if (charCount > len)
381402
{

Core/GameEngine/Source/Common/System/UnicodeString.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,20 @@ void UnicodeString::ensureUniqueBufferOfSize(int numCharsNeeded, Bool preserveDa
7676
{
7777
validate();
7878

79+
const int usableNumChars = numCharsNeeded - 1;
80+
7981
if (m_data &&
8082
m_data->m_refCount == 1 &&
8183
m_data->m_numCharsAllocated >= numCharsNeeded)
8284
{
8385
// no buffer manhandling is needed (it's already large enough, and unique to us)
8486
if (strToCopy)
87+
{
8588
// TheSuperHackers @fix Mauller 04/04/2025 Replace wcscpy with safer memmove as memory regions can overlap when part of string is copied to itself
86-
memmove(m_data->peek(), strToCopy, (wcslen(strToCopy) + 1) * sizeof(WideChar));
89+
DEBUG_ASSERTCRASH(usableNumChars <= wcslen(strToCopy), ("strToCopy is too small"));
90+
memmove(m_data->peek(), strToCopy, usableNumChars * sizeof(WideChar));
91+
m_data->peek()[usableNumChars] = 0;
92+
}
8793
if (strToCat)
8894
wcscat(m_data->peek(), strToCat);
8995
return;
@@ -108,7 +114,11 @@ void UnicodeString::ensureUniqueBufferOfSize(int numCharsNeeded, Bool preserveDa
108114
// do these BEFORE releasing the old buffer, so that self-copies
109115
// or self-cats will work correctly.
110116
if (strToCopy)
111-
wcscpy(newData->peek(), strToCopy);
117+
{
118+
DEBUG_ASSERTCRASH(usableNumChars <= wcslen(strToCopy), ("strToCopy is too small"));
119+
wcsncpy(newData->peek(), strToCopy, usableNumChars);
120+
newData->peek()[usableNumChars] = 0;
121+
}
112122
if (strToCat)
113123
wcscat(newData->peek(), strToCat);
114124

@@ -136,10 +146,21 @@ void UnicodeString::releaseBuffer()
136146
}
137147

138148
// -----------------------------------------------------
139-
UnicodeString::UnicodeString(const WideChar* s) : m_data(0)
149+
UnicodeString::UnicodeString(const WideChar* s) : m_data(NULL)
150+
{
151+
int len = s ? (int)wcslen(s) : 0;
152+
if (len > 0)
153+
{
154+
ensureUniqueBufferOfSize(len + 1, false, s, NULL);
155+
}
156+
validate();
157+
}
158+
159+
// -----------------------------------------------------
160+
UnicodeString::UnicodeString(const WideChar* s, int len) : m_data(NULL)
140161
{
141-
int len = wcslen(s);
142-
if (len)
162+
len = min(s ? (int)wcslen(s) : 0, len);
163+
if (len > 0)
143164
{
144165
ensureUniqueBufferOfSize(len + 1, false, s, NULL);
145166
}
@@ -307,7 +328,7 @@ void UnicodeString::truncateBy(const Int charCount)
307328
const size_t len = wcslen(peek());
308329
if (len > 0)
309330
{
310-
ensureUniqueBufferOfSize(len+1, true, NULL, NULL);
331+
ensureUniqueBufferOfSize(len + 1, true, NULL, NULL);
311332
size_t count = charCount;
312333
if (charCount > len)
313334
{

0 commit comments

Comments
 (0)