Merge branch 'main' into release-0.32

This commit is contained in:
MihailRis 2026-09-20 22:41:13 +03:00
commit f3131b058c
4 changed files with 44 additions and 19 deletions

View file

@ -1,3 +1,9 @@
debug.log("file extension")
asserts.equals(nil, file.ext("config:test"))
asserts.equals("cfg", file.ext("config:test.cfg"))
asserts.equals("gz", file.ext("config:test.cfg.gz"))
asserts.equals("config:test.cfg", file.remove_ext("config:test.cfg.gz"))
debug.log("check initial state") debug.log("check initial state")
assert(file.exists("config:")) assert(file.exists("config:"))

View file

@ -8,7 +8,7 @@ function file.stem(path)
end end
function file.ext(path) function file.ext(path)
return path:match("%.([^:/\\]+)$") return path:match("[^:/\\.]%.([^.:/\\]+)$")
end end
function file.prefix(path) function file.prefix(path)
@ -24,7 +24,11 @@ function file.parent(path)
end end
function file.remove_ext(path) function file.remove_ext(path)
return string.format("%s/%s", file.parent(path), file.stem(path)) local ext = file.ext(path)
if not ext then
return path
end
return path:sub(1, -#ext - 2)
end end
function file.path(path) function file.path(path)

View file

@ -1,9 +1,11 @@
#include "stringutil.hpp" #include "stringutil.hpp"
#include <algorithm> #include <algorithm>
#include <cmath> #include <charconv>
#include <iomanip> #include <cctype>
#include <locale> #include <cmath>
#include <iomanip>
#include <locale>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
@ -509,17 +511,22 @@ int util::replaceAll(
return replace_all(str, from, to); return replace_all(str, from, to);
} }
// replace it with std::from_chars in the far far future double util::parse_double(const std::string& str) {
double util::parse_double(const std::string& str) { const char* begin = str.data();
std::istringstream ss(str); const char* end = begin + str.size();
ss.imbue(std::locale("C")); while (begin != end && std::isspace(static_cast<unsigned char>(*begin))) {
double d; begin++;
ss >> d; }
if (ss.fail()) { if (begin != end && *begin == '+') {
throw std::runtime_error("invalid number format"); begin++;
} }
return d; double d = 0.0;
} const auto result = std::from_chars(begin, end, d);
if (result.ec != std::errc()) {
throw std::runtime_error("invalid number format");
}
return d;
}
double util::parse_double(const std::string& str, size_t offset, size_t len) { double util::parse_double(const std::string& str, size_t offset, size_t len) {
return parse_double(str.substr(offset, len)); return parse_double(str.substr(offset, len));

View file

@ -68,6 +68,14 @@ TEST(stringutil, base64_urlsafe) {
} }
} }
TEST(stringutil, parse_double) {
EXPECT_DOUBLE_EQ(util::parse_double("53.125"), 53.125);
EXPECT_DOUBLE_EQ(util::parse_double("-0.25"), -0.25);
EXPECT_DOUBLE_EQ(util::parse_double(" +12.5"), 12.5);
EXPECT_DOUBLE_EQ(util::parse_double("xx1.75yy", 2, 4), 1.75);
EXPECT_THROW(util::parse_double("not-a-number"), std::runtime_error);
}
class StringParser : BasicParser<char> { class StringParser : BasicParser<char> {
public: public:
StringParser(std::string_view source) : BasicParser("<string>", source) {} StringParser(std::string_view source) : BasicParser("<string>", source) {}