Skip to content

Commit 77feed8

Browse files
authored
chore(string): Add strlcpy, strlcat family functions (#1477)
Use them instead of strcpy and strncpy functions
1 parent 9c87f92 commit 77feed8

File tree

4 files changed

+194
-0
lines changed

4 files changed

+194
-0
lines changed

Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ set(WWLIB_SRC
108108
stimer.h
109109
straw.cpp
110110
STRAW.H
111+
stringex.h
111112
strtok_r.cpp
112113
strtok_r.h
113114
#swap.h

Core/Libraries/Source/WWVegas/WWLib/WWCommon.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#pragma once
2020

21+
#include <stringex.h>
22+
2123
#if defined(_MSC_VER) && _MSC_VER < 1300
2224
typedef unsigned MemValueType;
2325
#else

Core/Libraries/Source/WWVegas/WWLib/bittype.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,11 @@ typedef const char * LPCSTR;
6363
typedef unsigned int UINT;
6464
typedef unsigned long ULONG;
6565

66+
#if defined(_MSC_VER) && _MSC_VER < 1300
67+
#ifndef _WCHAR_T_DEFINED
68+
typedef unsigned short wchar_t;
69+
#define _WCHAR_T_DEFINED
70+
#endif
71+
#endif
72+
6673
#endif //BITTYPE_H
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
** Command & Conquer Generals Zero Hour(tm)
3+
** Copyright 2025 TheSuperHackers
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+
#pragma once
20+
21+
#include "bittype.h"
22+
#include <string.h>
23+
24+
25+
// Declaration
26+
27+
template<typename T> size_t strlen_t(const T *str);
28+
template<typename T> size_t strnlen_t(const T *str, size_t maxlen);
29+
30+
#if defined(_MSC_VER) && _MSC_VER < 1300
31+
size_t strnlen(const char *str, size_t maxlen);
32+
size_t wcsnlen(const wchar_t *str, size_t maxlen);
33+
#endif
34+
35+
template<typename T> size_t strlcpy_t(T *dst, const T *src, size_t dstsize);
36+
template<typename T> size_t strlcat_t(T *dst, const T *src, size_t dstsize);
37+
38+
size_t strlcpy(char *dst, const char *src, size_t dstsize);
39+
size_t strlcat(char *dst, const char *src, size_t dstsize);
40+
size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t dstsize);
41+
size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t dstsize);
42+
43+
template<typename T> size_t strlmove_t(T *dst, const T *src, size_t dstsize);
44+
template<typename T> size_t strlmcat_t(T *dst, const T *src, size_t dstsize);
45+
46+
size_t strlmove(char *dst, const char *src, size_t dstsize);
47+
size_t strlmcat(char *dst, const char *src, size_t dstsize);
48+
size_t wcslmove(wchar_t *dst, const wchar_t *src, size_t dstsize);
49+
size_t wcslmcat(wchar_t *dst, const wchar_t *src, size_t dstsize);
50+
51+
#if !(defined(_MSC_VER) && _MSC_VER < 1300)
52+
template<size_t Size> size_t strlcpy_t(char (&dst)[Size], const char *src);
53+
template<size_t Size> size_t strlcat_t(char (&dst)[Size], const char *src);
54+
template<size_t Size> size_t strlmove_t(char (&dst)[Size], const char *src);
55+
template<size_t Size> size_t strlmcat_t(char (&dst)[Size], const char *src);
56+
#endif
57+
58+
59+
// Implementation
60+
61+
// Templated strlen.
62+
// Returns the number of characters until the first zero character.
63+
template<typename T> size_t strlen_t(const T *str)
64+
{
65+
const T* begin = str;
66+
while (*str)
67+
++str;
68+
return static_cast<size_t>(str - begin);
69+
}
70+
71+
// Templated strlen.
72+
// Returns the number of characters until the first zero character or when maxlen is reached.
73+
template<typename T> size_t strnlen_t(const T *str, size_t maxlen)
74+
{
75+
const T* begin = str;
76+
const T* end = str + maxlen;
77+
while (str < end && *str)
78+
++str;
79+
return static_cast<size_t>(str - begin);
80+
}
81+
82+
#if defined(_MSC_VER) && _MSC_VER < 1300
83+
inline size_t strnlen(const char *str, size_t maxlen) { return strnlen_t(str, maxlen); }
84+
inline size_t wcsnlen(const wchar_t *str, size_t maxlen) { return strnlen_t(str, maxlen); }
85+
#endif
86+
87+
// Templated strlcpy. Prefer using this over strncpy.
88+
// Copies src into dst until dstsize minus one. Always null terminates.
89+
// Returns the length of src, excluding the null terminator.
90+
template<typename T> size_t strlcpy_t(T *dst, const T *src, size_t dstsize)
91+
{
92+
const size_t srclen = strlen_t(src);
93+
if (dstsize != 0)
94+
{
95+
size_t copylen = (srclen >= dstsize) ? dstsize - 1 : srclen;
96+
memcpy(dst, src, copylen * sizeof(T));
97+
dst[copylen] = T(0);
98+
}
99+
return srclen; // length tried to create
100+
}
101+
102+
// Templated strlcat. Prefer using this over strncpy.
103+
// Appends src into dst until dstsize minus one. Always null terminates.
104+
// Returns the length of dst + src, excluding the null terminator.
105+
template<typename T> size_t strlcat_t(T *dst, const T *src, size_t dstsize)
106+
{
107+
const size_t dstlen = strnlen_t(dst, dstsize);
108+
const size_t srclen = strlen_t(src);
109+
if (dstlen == dstsize)
110+
{
111+
return dstsize + srclen; // no space to append
112+
}
113+
size_t copylen = dstsize - dstlen - 1;
114+
if (copylen > srclen)
115+
{
116+
copylen = srclen;
117+
}
118+
if (copylen > 0)
119+
{
120+
memcpy(dst + dstlen, src, copylen * sizeof(T));
121+
dst[dstlen + copylen] = T(0);
122+
}
123+
return dstlen + srclen; // length tried to create
124+
}
125+
126+
#ifndef HAVE_STRLCPY
127+
inline size_t strlcpy(char *dst, const char *src, size_t dstsize) { return strlcpy_t(dst, src, dstsize); }
128+
#endif
129+
#ifndef HAVE_STRLCAT
130+
inline size_t strlcat(char *dst, const char *src, size_t dstsize) { return strlcat_t(dst, src, dstsize); }
131+
#endif
132+
inline size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t dstsize) { return strlcpy_t(dst, src, dstsize); }
133+
inline size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t dstsize) { return strlcat_t(dst, src, dstsize); }
134+
135+
// Templated strlmove. Prefer using this over strlcpy if dst and src overlap.
136+
// Moves src into dst until dstsize minus one. Always null terminates.
137+
// Returns the length of src, excluding the null terminator.
138+
template<typename T> size_t strlmove_t(T *dst, const T *src, size_t dstsize)
139+
{
140+
const size_t srclen = strlen_t(src);
141+
if (dstsize > 0)
142+
{
143+
size_t copylen = (srclen >= dstsize) ? dstsize - 1 : srclen;
144+
memmove(dst, src, copylen * sizeof(T));
145+
dst[copylen] = T(0);
146+
}
147+
return srclen; // length tried to create
148+
}
149+
150+
// Templated strlmcat. Prefer using this over strlcat if dst and src overlap.
151+
// Appends src into dst until dstsize minus one. Always null terminates.
152+
// Returns the length of dst + src, excluding the null terminator.
153+
template<typename T> size_t strlmcat_t(T *dst, const T *src, size_t dstsize)
154+
{
155+
const size_t dstlen = strnlen_t(dst, dstsize);
156+
const size_t srclen = strlen_t(src);
157+
if (dstlen == dstsize)
158+
{
159+
return dstsize + srclen; // no space to append
160+
}
161+
size_t copylen = dstsize - dstlen - 1;
162+
if (copylen > srclen)
163+
{
164+
copylen = srclen;
165+
}
166+
if (copylen > 0)
167+
{
168+
memmove(dst + dstlen, src, copylen * sizeof(T));
169+
dst[dstlen + copylen] = T(0);
170+
}
171+
return dstlen + srclen; // length tried to create
172+
}
173+
174+
inline size_t strlmove(char *dst, const char *src, size_t dstsize) { return strlmove_t(dst, src, dstsize); }
175+
inline size_t strlmcat(char *dst, const char *src, size_t dstsize) { return strlmcat_t(dst, src, dstsize); }
176+
inline size_t wcslmove(wchar_t *dst, const wchar_t *src, size_t dstsize) { return strlmove_t(dst, src, dstsize); }
177+
inline size_t wcslmcat(wchar_t *dst, const wchar_t *src, size_t dstsize) { return strlmcat_t(dst, src, dstsize); }
178+
179+
#if !(defined(_MSC_VER) && _MSC_VER < 1300)
180+
template<size_t Size> size_t strlcpy_t(char (&dst)[Size], const char *src) { return strlcpy_t(dst, src, Size); }
181+
template<size_t Size> size_t strlcat_t(char (&dst)[Size], const char *src) { return strlcat_t(dst, src, Size); }
182+
template<size_t Size> size_t strlmove_t(char (&dst)[Size], const char *src) { return strlmove_t(dst, src, Size); }
183+
template<size_t Size> size_t strlmcat_t(char (&dst)[Size], const char *src) { return strlmcat_t(dst, src, Size); }
184+
#endif

0 commit comments

Comments
 (0)