Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2024-09-16 23:02:22 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2024-09-16 23:02:22 +1000
commit090441b80aed3c7df45ff1a6d40ed56ee895ad28 (patch)
tree3a4a8137941aa60f0674d9ed9308a45266c96e4e /source/core
parent40299558dd4585adb6066cdade5703be7cf10b76 (diff)
make lexical casts (string -> int/float) faster
Diffstat (limited to 'source/core')
-rw-r--r--source/core/CMakeLists.txt1
-rw-r--r--source/core/StarLexicalCast.cpp13
-rw-r--r--source/core/StarLexicalCast.hpp58
3 files changed, 52 insertions, 20 deletions
diff --git a/source/core/CMakeLists.txt b/source/core/CMakeLists.txt
index 2f0c858..fa1d246 100644
--- a/source/core/CMakeLists.txt
+++ b/source/core/CMakeLists.txt
@@ -160,6 +160,7 @@ SET (star_core_SOURCES
StarJsonPatch.cpp
StarJsonRpc.cpp
StarFormattedJson.cpp
+ StarLexicalCast.cpp
StarListener.cpp
StarLogging.cpp
StarLua.cpp
diff --git a/source/core/StarLexicalCast.cpp b/source/core/StarLexicalCast.cpp
new file mode 100644
index 0000000..1387b2e
--- /dev/null
+++ b/source/core/StarLexicalCast.cpp
@@ -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));
+}
+
+} \ No newline at end of file
diff --git a/source/core/StarLexicalCast.hpp b/source/core/StarLexicalCast.hpp
index 9c671e9..13c0521 100644
--- a/source/core/StarLexicalCast.hpp
+++ b/source/core/StarLexicalCast.hpp
@@ -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))
- return {};
+template <typename Type>
+bool tryLexicalCast(Type& result, String const& s) {
+ return tryLexicalCast<Type>(s.utf8Ptr(), s.utf8Ptr() + s.utf8Size());
+}
- // Confirm that we read everything out of the stream
- char ch;
- if (stream >> ch)
+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 {};
+}
+
+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());
}
}