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
|
StarJsonPatch.cpp
|
||||||
StarJsonRpc.cpp
|
StarJsonRpc.cpp
|
||||||
StarFormattedJson.cpp
|
StarFormattedJson.cpp
|
||||||
|
StarLexicalCast.cpp
|
||||||
StarListener.cpp
|
StarListener.cpp
|
||||||
StarLogging.cpp
|
StarLogging.cpp
|
||||||
StarLua.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 "StarStringView.hpp"
|
||||||
#include "StarMaybe.hpp"
|
#include "StarMaybe.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include "fast_float.h"
|
||||||
#include <locale>
|
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
STAR_EXCEPTION(BadLexicalCast, StarException);
|
STAR_EXCEPTION(BadLexicalCast, StarException);
|
||||||
|
|
||||||
// Very simple basic lexical cast using stream input. Always operates in the
|
void throwLexicalCastError(std::errc ec, const char* first, const char* last);
|
||||||
// "C" locale.
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
Maybe<Type> maybeLexicalCast(StringView s, std::ios_base::fmtflags flags = std::ios_base::boolalpha) {
|
bool tryLexicalCast(Type& result, const char* first, const char* last) {
|
||||||
Type result;
|
auto res = fast_float::from_chars(first, last, result);
|
||||||
std::istringstream stream(std::string(s.utf8()));
|
return res.ptr == last && (res.ec == std::errc() || res.ec == std::errc::result_out_of_range);
|
||||||
stream.flags(flags);
|
}
|
||||||
stream.imbue(std::locale::classic());
|
|
||||||
|
|
||||||
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 {};
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
// Confirm that we read everything out of the stream
|
template <typename Type>
|
||||||
char ch;
|
Maybe<Type> maybeLexicalCast(StringView s) {
|
||||||
if (stream >> ch)
|
return maybeLexicalCast<Type>(s.utf8Ptr(), s.utf8Ptr() + s.utf8Size());
|
||||||
return {};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
Type lexicalCast(StringView s, std::ios_base::fmtflags flags = std::ios_base::boolalpha) {
|
Type lexicalCast(StringView s) {
|
||||||
auto m = maybeLexicalCast<Type>(s, flags);
|
return lexicalCast<Type>(s.utf8Ptr(), s.utf8Ptr() + s.utf8Size());
|
||||||
if (m)
|
|
||||||
return m.take();
|
|
||||||
else
|
|
||||||
throw BadLexicalCast(strf("Lexical cast failed on '{}'", s));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
1
source/extern/CMakeLists.txt
vendored
1
source/extern/CMakeLists.txt
vendored
@ -15,6 +15,7 @@ SET (star_extern_HEADERS
|
|||||||
fmt/printf.h
|
fmt/printf.h
|
||||||
fmt/ranges.h
|
fmt/ranges.h
|
||||||
fmt/std.h
|
fmt/std.h
|
||||||
|
fast_float.h
|
||||||
lauxlib.h
|
lauxlib.h
|
||||||
lua.h
|
lua.h
|
||||||
lua.hpp
|
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>";
|
return "Not enough arguments to /settileprotection. Use /settileprotection <dungeonId> <protected>";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
bool isProtected = lexicalCast<bool>(arguments.takeLast());
|
bool isProtected = Json::parse(arguments.takeLast()).toBool();
|
||||||
List<DungeonId> dungeonIds;
|
List<DungeonId> dungeonIds;
|
||||||
for (auto& banana : arguments) {
|
for (auto& banana : arguments) {
|
||||||
auto slices = banana.split("..");
|
auto slices = banana.split("..");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user