COMMON: Add strcpy_s and strcat_s
These functions will issue warnings and truncate strings. It's like strlcpy and strlcat but noisier. There are also versions automatically determining size based on the destination array size. This raises a compilation error when the size cannot be determined by the compiler.
This commit is contained in:
parent
f1eb05c898
commit
f8c25e2374
2 changed files with 142 additions and 0 deletions
|
@ -736,6 +736,88 @@ String tag2string(uint32 tag, bool nonPrintable) {
|
|||
|
||||
#endif
|
||||
|
||||
// When str.cpp is used in devtools warning is not defined
|
||||
#ifdef SCUMMVM_UTIL
|
||||
#define warning(msg, ...)
|
||||
#endif
|
||||
|
||||
// Our simple implementation of strcpy_s and strcat_s
|
||||
// We don't check for overlapping strings and we issue warnings instead of erroring out
|
||||
void strcpy_s(char *dst, size_t size, const char *src) {
|
||||
if (!dst) {
|
||||
warning("%s: dst is nullptr", __func__);
|
||||
return;
|
||||
}
|
||||
if (!src) {
|
||||
warning("%s: src is nullptr", __func__);
|
||||
return;
|
||||
}
|
||||
if (!size) {
|
||||
warning("%s: size is zero", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dst == src) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy over (size - 1) bytes at max.
|
||||
while (size != 0) {
|
||||
*dst = *src;
|
||||
if (*dst == '\0') {
|
||||
return;
|
||||
}
|
||||
++dst;
|
||||
++src;
|
||||
--size;
|
||||
}
|
||||
|
||||
warning("%s: truncating string", __func__);
|
||||
dst[-1] = '\0';
|
||||
}
|
||||
|
||||
void strcat_s(char *dst, size_t size, const char *src) {
|
||||
if (!dst) {
|
||||
warning("%s: dst is nullptr", __func__);
|
||||
return;
|
||||
}
|
||||
if (!src) {
|
||||
warning("%s: src is nullptr", __func__);
|
||||
return;
|
||||
}
|
||||
if (!size) {
|
||||
warning("%s: size is zero", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
// Search the end of the destination, but do not
|
||||
// move past the terminating zero.
|
||||
while(*dst != '\0') {
|
||||
++dst;
|
||||
--size;
|
||||
if (!size) {
|
||||
warning("%s: dst is unterminated", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy over all of the source that fits
|
||||
// the destination buffer.
|
||||
while (size != 0) {
|
||||
*dst = *src;
|
||||
if (*dst == '\0') {
|
||||
return;
|
||||
}
|
||||
++dst;
|
||||
++src;
|
||||
--size;
|
||||
}
|
||||
|
||||
warning("%s: truncating string", __func__);
|
||||
dst[-1] = '\0';
|
||||
}
|
||||
|
||||
size_t strlcpy(char *dst, const char *src, size_t size) {
|
||||
// Our backup of the source's start, we need this
|
||||
// to calculate the source's length.
|
||||
|
|
60
common/str.h
60
common/str.h
|
@ -371,6 +371,66 @@ void replace(Common::String &source, const Common::String &what, const Common::S
|
|||
*/
|
||||
String tag2string(uint32 tag, bool nonPrintable = false);
|
||||
|
||||
/**
|
||||
* Copy up to size - 1 characters from src to dst and also zero terminate the
|
||||
* result. Note that src must be a zero terminated string.
|
||||
*
|
||||
* @note This is modeled after strcpy_s from C11 but simplified by using warning
|
||||
* instead of erroring out
|
||||
*
|
||||
* @param dst The destination buffer.
|
||||
* @param size The size of the destination buffer.
|
||||
* @param src The source string.
|
||||
*/
|
||||
void strcpy_s(char *dst, size_t size, const char *src);
|
||||
|
||||
/**
|
||||
* Copy up to N - 1 characters from src to dst and also zero terminate the
|
||||
* result. Note that src must be a zero terminated string.
|
||||
*
|
||||
* @note This is modeled after strcpy_s from C11 but simplified by using warning
|
||||
* instead of erroring out
|
||||
*
|
||||
* @param dst The destination buffer as a reference to a constant size array.
|
||||
* @param src The source string.
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
FORCEINLINE void strcpy_s(T (&dst)[N], const char *src) {
|
||||
STATIC_ASSERT(sizeof(T) == sizeof(char), T_is_not_compatible_with_char);
|
||||
strcpy_s((char *)dst, N, src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the string src to the string dst. Note that both src and dst must be
|
||||
* zero terminated. The result will be zero terminated. At most
|
||||
* "size - strlen(dst) - 1" bytes will be appended.
|
||||
*
|
||||
* @note This is modeled after strcpy_s from C11 but simplified by using warning
|
||||
* instead of erroring out
|
||||
*
|
||||
* @param dst The string the source string should be appended to.
|
||||
* @param size The (total) size of the destination buffer.
|
||||
* @param src The source string.
|
||||
*/
|
||||
void strcat_s(char *dst, size_t size, const char *src);
|
||||
|
||||
/**
|
||||
* Append the string src to the string dst. Note that both src and dst must be
|
||||
* zero terminated. The result will be zero terminated. At most
|
||||
* "N - strlen(dst) - 1" bytes will be appended.
|
||||
*
|
||||
* @note This is modeled after strcat_s from C11 but simplified by using warning
|
||||
* instead of erroring out
|
||||
*
|
||||
* @param dst The string the source string should be appended to as a reference to a constant size array.
|
||||
* @param src The source string.
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
FORCEINLINE void strcat_s(T (&dst)[N], const char *src) {
|
||||
STATIC_ASSERT(sizeof(T) == sizeof(char), T_is_not_compatible_with_char);
|
||||
strcat_s((char *)dst, N, src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy up to size - 1 characters from src to dst and also zero terminate the
|
||||
* result. Note that src must be a zero terminated string.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue