make lexical casts (string -> int/float) faster
This commit is contained in:
parent
40299558dd
commit
090441b80a
@ -160,6 +160,7 @@ SET (star_core_SOURCES
|
||||
StarJsonPatch.cpp
|
||||
StarJsonRpc.cpp
|
||||
StarFormattedJson.cpp
|
||||
StarLexicalCast.cpp
|
||||
StarListener.cpp
|
||||
StarLogging.cpp
|
||||
StarLua.cpp
|
||||
|
13
source/core/StarLexicalCast.cpp
Normal file
13
source/core/StarLexicalCast.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "StarLexicalCast.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
void throwLexicalCastError(std::errc ec, const char* first, const char* last) {
|
||||
StringView str(first, last - first);
|
||||
if (ec == std::errc::invalid_argument)
|
||||
throw BadLexicalCast(strf("Lexical cast failed on '{}' (invalid argument)", str));
|
||||
else
|
||||
throw BadLexicalCast(strf("Lexical cast failed on '{}'", str));
|
||||
}
|
||||
|
||||
}
|
@ -5,40 +5,58 @@
|
||||
#include "StarStringView.hpp"
|
||||
#include "StarMaybe.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <locale>
|
||||
#include "fast_float.h"
|
||||
|
||||
namespace Star {
|
||||
|
||||
STAR_EXCEPTION(BadLexicalCast, StarException);
|
||||
|
||||
// Very simple basic lexical cast using stream input. Always operates in the
|
||||
// "C" locale.
|
||||
void throwLexicalCastError(std::errc ec, const char* first, const char* last);
|
||||
|
||||
template <typename Type>
|
||||
Maybe<Type> maybeLexicalCast(StringView s, std::ios_base::fmtflags flags = std::ios_base::boolalpha) {
|
||||
Type result;
|
||||
std::istringstream stream(std::string(s.utf8()));
|
||||
stream.flags(flags);
|
||||
stream.imbue(std::locale::classic());
|
||||
bool tryLexicalCast(Type& result, const char* first, const char* last) {
|
||||
auto res = fast_float::from_chars(first, last, result);
|
||||
return res.ptr == last && (res.ec == std::errc() || res.ec == std::errc::result_out_of_range);
|
||||
}
|
||||
|
||||
if (!(stream >> result))
|
||||
template <typename Type>
|
||||
bool tryLexicalCast(Type& result, String const& s) {
|
||||
return tryLexicalCast<Type>(s.utf8Ptr(), s.utf8Ptr() + s.utf8Size());
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
bool tryLexicalCast(Type& result, StringView s) {
|
||||
return tryLexicalCast<Type>(s.utf8Ptr(), s.utf8Ptr() + s.utf8Size());
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
Maybe<Type> maybeLexicalCast(const char* first, const char* last) {
|
||||
Type result{};
|
||||
if (tryLexicalCast(result, first, last))
|
||||
return result;
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
// Confirm that we read everything out of the stream
|
||||
char ch;
|
||||
if (stream >> ch)
|
||||
return {};
|
||||
template <typename Type>
|
||||
Maybe<Type> maybeLexicalCast(StringView s) {
|
||||
return maybeLexicalCast<Type>(s.utf8Ptr(), s.utf8Ptr() + s.utf8Size());
|
||||
}
|
||||
|
||||
|
||||
template <typename Type>
|
||||
Type lexicalCast(const char* first, const char* last) {
|
||||
Type result{};
|
||||
auto res = fast_float::from_chars(first, last, result);
|
||||
if ((res.ec != std::errc() && res.ec != std::errc::result_out_of_range) || res.ptr != last)
|
||||
throwLexicalCastError(res.ec, first, last);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
Type lexicalCast(StringView s, std::ios_base::fmtflags flags = std::ios_base::boolalpha) {
|
||||
auto m = maybeLexicalCast<Type>(s, flags);
|
||||
if (m)
|
||||
return m.take();
|
||||
else
|
||||
throw BadLexicalCast(strf("Lexical cast failed on '{}'", s));
|
||||
Type lexicalCast(StringView s) {
|
||||
return lexicalCast<Type>(s.utf8Ptr(), s.utf8Ptr() + s.utf8Size());
|
||||
}
|
||||
|
||||
}
|
||||
|
1
source/extern/CMakeLists.txt
vendored
1
source/extern/CMakeLists.txt
vendored
@ -15,6 +15,7 @@ SET (star_extern_HEADERS
|
||||
fmt/printf.h
|
||||
fmt/ranges.h
|
||||
fmt/std.h
|
||||
fast_float.h
|
||||
lauxlib.h
|
||||
lua.h
|
||||
lua.hpp
|
||||
|
3913
source/extern/fast_float.h
vendored
Normal file
3913
source/extern/fast_float.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -262,7 +262,7 @@ String CommandProcessor::setTileProtection(ConnectionId connectionId, String con
|
||||
return "Not enough arguments to /settileprotection. Use /settileprotection <dungeonId> <protected>";
|
||||
|
||||
try {
|
||||
bool isProtected = lexicalCast<bool>(arguments.takeLast());
|
||||
bool isProtected = Json::parse(arguments.takeLast()).toBool();
|
||||
List<DungeonId> dungeonIds;
|
||||
for (auto& banana : arguments) {
|
||||
auto slices = banana.split("..");
|
||||
|
Loading…
x
Reference in New Issue
Block a user