2017-04-11 17:39:27 +00:00
|
|
|
/*
|
|
|
|
* This file is part of OpenTTD.
|
|
|
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
|
|
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef STRING_FUNC_EXTRA_H
|
|
|
|
#define STRING_FUNC_EXTRA_H
|
|
|
|
|
|
|
|
#include "string_func.h"
|
|
|
|
#include <string>
|
2021-11-28 19:56:33 +00:00
|
|
|
#include <limits>
|
2017-04-11 17:39:27 +00:00
|
|
|
|
2021-10-18 17:01:27 +00:00
|
|
|
static inline void StrMakeValidInPlace(std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK)
|
2017-04-11 17:39:27 +00:00
|
|
|
{
|
|
|
|
if (str.empty()) return;
|
2021-03-11 01:08:33 +00:00
|
|
|
char *buf = str.data();
|
2021-10-18 17:01:27 +00:00
|
|
|
str.resize(StrMakeValidInPlace(buf, buf + str.size(), settings) - buf);
|
2017-04-11 17:39:27 +00:00
|
|
|
}
|
|
|
|
|
2019-05-18 17:29:22 +00:00
|
|
|
template <typename F>
|
|
|
|
inline void ProcessLineByLine(char *buf, F line_functor)
|
|
|
|
{
|
|
|
|
char *p = buf;
|
|
|
|
char *p2 = buf;
|
|
|
|
/* Print output line by line */
|
|
|
|
for (; *p2 != '\0'; p2++) {
|
|
|
|
if (*p2 == '\n') {
|
|
|
|
*p2 = '\0';
|
|
|
|
line_functor(p);
|
|
|
|
p = p2 + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (p < p2) line_functor(p);
|
|
|
|
}
|
|
|
|
|
2021-11-28 19:56:33 +00:00
|
|
|
/*
|
|
|
|
* Cut down version of std::from_chars, base is fixed at 10.
|
|
|
|
* Returns true on success
|
|
|
|
*/
|
|
|
|
template <typename T>
|
|
|
|
inline bool IntFromChars(const char* first, const char* last, T& value)
|
|
|
|
{
|
|
|
|
static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "T must be an integer");
|
|
|
|
|
|
|
|
bool negative = false;
|
|
|
|
if (std::is_signed<T>::value) {
|
|
|
|
if (first != last && *first == '-') {
|
|
|
|
first++;
|
|
|
|
negative = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
T out = 0;
|
|
|
|
const char * const start = first;
|
|
|
|
while (first != last) {
|
|
|
|
const char c = *first;
|
|
|
|
if (c >= '0' && c <= '9') {
|
|
|
|
#ifdef WITH_OVERFLOW_BUILTINS
|
|
|
|
if (unlikely(__builtin_mul_overflow(out, 10, &out))) return false;
|
|
|
|
if (unlikely(__builtin_add_overflow(out, c - '0', &out))) return false;
|
|
|
|
#else
|
|
|
|
if (unlikely(out > std::numeric_limits<T>::max() / 10)) return false;
|
|
|
|
out *= 10;
|
|
|
|
if (unlikely(out > (std::numeric_limits<T>::max() - (c - '0')))) return false;
|
|
|
|
out += (c - '0');
|
|
|
|
#endif
|
|
|
|
first++;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (start == first) return false;
|
2021-11-29 18:15:56 +00:00
|
|
|
if (std::is_signed<T>::value) {
|
2021-11-30 18:42:40 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(push)
|
|
|
|
#pragma warning(disable: 4146)
|
|
|
|
#endif
|
2021-11-29 18:15:56 +00:00
|
|
|
value = negative ? -out : out;
|
2021-11-30 18:42:40 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(pop)
|
|
|
|
#endif
|
2021-11-29 18:15:56 +00:00
|
|
|
} else {
|
|
|
|
value = out;
|
|
|
|
}
|
2021-11-28 19:56:33 +00:00
|
|
|
return true;
|
|
|
|
}
|
2019-05-18 17:29:22 +00:00
|
|
|
|
2017-04-11 17:39:27 +00:00
|
|
|
#endif /* STRING_FUNC_EXTRA_H */
|