mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
[Utility] Add std::string_view overloads for std::from_chars (#2392)
* Add std::string_view overloads for std::from_chars std::from_chars floating point support is still pour, so we provide some fall backs. These fall backs currently lack error handling. (since GCC 11 and MSVC 2019 16.4 FP support is added, clang with libc++ still doesn't support FP) GCC's floating point support is still rather pour (performance) and probably shouldn't be used, but we have support to if people want to now. Probably need more test cases ... * Fix issue with std::chars_format define lacking My test case for lacking FP support was clang with libc++ which defined this enum anyways.
This commit is contained in:
parent
786a7e2169
commit
edda5ef811
@ -1,3 +1,4 @@
|
||||
// for folly stuff
|
||||
/*
|
||||
* Copyright 2013 Facebook, Inc.
|
||||
*
|
||||
@ -13,6 +14,24 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// for our stuff
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2022 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program 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 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "strings.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
// for folly stuff
|
||||
/*
|
||||
* Copyright 2013 Facebook, Inc.
|
||||
*
|
||||
@ -13,14 +14,35 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// for our stuff
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2022 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program 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 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _STRINGUTIL_H_
|
||||
#define _STRINGUTIL_H_
|
||||
|
||||
#include <charconv>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <cstdarg>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef _WIN32
|
||||
// this doesn't appear to affect linux-based systems..need feedback for _WIN64
|
||||
@ -36,6 +58,29 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace detail {
|
||||
// template magic to check if std::from_chars floating point functions exist
|
||||
template <typename T, typename = void>
|
||||
struct has_from_chars_float : std::false_type { };
|
||||
|
||||
// basically it "uses" this template if they do exist because reasons
|
||||
template <typename T>
|
||||
struct has_from_chars_float < T,
|
||||
std::void_t<decltype(std::from_chars(std::declval<const char *>(), std::declval<const char *>(),
|
||||
std::declval<T &>()))>> : std::true_type { };
|
||||
}; // namespace detail
|
||||
|
||||
namespace EQ {
|
||||
// lame -- older GCC's didn't define this, clang's libc++ however does, even though they lack FP support
|
||||
#if defined(__GNUC__) && (__GNUC__ < 11) && !defined(__clang__)
|
||||
enum class chars_format {
|
||||
scientific = 1, fixed = 2, hex = 4, general = fixed | scientific
|
||||
};
|
||||
#else
|
||||
using chars_format = std::chars_format;
|
||||
#endif
|
||||
}; // namespace EQ
|
||||
|
||||
class Strings {
|
||||
public:
|
||||
static bool Contains(std::vector<std::string> container, std::string element);
|
||||
@ -79,6 +124,45 @@ public:
|
||||
output.resize(output.size() - glue.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
// basic string_view overloads that just use std stuff since they work!
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_floating_point_v<T> && detail::has_from_chars_float<T>::value, std::from_chars_result>
|
||||
static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general)
|
||||
{
|
||||
return std::from_chars(str.data(), str.data() + str.size(), value, fmt);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_integral_v<T>, std::from_chars_result>
|
||||
static from_chars(std::string_view str, T& value, int base = 10)
|
||||
{
|
||||
return std::from_chars(str.data(), str.data() + str.size(), value, base);
|
||||
}
|
||||
|
||||
// fallback versions of floating point in case they're not implemented
|
||||
// TODO: add error handling ...
|
||||
// This does have to allocate since from_chars doesn't need a null terminated string and neither does string_view
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_floating_point_v<T> && !detail::has_from_chars_float<T>::value && std::is_same_v<T, float>, std::from_chars_result>
|
||||
static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general)
|
||||
{
|
||||
std::from_chars_result res{};
|
||||
std::string tmp_str(str.data(), str.size());
|
||||
value = strtof(tmp_str.data(), nullptr);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_floating_point_v<T> && !detail::has_from_chars_float<T>::value && std::is_same_v<T, double>, std::from_chars_result>
|
||||
static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general)
|
||||
{
|
||||
std::from_chars_result res{};
|
||||
std::string tmp_str(str.data(), str.size());
|
||||
value = strtod(tmp_str.data(), nullptr);
|
||||
return res;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const std::string StringFormat(const char *format, ...);
|
||||
|
||||
@ -30,6 +30,7 @@ public:
|
||||
TEST_ADD(StringUtilTest::EscapeStringTest);
|
||||
TEST_ADD(StringUtilTest::SearchDeliminatedStringTest);
|
||||
TEST_ADD(StringUtilTest::SplitStringTest);
|
||||
TEST_ADD(StringUtilTest::FromCharsTest);
|
||||
}
|
||||
|
||||
~StringUtilTest() {
|
||||
@ -100,6 +101,21 @@ public:
|
||||
TEST_ASSERT(v[1] == "456");
|
||||
TEST_ASSERT(v[2] == "789");
|
||||
}
|
||||
|
||||
void FromCharsTest() {
|
||||
char int_chars[] = "123";
|
||||
int int_value = 0;
|
||||
|
||||
char float_chars[] = "3.14";
|
||||
float float_value = 0.0f;
|
||||
|
||||
Strings::from_chars(int_chars, int_value);
|
||||
TEST_ASSERT(int_value == 123);
|
||||
|
||||
Strings::from_chars(float_chars, float_value);
|
||||
TEST_ASSERT(float_value == 3.14f);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user