mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Use std::span/std::string_view for strecpy. (#12848)
This avoids needing to manually pass the last character of the destination buffer, and allows use of standard library functions.pull/12849/head
parent
86e32631d7
commit
56b0eac2e9
|
@ -108,11 +108,11 @@ void FileStringReader::HandlePragma(char *str)
|
||||||
if (!memcmp(str, "id ", 3)) {
|
if (!memcmp(str, "id ", 3)) {
|
||||||
this->data.next_string_id = std::strtoul(str + 3, nullptr, 0);
|
this->data.next_string_id = std::strtoul(str + 3, nullptr, 0);
|
||||||
} else if (!memcmp(str, "name ", 5)) {
|
} else if (!memcmp(str, "name ", 5)) {
|
||||||
strecpy(_lang.name, str + 5, lastof(_lang.name));
|
strecpy(_lang.name, str + 5);
|
||||||
} else if (!memcmp(str, "ownname ", 8)) {
|
} else if (!memcmp(str, "ownname ", 8)) {
|
||||||
strecpy(_lang.own_name, str + 8, lastof(_lang.own_name));
|
strecpy(_lang.own_name, str + 8);
|
||||||
} else if (!memcmp(str, "isocode ", 8)) {
|
} else if (!memcmp(str, "isocode ", 8)) {
|
||||||
strecpy(_lang.isocode, str + 8, lastof(_lang.isocode));
|
strecpy(_lang.isocode, str + 8);
|
||||||
} else if (!memcmp(str, "textdir ", 8)) {
|
} else if (!memcmp(str, "textdir ", 8)) {
|
||||||
if (!memcmp(str + 8, "ltr", 3)) {
|
if (!memcmp(str + 8, "ltr", 3)) {
|
||||||
_lang.text_dir = TD_LTR;
|
_lang.text_dir = TD_LTR;
|
||||||
|
@ -123,13 +123,13 @@ void FileStringReader::HandlePragma(char *str)
|
||||||
}
|
}
|
||||||
} else if (!memcmp(str, "digitsep ", 9)) {
|
} else if (!memcmp(str, "digitsep ", 9)) {
|
||||||
str += 9;
|
str += 9;
|
||||||
strecpy(_lang.digit_group_separator, strcmp(str, "{NBSP}") == 0 ? NBSP : str, lastof(_lang.digit_group_separator));
|
strecpy(_lang.digit_group_separator, strcmp(str, "{NBSP}") == 0 ? NBSP : str);
|
||||||
} else if (!memcmp(str, "digitsepcur ", 12)) {
|
} else if (!memcmp(str, "digitsepcur ", 12)) {
|
||||||
str += 12;
|
str += 12;
|
||||||
strecpy(_lang.digit_group_separator_currency, strcmp(str, "{NBSP}") == 0 ? NBSP : str, lastof(_lang.digit_group_separator_currency));
|
strecpy(_lang.digit_group_separator_currency, strcmp(str, "{NBSP}") == 0 ? NBSP : str);
|
||||||
} else if (!memcmp(str, "decimalsep ", 11)) {
|
} else if (!memcmp(str, "decimalsep ", 11)) {
|
||||||
str += 11;
|
str += 11;
|
||||||
strecpy(_lang.digit_decimal_separator, strcmp(str, "{NBSP}") == 0 ? NBSP : str, lastof(_lang.digit_decimal_separator));
|
strecpy(_lang.digit_decimal_separator, strcmp(str, "{NBSP}") == 0 ? NBSP : str);
|
||||||
} else if (!memcmp(str, "winlangid ", 10)) {
|
} else if (!memcmp(str, "winlangid ", 10)) {
|
||||||
const char *buf = str + 10;
|
const char *buf = str + 10;
|
||||||
long langid = std::strtol(buf, nullptr, 16);
|
long langid = std::strtol(buf, nullptr, 16);
|
||||||
|
@ -153,7 +153,7 @@ void FileStringReader::HandlePragma(char *str)
|
||||||
|
|
||||||
if (s == nullptr) break;
|
if (s == nullptr) break;
|
||||||
if (_lang.num_genders >= MAX_NUM_GENDERS) FatalError("Too many genders, max {}", MAX_NUM_GENDERS);
|
if (_lang.num_genders >= MAX_NUM_GENDERS) FatalError("Too many genders, max {}", MAX_NUM_GENDERS);
|
||||||
strecpy(_lang.genders[_lang.num_genders], s, lastof(_lang.genders[_lang.num_genders]));
|
strecpy(_lang.genders[_lang.num_genders], s);
|
||||||
_lang.num_genders++;
|
_lang.num_genders++;
|
||||||
}
|
}
|
||||||
} else if (!memcmp(str, "case ", 5)) {
|
} else if (!memcmp(str, "case ", 5)) {
|
||||||
|
@ -165,7 +165,7 @@ void FileStringReader::HandlePragma(char *str)
|
||||||
|
|
||||||
if (s == nullptr) break;
|
if (s == nullptr) break;
|
||||||
if (_lang.num_cases >= MAX_NUM_CASES) FatalError("Too many cases, max {}", MAX_NUM_CASES);
|
if (_lang.num_cases >= MAX_NUM_CASES) FatalError("Too many cases, max {}", MAX_NUM_CASES);
|
||||||
strecpy(_lang.cases[_lang.num_cases], s, lastof(_lang.cases[_lang.num_cases]));
|
strecpy(_lang.cases[_lang.num_cases], s);
|
||||||
_lang.num_cases++;
|
_lang.num_cases++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -756,9 +756,9 @@ void StringReader::ParseFile()
|
||||||
|
|
||||||
/* For each new file we parse, reset the genders, and language codes. */
|
/* For each new file we parse, reset the genders, and language codes. */
|
||||||
MemSetT(&_lang, 0);
|
MemSetT(&_lang, 0);
|
||||||
strecpy(_lang.digit_group_separator, ",", lastof(_lang.digit_group_separator));
|
strecpy(_lang.digit_group_separator, ",");
|
||||||
strecpy(_lang.digit_group_separator_currency, ",", lastof(_lang.digit_group_separator_currency));
|
strecpy(_lang.digit_group_separator_currency, ",");
|
||||||
strecpy(_lang.digit_decimal_separator, ".", lastof(_lang.digit_decimal_separator));
|
strecpy(_lang.digit_decimal_separator, ".");
|
||||||
|
|
||||||
_cur_line = 1;
|
_cur_line = 1;
|
||||||
while (this->data.next_string_id < this->data.max_strings) {
|
while (this->data.next_string_id < this->data.max_strings) {
|
||||||
|
|
|
@ -50,34 +50,27 @@
|
||||||
* Copies characters from one buffer to another.
|
* Copies characters from one buffer to another.
|
||||||
*
|
*
|
||||||
* Copies the source string to the destination buffer with respect of the
|
* Copies the source string to the destination buffer with respect of the
|
||||||
* terminating null-character and the last pointer to the last element in
|
* terminating null-character and the size of the destination buffer.
|
||||||
* the destination buffer. If the last pointer is set to nullptr no boundary
|
|
||||||
* check is performed.
|
|
||||||
*
|
*
|
||||||
* @note usage: strecpy(dst, src, lastof(dst));
|
* @note usage: strecpy(dst, src);
|
||||||
* @note lastof() applies only to fixed size arrays
|
|
||||||
*
|
*
|
||||||
* @param dst The destination buffer
|
* @param dst The destination buffer
|
||||||
* @param src The buffer containing the string to copy
|
* @param src The buffer containing the string to copy
|
||||||
* @param last The pointer to the last element of the destination buffer
|
|
||||||
* @return The pointer to the terminating null-character in the destination buffer
|
|
||||||
*/
|
*/
|
||||||
char *strecpy(char *dst, const char *src, const char *last)
|
void strecpy(std::span<char> dst, std::string_view src)
|
||||||
{
|
{
|
||||||
assert(dst <= last);
|
/* Ensure source string fits with NUL terminator; dst must be at least 1 character longer than src. */
|
||||||
while (dst != last && *src != '\0') {
|
if (std::empty(dst) || std::size(src) >= std::size(dst) - 1U) {
|
||||||
*dst++ = *src++;
|
|
||||||
}
|
|
||||||
*dst = '\0';
|
|
||||||
|
|
||||||
if (dst == last && *src != '\0') {
|
|
||||||
#if defined(STRGEN) || defined(SETTINGSGEN)
|
#if defined(STRGEN) || defined(SETTINGSGEN)
|
||||||
FatalError("String too long for destination buffer");
|
FatalError("String too long for destination buffer");
|
||||||
#else /* STRGEN || SETTINGSGEN */
|
#else /* STRGEN || SETTINGSGEN */
|
||||||
Debug(misc, 0, "String too long for destination buffer");
|
Debug(misc, 0, "String too long for destination buffer");
|
||||||
|
src = src.substr(0, std::size(dst) - 1U);
|
||||||
#endif /* STRGEN || SETTINGSGEN */
|
#endif /* STRGEN || SETTINGSGEN */
|
||||||
}
|
}
|
||||||
return dst;
|
|
||||||
|
auto it = std::copy(std::begin(src), std::end(src), std::begin(dst));
|
||||||
|
*it = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "core/bitmath_func.hpp"
|
#include "core/bitmath_func.hpp"
|
||||||
#include "string_type.h"
|
#include "string_type.h"
|
||||||
|
|
||||||
char *strecpy(char *dst, const char *src, const char *last) NOACCESS(3);
|
void strecpy(std::span<char> dst, std::string_view src);
|
||||||
|
|
||||||
std::string FormatArrayAsHex(std::span<const uint8_t> data);
|
std::string FormatArrayAsHex(std::span<const uint8_t> data);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue