diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2023-07-26 10:49:23 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rspamd.com> | 2023-07-26 10:49:23 +0100 |
commit | 537a7180a0d5132c11636c4fd8b1450cd99d352c (patch) | |
tree | fb9f8c84955a411bdffbd6371ea32f2716fb3687 /src/libutil/cxx | |
parent | 5fd7a90fdaa33f52c59bdb0ca84451e5c1e22365 (diff) | |
download | rspamd-537a7180a0d5132c11636c4fd8b1450cd99d352c.tar.gz rspamd-537a7180a0d5132c11636c4fd8b1450cd99d352c.zip |
[Rework] Use clang-format to unify formatting in all sources
No meaningful changes.
Diffstat (limited to 'src/libutil/cxx')
-rw-r--r-- | src/libutil/cxx/error.hxx | 36 | ||||
-rw-r--r-- | src/libutil/cxx/file_util.cxx | 296 | ||||
-rw-r--r-- | src/libutil/cxx/file_util.hxx | 99 | ||||
-rw-r--r-- | src/libutil/cxx/hash_util.hxx | 46 | ||||
-rw-r--r-- | src/libutil/cxx/local_shared_ptr.hxx | 222 | ||||
-rw-r--r-- | src/libutil/cxx/utf8_util.cxx | 232 | ||||
-rw-r--r-- | src/libutil/cxx/utf8_util.h | 10 | ||||
-rw-r--r-- | src/libutil/cxx/util.hxx | 92 | ||||
-rw-r--r-- | src/libutil/cxx/util_tests.cxx | 36 |
9 files changed, 630 insertions, 439 deletions
diff --git a/src/libutil/cxx/error.hxx b/src/libutil/cxx/error.hxx index 714ed309b..91f9d0cf4 100644 --- a/src/libutil/cxx/error.hxx +++ b/src/libutil/cxx/error.hxx @@ -44,8 +44,10 @@ public: * @param code * @param category */ - error(const char *msg, int code, error_category category = error_category::INFORMAL) : - error_message(msg), error_code(code), category(category) {} + error(const char *msg, int code, error_category category = error_category::INFORMAL) + : error_message(msg), error_code(code), category(category) + { + } /** * Construct error from a temporary string taking membership * @param msg @@ -53,7 +55,8 @@ public: * @param category */ error(std::string &&msg, int code, error_category category = error_category::INFORMAL) - : error_code(code), category(category) { + : error_code(code), category(category) + { static_storage = std::move(msg); error_message = static_storage.value(); } @@ -64,12 +67,15 @@ public: * @param category */ error(const std::string &msg, int code, error_category category = error_category::INFORMAL) - : error_code(code), category(category) { + : error_code(code), category(category) + { static_storage = msg; error_message = static_storage.value(); } - error(const error &other) : error_code(other.error_code), category(other.category) { + error(const error &other) + : error_code(other.error_code), category(other.category) + { if (other.static_storage) { static_storage = other.static_storage; error_message = static_storage.value(); @@ -79,11 +85,13 @@ public: } } - error(error &&other) noexcept { + error(error &&other) noexcept + { *this = std::move(other); } - error& operator = (error &&other) noexcept { + error &operator=(error &&other) noexcept + { if (other.static_storage.has_value()) { std::swap(static_storage, other.static_storage); error_message = static_storage.value(); @@ -101,28 +109,32 @@ public: * Convert into GError * @return */ - auto into_g_error() const -> GError * { + auto into_g_error() const -> GError * + { return g_error_new(g_quark_from_static_string("rspamd"), error_code, "%s", - error_message.data()); + error_message.data()); } /** * Convenience alias for the `into_g_error` * @param err */ - auto into_g_error_set(GError **err) const -> void { + auto into_g_error_set(GError **err) const -> void + { if (err && *err == nullptr) { *err = into_g_error(); } } + public: std::string_view error_message; int error_code; error_category category; + private: std::optional<std::string> static_storage; }; -} // namespace rspamd::util +}// namespace rspamd::util -#endif //RSPAMD_ERROR_HXX +#endif//RSPAMD_ERROR_HXX diff --git a/src/libutil/cxx/file_util.cxx b/src/libutil/cxx/file_util.cxx index bc9028aa8..9baf062a5 100644 --- a/src/libutil/cxx/file_util.cxx +++ b/src/libutil/cxx/file_util.cxx @@ -32,7 +32,7 @@ auto raii_file::open(const char *fname, int flags) -> tl::expected<raii_file, er #endif if (fname == nullptr) { - return tl::make_unexpected(error {"cannot open file; filename is nullptr", EINVAL, error_category::CRITICAL}); + return tl::make_unexpected(error{"cannot open file; filename is nullptr", EINVAL, error_category::CRITICAL}); } auto fd = ::open(fname, oflags); @@ -44,7 +44,7 @@ auto raii_file::open(const char *fname, int flags) -> tl::expected<raii_file, er auto ret = raii_file{fname, fd, false}; if (fstat(ret.fd, &ret.st) == -1) { - return tl::make_unexpected(error {fmt::format("cannot stat file {}: {}", fname, ::strerror(errno)), errno}); + return tl::make_unexpected(error{fmt::format("cannot stat file {}: {}", fname, ::strerror(errno)), errno}); } return ret; @@ -52,13 +52,13 @@ auto raii_file::open(const char *fname, int flags) -> tl::expected<raii_file, er auto raii_file::create(const char *fname, int flags, int perms) -> tl::expected<raii_file, error> { - int oflags = flags|O_CREAT; + int oflags = flags | O_CREAT; #ifdef O_CLOEXEC oflags |= O_CLOEXEC; #endif if (fname == nullptr) { - return tl::make_unexpected(error {"cannot create file; filename is nullptr", EINVAL, error_category::CRITICAL}); + return tl::make_unexpected(error{"cannot create file; filename is nullptr", EINVAL, error_category::CRITICAL}); } auto fd = ::open(fname, oflags, perms); @@ -83,19 +83,19 @@ auto raii_file::create_temp(const char *fname, int flags, int perms) -> tl::expe oflags |= O_CLOEXEC | O_CREAT | O_EXCL; #endif if (fname == nullptr) { - return tl::make_unexpected(error {"cannot open file; filename is nullptr", EINVAL, error_category::CRITICAL}); + return tl::make_unexpected(error{"cannot open file; filename is nullptr", EINVAL, error_category::CRITICAL}); } auto fd = ::open(fname, oflags, perms); if (fd == -1) { - return tl::make_unexpected(error {fmt::format("cannot create file {}: {}", fname, ::strerror(errno)), errno}); + return tl::make_unexpected(error{fmt::format("cannot create file {}: {}", fname, ::strerror(errno)), errno}); } auto ret = raii_file{fname, fd, true}; if (fstat(ret.fd, &ret.st) == -1) { - return tl::make_unexpected(error {fmt::format("cannot stat file {}: {}", fname, ::strerror(errno)), errno}); + return tl::make_unexpected(error{fmt::format("cannot stat file {}: {}", fname, ::strerror(errno)), errno}); } return ret; @@ -108,8 +108,7 @@ auto raii_file::mkstemp(const char *pattern, int flags, int perms) -> tl::expect oflags |= O_CLOEXEC | O_CREAT | O_EXCL; #endif if (pattern == nullptr) { - return tl::make_unexpected(error {"cannot open file; pattern is nullptr", EINVAL, error_category::CRITICAL}); - + return tl::make_unexpected(error{"cannot open file; pattern is nullptr", EINVAL, error_category::CRITICAL}); } std::string mutable_pattern = pattern; @@ -117,14 +116,15 @@ auto raii_file::mkstemp(const char *pattern, int flags, int perms) -> tl::expect auto fd = g_mkstemp_full(mutable_pattern.data(), oflags, perms); if (fd == -1) { - return tl::make_unexpected(error {fmt::format("cannot create file {}: {}", pattern, ::strerror(errno)), errno}); + return tl::make_unexpected(error{fmt::format("cannot create file {}: {}", pattern, ::strerror(errno)), errno}); } auto ret = raii_file{mutable_pattern.c_str(), fd, true}; if (fstat(ret.fd, &ret.st) == -1) { - return tl::make_unexpected(error { fmt::format("cannot stat file {}: {}", - mutable_pattern, ::strerror(errno)), errno} ); + return tl::make_unexpected(error{fmt::format("cannot stat file {}: {}", + mutable_pattern, ::strerror(errno)), + errno}); } return ret; @@ -134,7 +134,7 @@ raii_file::~raii_file() noexcept { if (fd != -1) { if (temp) { - (void)unlink(fname.c_str()); + (void) unlink(fname.c_str()); } close(fd); } @@ -145,7 +145,8 @@ auto raii_file::update_stat() noexcept -> bool return fstat(fd, &st) != -1; } -raii_file::raii_file(const char *fname, int fd, bool temp) : fd(fd), temp(temp) +raii_file::raii_file(const char *fname, int fd, bool temp) + : fd(fd), temp(temp) { std::size_t nsz; @@ -167,22 +168,23 @@ auto raii_locked_file::lock_raii_file(raii_file &&unlocked) -> tl::expected<raii { if (!rspamd_file_lock(unlocked.get_fd(), TRUE)) { return tl::make_unexpected( - error { fmt::format("cannot lock file {}: {}", unlocked.get_name(), ::strerror(errno)), errno}); + error{fmt::format("cannot lock file {}: {}", unlocked.get_name(), ::strerror(errno)), errno}); } return raii_locked_file{std::move(unlocked)}; } -auto raii_locked_file::unlock() -> raii_file { +auto raii_locked_file::unlock() -> raii_file +{ if (fd != -1) { (void) rspamd_file_unlock(fd, FALSE); } - return raii_file{static_cast<raii_file&&>(std::move(*this))}; + return raii_file{static_cast<raii_file &&>(std::move(*this))}; } raii_mmaped_file::raii_mmaped_file(raii_file &&file, void *map, std::size_t sz) - : file(std::move(file)), map(map), map_size(sz) + : file(std::move(file)), map(map), map_size(sz) { } @@ -192,21 +194,22 @@ auto raii_mmaped_file::mmap_shared(raii_file &&file, void *map; if (file.get_stat().st_size < offset || offset < 0) { - return tl::make_unexpected(error { + return tl::make_unexpected(error{ fmt::format("cannot mmap file {} due to incorrect offset; offset={}, size={}", - file.get_name(), offset, file.get_size()), EINVAL}); + file.get_name(), offset, file.get_size()), + EINVAL}); } /* Update stat on file to ensure it is up-to-date */ file.update_stat(); map = mmap(nullptr, (std::size_t)(file.get_size() - offset), flags, MAP_SHARED, file.get_fd(), offset); if (map == MAP_FAILED) { - return tl::make_unexpected(error { fmt::format("cannot mmap file {}: {}", - file.get_name(), ::strerror(errno)), errno }); - + return tl::make_unexpected(error{fmt::format("cannot mmap file {}: {}", + file.get_name(), ::strerror(errno)), + errno}); } - return raii_mmaped_file{std::move(file), map, (std::size_t)(file.get_size() - offset)}; + return raii_mmaped_file{std::move(file), map, (std::size_t)(file.get_size() - offset)}; } auto raii_mmaped_file::mmap_shared(const char *fname, int open_flags, @@ -229,7 +232,7 @@ raii_mmaped_file::~raii_mmaped_file() } raii_mmaped_file::raii_mmaped_file(raii_mmaped_file &&other) noexcept - : file(std::move(other.file)) + : file(std::move(other.file)) { std::swap(map, other.map); std::swap(map_size, other.map_size); @@ -239,7 +242,7 @@ auto raii_file_sink::create(const char *fname, int flags, int perms, const char *suffix) -> tl::expected<raii_file_sink, error> { if (!fname || !suffix) { - return tl::make_unexpected(error {"cannot create file; filename is nullptr", EINVAL, error_category::CRITICAL}); + return tl::make_unexpected(error{"cannot create file; filename is nullptr", EINVAL, error_category::CRITICAL}); } auto tmp_fname = fmt::format("{}.{}", fname, suffix); @@ -277,34 +280,37 @@ raii_file_sink::~raii_file_sink() } raii_file_sink::raii_file_sink(raii_locked_file &&_file, const char *_output, std::string &&_tmp_fname) - : file(std::move(_file)), output_fname(_output), tmp_fname(std::move(_tmp_fname)), success(false) + : file(std::move(_file)), output_fname(_output), tmp_fname(std::move(_tmp_fname)), success(false) { } raii_file_sink::raii_file_sink(raii_file_sink &&other) noexcept - : file(std::move(other.file)), - output_fname(std::move(other.output_fname)), - tmp_fname(std::move(other.tmp_fname)), - success(other.success) + : file(std::move(other.file)), + output_fname(std::move(other.output_fname)), + tmp_fname(std::move(other.tmp_fname)), + success(other.success) { } namespace tests { template<class T> -static auto test_read_file(const T& f) { +static auto test_read_file(const T &f) +{ auto fd = f.get_fd(); - (void)::lseek(fd, 0, SEEK_SET); - std::string buf('\0', (std::size_t)f.get_size()); + (void) ::lseek(fd, 0, SEEK_SET); + std::string buf('\0', (std::size_t) f.get_size()); ::read(fd, buf.data(), buf.size()); return buf; } template<class T> -static auto test_write_file(const T& f, const std::string_view &buf) { +static auto test_write_file(const T &f, const std::string_view &buf) +{ auto fd = f.get_fd(); - (void)::lseek(fd, 0, SEEK_SET); + (void) ::lseek(fd, 0, SEEK_SET); return ::write(fd, buf.data(), buf.size()); } -auto random_fname(std::string_view extension) { +auto random_fname(std::string_view extension) +{ const auto *tmpdir = getenv("TMPDIR"); if (tmpdir == nullptr) { tmpdir = G_DIR_SEPARATOR_S "tmp"; @@ -315,7 +321,7 @@ auto random_fname(std::string_view extension) { unsigned char hexbuf[32]; rspamd_random_hex(hexbuf, sizeof(hexbuf)); - out_fname.append((const char *)hexbuf, sizeof(hexbuf)); + out_fname.append((const char *) hexbuf, sizeof(hexbuf)); if (!extension.empty()) { out_fname.append("."); out_fname.append(extension); @@ -323,123 +329,129 @@ auto random_fname(std::string_view extension) { return out_fname; } -TEST_SUITE("loked files utils") { +TEST_SUITE("loked files utils") +{ -TEST_CASE("create and delete file") { - auto fname = random_fname("tmp"); + TEST_CASE("create and delete file") { - auto raii_locked_file = raii_locked_file::create_temp(fname.c_str(), O_RDONLY, 00600); - CHECK(raii_locked_file.has_value()); - CHECK(raii_locked_file.value().get_extension() == "tmp"); - CHECK(::access(fname.c_str(), R_OK) == 0); - } - // File must be deleted after this call - auto ret = ::access(fname.c_str(), R_OK); - auto serrno = errno; - CHECK(ret == -1); - CHECK(serrno == ENOENT); - // Create one more time + auto fname = random_fname("tmp"); + { + auto raii_locked_file = raii_locked_file::create_temp(fname.c_str(), O_RDONLY, 00600); + CHECK(raii_locked_file.has_value()); + CHECK(raii_locked_file.value().get_extension() == "tmp"); + CHECK(::access(fname.c_str(), R_OK) == 0); + } + // File must be deleted after this call + auto ret = ::access(fname.c_str(), R_OK); + auto serrno = errno; + CHECK(ret == -1); + CHECK(serrno == ENOENT); + // Create one more time + { + auto raii_locked_file = raii_locked_file::create_temp(fname.c_str(), O_RDONLY, 00600); + CHECK(raii_locked_file.has_value()); + CHECK(::access(fname.c_str(), R_OK) == 0); + } + ret = ::access(fname.c_str(), R_OK); + serrno = errno; + CHECK(ret == -1); + CHECK(serrno == ENOENT); + } + + TEST_CASE("check lock") { - auto raii_locked_file = raii_locked_file::create_temp(fname.c_str(), O_RDONLY, 00600); - CHECK(raii_locked_file.has_value()); - CHECK(::access(fname.c_str(), R_OK) == 0); - } - ret = ::access(fname.c_str(), R_OK); - serrno = errno; - CHECK(ret == -1); - CHECK(serrno == ENOENT); -} + auto fname = random_fname(""); + { + auto raii_locked_file = raii_locked_file::create_temp(fname.c_str(), O_RDONLY, 00600); + CHECK(raii_locked_file.has_value()); + CHECK(raii_locked_file.value().get_extension() == ""); + CHECK(::access(fname.c_str(), R_OK) == 0); + auto raii_locked_file2 = raii_locked_file::open(fname.c_str(), O_RDONLY); + CHECK(!raii_locked_file2.has_value()); + CHECK(::access(fname.c_str(), R_OK) == 0); + } + // File must be deleted after this call + auto ret = ::access(fname.c_str(), R_OK); + auto serrno = errno; + CHECK(ret == -1); + CHECK(serrno == ENOENT); + } -TEST_CASE("check lock") { - auto fname = random_fname(""); + auto get_tmpdir()->std::string { - auto raii_locked_file = raii_locked_file::create_temp(fname.c_str(), O_RDONLY, 00600); - CHECK(raii_locked_file.has_value()); - CHECK(raii_locked_file.value().get_extension() == ""); - CHECK(::access(fname.c_str(), R_OK) == 0); - auto raii_locked_file2 = raii_locked_file::open(fname.c_str(), O_RDONLY); - CHECK(!raii_locked_file2.has_value()); - CHECK(::access(fname.c_str(), R_OK) == 0); - } - // File must be deleted after this call - auto ret = ::access(fname.c_str(), R_OK); - auto serrno = errno; - CHECK(ret == -1); - CHECK(serrno == ENOENT); -} + const auto *tmpdir = getenv("TMPDIR"); + if (tmpdir == nullptr) { + tmpdir = G_DIR_SEPARATOR_S "tmp"; + } -auto get_tmpdir() -> std::string { - const auto *tmpdir = getenv("TMPDIR"); - if (tmpdir == nullptr) { - tmpdir = G_DIR_SEPARATOR_S "tmp"; - } + std::size_t sz; + std::string mut_fname = tmpdir; + rspamd_normalize_path_inplace(mut_fname.data(), mut_fname.size(), &sz); + mut_fname.resize(sz); - std::size_t sz; - std::string mut_fname = tmpdir; - rspamd_normalize_path_inplace(mut_fname.data(), mut_fname.size(), &sz); - mut_fname.resize(sz); + if (!mut_fname.ends_with(G_DIR_SEPARATOR)) { + mut_fname += G_DIR_SEPARATOR; + } - if (!mut_fname.ends_with(G_DIR_SEPARATOR)) { - mut_fname += G_DIR_SEPARATOR; + return mut_fname; } - return mut_fname; -} - -TEST_CASE("tempfile") { - std::string tmpname; - const std::string tmpdir{get_tmpdir()}; + TEST_CASE("tempfile") { - auto raii_locked_file = raii_locked_file::mkstemp(std::string(tmpdir + G_DIR_SEPARATOR_S + "doctest-XXXXXXXX").c_str(), - O_RDONLY, 00600); - CHECK(raii_locked_file.has_value()); - CHECK(raii_locked_file.value().get_dir() == tmpdir); - CHECK(access(raii_locked_file.value().get_name().data(), R_OK) == 0); - auto raii_locked_file2 = raii_locked_file::open(raii_locked_file.value().get_name().data(), O_RDONLY); - CHECK(!raii_locked_file2.has_value()); - CHECK(access(raii_locked_file.value().get_name().data(), R_OK) == 0); - tmpname = raii_locked_file.value().get_name(); - } - // File must be deleted after this call - auto ret = ::access(tmpname.c_str(), R_OK); - auto serrno = errno; - CHECK(ret == -1); - CHECK(serrno == ENOENT); -} + std::string tmpname; + const std::string tmpdir{get_tmpdir()}; + { + auto raii_locked_file = raii_locked_file::mkstemp(std::string(tmpdir + G_DIR_SEPARATOR_S + "doctest-XXXXXXXX").c_str(), + O_RDONLY, 00600); + CHECK(raii_locked_file.has_value()); + CHECK(raii_locked_file.value().get_dir() == tmpdir); + CHECK(access(raii_locked_file.value().get_name().data(), R_OK) == 0); + auto raii_locked_file2 = raii_locked_file::open(raii_locked_file.value().get_name().data(), O_RDONLY); + CHECK(!raii_locked_file2.has_value()); + CHECK(access(raii_locked_file.value().get_name().data(), R_OK) == 0); + tmpname = raii_locked_file.value().get_name(); + } + // File must be deleted after this call + auto ret = ::access(tmpname.c_str(), R_OK); + auto serrno = errno; + CHECK(ret == -1); + CHECK(serrno == ENOENT); + } -TEST_CASE("mmap") { - std::string tmpname; - const std::string tmpdir{get_tmpdir()}; + TEST_CASE("mmap") { - auto raii_file = raii_file::mkstemp(std::string(tmpdir + G_DIR_SEPARATOR_S + "doctest-XXXXXXXX").c_str(), - O_RDWR|O_CREAT|O_EXCL, 00600); - CHECK(raii_file.has_value()); - CHECK(raii_file->get_dir() == tmpdir); - CHECK(access(raii_file->get_name().data(), R_OK) == 0); - tmpname = std::string{raii_file->get_name()}; - char payload[] = {'1', '2', '3'}; - CHECK(write(raii_file->get_fd(), payload, sizeof(payload)) == sizeof(payload)); - auto mmapped_file1 = raii_mmaped_file::mmap_shared(std::move(raii_file.value()), PROT_READ|PROT_WRITE); - CHECK(mmapped_file1.has_value()); - CHECK(!raii_file->is_valid()); - CHECK(mmapped_file1->get_size() == sizeof(payload)); - CHECK(memcmp(mmapped_file1->get_map(), payload, sizeof(payload)) == 0); - *(char *)mmapped_file1->get_map() = '2'; - auto mmapped_file2 = raii_mmaped_file::mmap_shared(tmpname.c_str(), O_RDONLY, PROT_READ); - CHECK(mmapped_file2.has_value()); - CHECK(mmapped_file2->get_size() == sizeof(payload)); - CHECK(memcmp(mmapped_file2->get_map(), payload, sizeof(payload)) != 0); - CHECK(memcmp(mmapped_file2->get_map(), mmapped_file1->get_map(), sizeof(payload)) == 0); - } - // File must be deleted after this call - auto ret = ::access(tmpname.c_str(), R_OK); - auto serrno = errno; - CHECK(ret == -1); - CHECK(serrno == ENOENT); -} + std::string tmpname; + const std::string tmpdir{get_tmpdir()}; + { + auto raii_file = raii_file::mkstemp(std::string(tmpdir + G_DIR_SEPARATOR_S + "doctest-XXXXXXXX").c_str(), + O_RDWR | O_CREAT | O_EXCL, 00600); + CHECK(raii_file.has_value()); + CHECK(raii_file->get_dir() == tmpdir); + CHECK(access(raii_file->get_name().data(), R_OK) == 0); + tmpname = std::string{raii_file->get_name()}; + char payload[] = {'1', '2', '3'}; + CHECK(write(raii_file->get_fd(), payload, sizeof(payload)) == sizeof(payload)); + auto mmapped_file1 = raii_mmaped_file::mmap_shared(std::move(raii_file.value()), PROT_READ | PROT_WRITE); + CHECK(mmapped_file1.has_value()); + CHECK(!raii_file->is_valid()); + CHECK(mmapped_file1->get_size() == sizeof(payload)); + CHECK(memcmp(mmapped_file1->get_map(), payload, sizeof(payload)) == 0); + *(char *) mmapped_file1->get_map() = '2'; + auto mmapped_file2 = raii_mmaped_file::mmap_shared(tmpname.c_str(), O_RDONLY, PROT_READ); + CHECK(mmapped_file2.has_value()); + CHECK(mmapped_file2->get_size() == sizeof(payload)); + CHECK(memcmp(mmapped_file2->get_map(), payload, sizeof(payload)) != 0); + CHECK(memcmp(mmapped_file2->get_map(), mmapped_file1->get_map(), sizeof(payload)) == 0); + } + // File must be deleted after this call + auto ret = ::access(tmpname.c_str(), R_OK); + auto serrno = errno; + CHECK(ret == -1); + CHECK(serrno == ENOENT); + } -} // TEST_SUITE +}// TEST_SUITE -} // namespace tests +}// namespace tests -} // namespace rspamd::util +}// namespace rspamd::util diff --git a/src/libutil/cxx/file_util.hxx b/src/libutil/cxx/file_util.hxx index e712fcb15..a0c624726 100644 --- a/src/libutil/cxx/file_util.hxx +++ b/src/libutil/cxx/file_util.hxx @@ -37,23 +37,28 @@ public: static auto create_temp(const char *fname, int flags, int perms) -> tl::expected<raii_file, error>; static auto mkstemp(const char *pattern, int flags, int perms) -> tl::expected<raii_file, error>; - auto get_fd() const -> int { + auto get_fd() const -> int + { return fd; } - auto get_stat() const -> const struct stat& { + auto get_stat() const -> const struct stat & + { return st; }; - auto get_size() const -> std::size_t { + auto get_size() const -> std::size_t + { return st.st_size; }; - auto get_name() const -> std::string_view { + auto get_name() const -> std::string_view + { return std::string_view{fname}; } - auto get_dir() const -> std::string_view { + auto get_dir() const -> std::string_view + { auto sep_pos = fname.rfind(G_DIR_SEPARATOR); if (sep_pos == std::string::npos) { @@ -61,13 +66,14 @@ public: } while (sep_pos >= 1 && fname[sep_pos - 1] == G_DIR_SEPARATOR) { - sep_pos --; + sep_pos--; } return std::string_view{fname.c_str(), sep_pos + 1}; } - auto get_extension() const -> std::string_view { + auto get_extension() const -> std::string_view + { auto sep_pos = fname.rfind(G_DIR_SEPARATOR); if (sep_pos == std::string::npos) { @@ -85,7 +91,8 @@ public: } } - raii_file& operator=(raii_file &&other) noexcept { + raii_file &operator=(raii_file &&other) noexcept + { std::swap(fd, other.fd); std::swap(temp, other.temp); std::swap(fname, other.fname); @@ -94,7 +101,8 @@ public: return *this; } - raii_file(raii_file &&other) noexcept { + raii_file(raii_file &&other) noexcept + { *this = std::move(other); } @@ -102,7 +110,8 @@ public: * Prevent file from being deleted * @return */ - auto make_immortal() noexcept { + auto make_immortal() noexcept + { temp = false; } @@ -112,14 +121,16 @@ public: */ auto update_stat() noexcept -> bool; - auto is_valid() noexcept -> bool { + auto is_valid() noexcept -> bool + { return fd != -1; } /* Do not allow copy/default ctor */ - const raii_file& operator=(const raii_file &other) = delete; + const raii_file &operator=(const raii_file &other) = delete; raii_file() = delete; raii_file(const raii_file &other) = delete; + protected: int fd = -1; bool temp; @@ -136,28 +147,32 @@ struct raii_locked_file final : public raii_file { public: ~raii_locked_file() noexcept override; - static auto open(const char *fname, int flags) -> tl::expected<raii_locked_file, error> { + static auto open(const char *fname, int flags) -> tl::expected<raii_locked_file, error> + { auto locked = raii_file::open(fname, flags).and_then([]<class T>(T &&file) { return lock_raii_file(std::forward<T>(file)); }); return locked; } - static auto create(const char *fname, int flags, int perms) -> tl::expected<raii_locked_file, error> { + static auto create(const char *fname, int flags, int perms) -> tl::expected<raii_locked_file, error> + { auto locked = raii_file::create(fname, flags, perms).and_then([]<class T>(T &&file) { return lock_raii_file(std::forward<T>(file)); }); return locked; } - static auto create_temp(const char *fname, int flags, int perms) -> tl::expected<raii_locked_file, error> { + static auto create_temp(const char *fname, int flags, int perms) -> tl::expected<raii_locked_file, error> + { auto locked = raii_file::create_temp(fname, flags, perms).and_then([]<class T>(T &&file) { return lock_raii_file(std::forward<T>(file)); }); return locked; } - static auto mkstemp(const char *pattern, int flags, int perms) -> tl::expected<raii_locked_file, error> { + static auto mkstemp(const char *pattern, int flags, int perms) -> tl::expected<raii_locked_file, error> + { auto locked = raii_file::mkstemp(pattern, flags, perms).and_then([]<class T>(T &&file) { return lock_raii_file(std::forward<T>(file)); }); @@ -165,7 +180,8 @@ public: return locked; } - raii_locked_file& operator=(raii_locked_file &&other) noexcept { + raii_locked_file &operator=(raii_locked_file &&other) noexcept + { std::swap(fd, other.fd); std::swap(temp, other.temp); std::swap(fname, other.fname); @@ -180,15 +196,25 @@ public: */ auto unlock() -> raii_file; - raii_locked_file(raii_locked_file &&other) noexcept : raii_file(static_cast<raii_file &&>(std::move(other))) {} + raii_locked_file(raii_locked_file &&other) noexcept + : raii_file(static_cast<raii_file &&>(std::move(other))) + { + } /* Do not allow copy/default ctor */ - const raii_locked_file& operator=(const raii_locked_file &other) = delete; + const raii_locked_file &operator=(const raii_locked_file &other) = delete; raii_locked_file() = delete; raii_locked_file(const raii_locked_file &other) = delete; + private: static auto lock_raii_file(raii_file &&unlocked) -> tl::expected<raii_locked_file, error>; - raii_locked_file(raii_file &&other) noexcept : raii_file(std::move(other)) {} - explicit raii_locked_file(const char *fname, int fd, bool temp) : raii_file(fname, fd, temp) {} + raii_locked_file(raii_file &&other) noexcept + : raii_file(std::move(other)) + { + } + explicit raii_locked_file(const char *fname, int fd, bool temp) + : raii_file(fname, fd, temp) + { + } }; /** @@ -199,18 +225,29 @@ struct raii_mmaped_file final { static auto mmap_shared(raii_file &&file, int flags, std::int64_t offset = 0) -> tl::expected<raii_mmaped_file, error>; static auto mmap_shared(const char *fname, int open_flags, int mmap_flags, std::int64_t offset = 0) -> tl::expected<raii_mmaped_file, error>; // Returns a constant pointer to the underlying map - auto get_map() const -> void* {return map;} - auto get_file() const -> const raii_file& { return file; } + auto get_map() const -> void * + { + return map; + } + auto get_file() const -> const raii_file & + { + return file; + } // Passes the ownership of the mmaped memory to the callee - auto steal_map() -> std::tuple<void *, std::size_t> { + auto steal_map() -> std::tuple<void *, std::size_t> + { auto ret = std::make_tuple(this->map, map_size); this->map = nullptr; return ret; } - auto get_size() const -> std::size_t { return file.get_stat().st_size; } + auto get_size() const -> std::size_t + { + return file.get_stat().st_size; + } - raii_mmaped_file& operator=(raii_mmaped_file &&other) noexcept { + raii_mmaped_file &operator=(raii_mmaped_file &&other) noexcept + { std::swap(map, other.map); std::swap(map_size, other.map_size); file = std::move(other.file); @@ -221,9 +258,10 @@ struct raii_mmaped_file final { raii_mmaped_file(raii_mmaped_file &&other) noexcept; /* Do not allow copy/default ctor */ - const raii_mmaped_file& operator=(const raii_mmaped_file &other) = delete; + const raii_mmaped_file &operator=(const raii_mmaped_file &other) = delete; raii_mmaped_file() = delete; raii_mmaped_file(const raii_mmaped_file &other) = delete; + private: /* Is intended to be used with map_shared */ explicit raii_mmaped_file(raii_file &&_file, void *_map, std::size_t sz); @@ -248,9 +286,10 @@ struct raii_file_sink final { raii_file_sink(raii_file_sink &&other) noexcept; /* Do not allow copy/default ctor */ - const raii_file_sink& operator=(const raii_file_sink &other) = delete; + const raii_file_sink &operator=(const raii_file_sink &other) = delete; raii_file_sink() = delete; raii_file_sink(const raii_file_sink &other) = delete; + private: explicit raii_file_sink(raii_locked_file &&_file, const char *_output, std::string &&_tmp_fname); raii_locked_file file; @@ -259,6 +298,6 @@ private: bool success; }; -} +}// namespace rspamd::util -#endif //RSPAMD_FILE_UTIL_HXX +#endif//RSPAMD_FILE_UTIL_HXX diff --git a/src/libutil/cxx/hash_util.hxx b/src/libutil/cxx/hash_util.hxx index 86f094083..972165850 100644 --- a/src/libutil/cxx/hash_util.hxx +++ b/src/libutil/cxx/hash_util.hxx @@ -30,22 +30,28 @@ namespace rspamd { template<typename T> struct smart_ptr_equal { using is_transparent = void; /* We want to find values in a set of shared_ptr by reference */ - auto operator()(const std::shared_ptr<T> &a, const std::shared_ptr<T> &b) const { + auto operator()(const std::shared_ptr<T> &a, const std::shared_ptr<T> &b) const + { return (*a) == (*b); } - auto operator()(const std::shared_ptr<T> &a, const T &b) const { + auto operator()(const std::shared_ptr<T> &a, const T &b) const + { return (*a) == b; } - auto operator()(const T &a, const std::shared_ptr<T> &b) const { + auto operator()(const T &a, const std::shared_ptr<T> &b) const + { return a == (*b); } - auto operator()(const std::unique_ptr<T> &a, const std::unique_ptr<T> &b) const { + auto operator()(const std::unique_ptr<T> &a, const std::unique_ptr<T> &b) const + { return (*a) == (*b); } - auto operator()(const std::unique_ptr<T> &a, const T &b) const { + auto operator()(const std::unique_ptr<T> &a, const T &b) const + { return (*a) == b; } - auto operator()(const T &a, const std::unique_ptr<T> &b) const { + auto operator()(const T &a, const std::unique_ptr<T> &b) const + { return a == (*b); } }; @@ -53,13 +59,16 @@ struct smart_ptr_equal { template<typename T> struct smart_ptr_hash { using is_transparent = void; /* We want to find values in a set of shared_ptr by reference */ - auto operator()(const std::shared_ptr<T> &a) const { + auto operator()(const std::shared_ptr<T> &a) const + { return std::hash<T>()(*a); } - auto operator()(const std::unique_ptr<T> &a) const { + auto operator()(const std::unique_ptr<T> &a) const + { return std::hash<T>()(*a); } - auto operator()(const T &a) const { + auto operator()(const T &a) const + { return std::hash<T>()(a); } }; @@ -67,13 +76,16 @@ struct smart_ptr_hash { /* Enable lookup by string view */ struct smart_str_equal { using is_transparent = void; - auto operator()(const std::string &a, const std::string &b) const { + auto operator()(const std::string &a, const std::string &b) const + { return a == b; } - auto operator()(const std::string_view &a, const std::string &b) const { + auto operator()(const std::string_view &a, const std::string &b) const + { return a == b; } - auto operator()(const std::string &a, const std::string_view &b) const { + auto operator()(const std::string &a, const std::string_view &b) const + { return a == b; } }; @@ -81,14 +93,16 @@ struct smart_str_equal { struct smart_str_hash { using is_transparent = void; using is_avalanching = typename ankerl::unordered_dense::hash<std::string_view>::is_avalanching; - auto operator()(const std::string &a) const { + auto operator()(const std::string &a) const + { return ankerl::unordered_dense::hash<std::string>()(a); } - auto operator()(const std::string_view &a) const { + auto operator()(const std::string_view &a) const + { return ankerl::unordered_dense::hash<std::string_view>()(a); } }; -} +}// namespace rspamd -#endif //RSPAMD_HASH_UTIL_HXX +#endif//RSPAMD_HASH_UTIL_HXX diff --git a/src/libutil/cxx/local_shared_ptr.hxx b/src/libutil/cxx/local_shared_ptr.hxx index 233c5df1e..78ed5ba92 100644 --- a/src/libutil/cxx/local_shared_ptr.hxx +++ b/src/libutil/cxx/local_shared_ptr.hxx @@ -21,8 +21,8 @@ #include <memory> #include <algorithm> // for std::swap -#include <cstddef> // for std::size_t -#include <functional> // for std::less +#include <cstddef> // for std::size_t +#include <functional>// for std::less /* * Smart pointers with no atomic refcounts to speed up Rspamd which is @@ -36,51 +36,64 @@ class ref_cnt { public: using refcount_t = int; - constexpr auto add_shared() -> refcount_t { + constexpr auto add_shared() -> refcount_t + { return ++ref_shared; } - constexpr auto add_weak() -> refcount_t { + constexpr auto add_weak() -> refcount_t + { return ++ref_weak; } - constexpr auto release_shared() -> refcount_t { + constexpr auto release_shared() -> refcount_t + { return --ref_shared; } - constexpr auto release_weak() -> refcount_t { + constexpr auto release_weak() -> refcount_t + { return --ref_weak; } - constexpr auto shared_count() const -> refcount_t { + constexpr auto shared_count() const -> refcount_t + { return ref_shared; } - constexpr auto weak_count() const -> refcount_t { + constexpr auto weak_count() const -> refcount_t + { return ref_weak; } - virtual ~ref_cnt() {} + virtual ~ref_cnt() + { + } virtual void dispose() = 0; + private: refcount_t ref_weak = 0; refcount_t ref_shared = 1; }; -template <class T> +template<class T> class obj_and_refcnt : public ref_cnt { private: typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type storage_type; storage_type storage; bool initialized; - virtual void dispose() override { + virtual void dispose() override + { if (initialized) { T *p = reinterpret_cast<T *>(&storage); p->~T(); initialized = false; } } + public: - template <typename... Args> - explicit obj_and_refcnt(Args&&... args) : initialized(true) + template<typename... Args> + explicit obj_and_refcnt(Args &&...args) + : initialized(true) { - new(&storage) T(std::forward<Args>(args)...); + new (&storage) T(std::forward<Args>(args)...); } - auto get(void) -> T* { + auto get(void) -> T * + { if (initialized) { return reinterpret_cast<T *>(&storage); } @@ -90,26 +103,32 @@ public: virtual ~obj_and_refcnt() = default; }; -template <class T, class D = typename std::default_delete<T>> +template<class T, class D = typename std::default_delete<T>> class ptr_and_refcnt : public ref_cnt { private: - T* ptr; + T *ptr; D deleter; - virtual void dispose() override { + virtual void dispose() override + { deleter(ptr); ptr = nullptr; } + public: - explicit ptr_and_refcnt(T *_ptr, D &&d = std::default_delete<T>()) : ptr(_ptr), - deleter(std::move(d)) {} + explicit ptr_and_refcnt(T *_ptr, D &&d = std::default_delete<T>()) + : ptr(_ptr), + deleter(std::move(d)) + { + } virtual ~ptr_and_refcnt() = default; }; -} +}// namespace detail -template <class T> class local_weak_ptr; +template<class T> +class local_weak_ptr; -template <class T> +template<class T> class local_shared_ptr { public: typedef T element_type; @@ -117,38 +136,53 @@ public: // Simplified comparing to libc++, no custom deleter and no rebind here // constructors: - constexpr local_shared_ptr() noexcept : px(nullptr), cnt(nullptr) {} + constexpr local_shared_ptr() noexcept + : px(nullptr), cnt(nullptr) + { + } template<class Y, typename std::enable_if< - std::is_convertible<Y*, element_type*>::value, bool>::type = true> - explicit local_shared_ptr(Y* p) : px(p), cnt(new detail::ptr_and_refcnt(p)) + std::is_convertible<Y *, element_type *>::value, bool>::type = true> + explicit local_shared_ptr(Y *p) + : px(p), cnt(new detail::ptr_and_refcnt(p)) { } // custom deleter - template<class Y, class D, typename std::enable_if< - std::is_convertible<Y*, element_type*>::value, bool>::type = true> - explicit local_shared_ptr(Y* p, D &&d) : px(p), cnt(new detail::ptr_and_refcnt<Y, D>(p, std::forward<D>(d))) + template<class Y, class D, typename std::enable_if<std::is_convertible<Y *, element_type *>::value, bool>::type = true> + explicit local_shared_ptr(Y *p, D &&d) + : px(p), cnt(new detail::ptr_and_refcnt<Y, D>(p, std::forward<D>(d))) { } - local_shared_ptr(const local_shared_ptr& r) noexcept : px(r.px), cnt(r.cnt) { + local_shared_ptr(const local_shared_ptr &r) noexcept + : px(r.px), cnt(r.cnt) + { if (cnt) { cnt->add_shared(); } } - local_shared_ptr(local_shared_ptr&& r) noexcept : px(r.px), cnt(r.cnt) { + local_shared_ptr(local_shared_ptr &&r) noexcept + : px(r.px), cnt(r.cnt) + { r.px = nullptr; r.cnt = nullptr; } - template<class Y> explicit local_shared_ptr(const local_weak_ptr<Y>& r) : px(r.px), cnt(r.cnt) { + template<class Y> + explicit local_shared_ptr(const local_weak_ptr<Y> &r) + : px(r.px), cnt(r.cnt) + { if (cnt) { cnt->add_shared(); } } - local_shared_ptr(std::nullptr_t) : local_shared_ptr() { } + local_shared_ptr(std::nullptr_t) + : local_shared_ptr() + { + } - ~local_shared_ptr() { + ~local_shared_ptr() + { if (cnt) { if (cnt->release_shared() <= 0) { cnt->dispose(); @@ -161,73 +195,85 @@ public: } // assignment: - local_shared_ptr& operator=(const local_shared_ptr& r) noexcept { + local_shared_ptr &operator=(const local_shared_ptr &r) noexcept + { local_shared_ptr(r).swap(*this); return *this; } - local_shared_ptr& operator=(local_shared_ptr&& r) noexcept { + local_shared_ptr &operator=(local_shared_ptr &&r) noexcept + { local_shared_ptr(std::move(r)).swap(*this); return *this; } // Mutators - void swap(local_shared_ptr& r) noexcept { + void swap(local_shared_ptr &r) noexcept + { std::swap(this->cnt, r.cnt); std::swap(this->px, r.px); } - void reset() noexcept { + void reset() noexcept + { local_shared_ptr().swap(*this); } // Observers: - T* get() const noexcept { + T *get() const noexcept + { return px; } - T& operator*() const noexcept { + T &operator*() const noexcept + { return *px; } - T* operator->() const noexcept { + T *operator->() const noexcept + { return px; } - long use_count() const noexcept { + long use_count() const noexcept + { if (cnt) { return cnt->shared_count(); } return 0; } - bool unique() const noexcept { + bool unique() const noexcept + { return use_count() == 1; } - explicit operator bool() const noexcept { + explicit operator bool() const noexcept + { return px != nullptr; } template<class Y, typename std::enable_if< - std::is_convertible<Y*, element_type*>::value, bool>::type = true> - auto operator ==(const local_shared_ptr<Y> &other) const -> bool { + std::is_convertible<Y *, element_type *>::value, bool>::type = true> + auto operator==(const local_shared_ptr<Y> &other) const -> bool + { return px == other.px; } template<class Y, typename std::enable_if< - std::is_convertible<Y*, element_type*>::value, bool>::type = true> - auto operator <(const local_shared_ptr<Y> &other) const -> auto { + std::is_convertible<Y *, element_type *>::value, bool>::type = true> + auto operator<(const local_shared_ptr<Y> &other) const -> auto + { return *px < *other.px; } private: - T *px; // contained pointer + T *px;// contained pointer detail::ref_cnt *cnt; - template<class _T, class ... Args> - friend local_shared_ptr<_T> local_make_shared(Args && ... args); + template<class _T, class... Args> + friend local_shared_ptr<_T> local_make_shared(Args &&...args); friend class local_weak_ptr<T>; }; -template<class T, class ... Args> -local_shared_ptr<T> local_make_shared(Args && ... args) +template<class T, class... Args> +local_shared_ptr<T> local_make_shared(Args &&...args) { local_shared_ptr<T> ptr; auto tmp_object = new detail::obj_and_refcnt<T>(std::forward<Args>(args)...); @@ -238,27 +284,35 @@ local_shared_ptr<T> local_make_shared(Args && ... args) } template<class T> -class local_weak_ptr -{ +class local_weak_ptr { public: typedef T element_type; // constructors - constexpr local_weak_ptr() noexcept : px(nullptr), cnt(nullptr) {} + constexpr local_weak_ptr() noexcept + : px(nullptr), cnt(nullptr) + { + } template<class Y, typename std::enable_if< - std::is_convertible<Y*, element_type*>::value, bool>::type = true> - local_weak_ptr(local_shared_ptr<Y> const& r) noexcept : px(r.px),cnt(r.cnt) { + std::is_convertible<Y *, element_type *>::value, bool>::type = true> + local_weak_ptr(local_shared_ptr<Y> const &r) noexcept + : px(r.px), cnt(r.cnt) + { if (cnt) { cnt->add_weak(); } } - local_weak_ptr(local_weak_ptr const& r) noexcept : px(r.px),cnt(r.cnt) { + local_weak_ptr(local_weak_ptr const &r) noexcept + : px(r.px), cnt(r.cnt) + { if (cnt) { cnt->add_weak(); } } - local_weak_ptr(local_weak_ptr && r) noexcept : px(r.px), cnt(r.cnt) { + local_weak_ptr(local_weak_ptr &&r) noexcept + : px(r.px), cnt(r.cnt) + { r.px = nullptr; r.cnt = nullptr; } @@ -273,43 +327,51 @@ public: } // assignment - local_weak_ptr& operator=(local_weak_ptr const& r) noexcept { + local_weak_ptr &operator=(local_weak_ptr const &r) noexcept + { local_weak_ptr(r).swap(*this); return *this; } - local_weak_ptr& operator=(local_shared_ptr<T> const& r) noexcept { + local_weak_ptr &operator=(local_shared_ptr<T> const &r) noexcept + { local_weak_ptr(r).swap(*this); return *this; } template<class Y, typename std::enable_if< - std::is_convertible<Y*, element_type*>::value, bool>::type = true> - local_weak_ptr& operator=(local_weak_ptr<Y> const& r) noexcept { + std::is_convertible<Y *, element_type *>::value, bool>::type = true> + local_weak_ptr &operator=(local_weak_ptr<Y> const &r) noexcept + { local_weak_ptr(r).swap(*this); return *this; } - local_weak_ptr& operator=(local_weak_ptr&& r) noexcept { + local_weak_ptr &operator=(local_weak_ptr &&r) noexcept + { local_weak_ptr(std::move(r)).swap(*this); return *this; } // modifiers - void swap(local_weak_ptr& r) noexcept { + void swap(local_weak_ptr &r) noexcept + { std::swap(this->cnt, r.cnt); std::swap(this->px, r.px); } - void reset() noexcept { + void reset() noexcept + { local_weak_ptr().swap(*this); } // observers - long use_count() const noexcept { + long use_count() const noexcept + { if (cnt) { return cnt->shared_count(); } return 0; } - bool expired() const noexcept { + bool expired() const noexcept + { if (cnt) { return cnt->shared_count() == 0; } @@ -317,7 +379,8 @@ public: return true; } - local_shared_ptr<T> lock() const noexcept { + local_shared_ptr<T> lock() const noexcept + { local_shared_ptr<T> tmp; tmp.cnt = cnt; @@ -328,28 +391,31 @@ public: return tmp; } + private: - element_type* px; + element_type *px; detail::ref_cnt *cnt; }; -} +}// namespace rspamd /* Hashing stuff */ namespace std { -template <class T> +template<class T> struct hash<rspamd::local_shared_ptr<T>> { - inline auto operator()(const rspamd::local_shared_ptr<T> &p) const -> auto { + inline auto operator()(const rspamd::local_shared_ptr<T> &p) const -> auto + { if (!p) { throw std::logic_error("no hash for dangling pointer"); } return hash<T>()(*p.get()); } }; -template <class T> +template<class T> struct hash<rspamd::local_weak_ptr<T>> { - inline auto operator()(const rspamd::local_weak_ptr<T> &p) const -> auto { + inline auto operator()(const rspamd::local_weak_ptr<T> &p) const -> auto + { if (!p) { throw std::logic_error("no hash for dangling pointer"); } @@ -369,6 +435,6 @@ inline void swap(rspamd::local_weak_ptr<T> &x, rspamd::local_weak_ptr<T> &y) noe x.swap(y); } -} +}// namespace std -#endif //RSPAMD_LOCAL_SHARED_PTR_HXX +#endif//RSPAMD_LOCAL_SHARED_PTR_HXX diff --git a/src/libutil/cxx/utf8_util.cxx b/src/libutil/cxx/utf8_util.cxx index 8bb709abf..166fe1cfa 100644 --- a/src/libutil/cxx/utf8_util.cxx +++ b/src/libutil/cxx/utf8_util.cxx @@ -34,7 +34,7 @@ #include "doctest/doctest.h" const char * -rspamd_string_unicode_trim_inplace (const char *str, size_t *len) +rspamd_string_unicode_trim_inplace(const char *str, size_t *len) { const auto *p = str, *end = str + *len; auto i = 0; @@ -97,12 +97,12 @@ rspamd_normalise_unicode_inplace(char *start, size_t *len) int ret = RSPAMD_UNICODE_NORM_NORMAL; - g_assert (U_SUCCESS (uc_err)); + g_assert(U_SUCCESS(uc_err)); auto uc_string = icu::UnicodeString::fromUTF8(icu::StringPiece(start, *len)); auto is_normal = nfkc_norm->quickCheck(uc_string, uc_err); - if (!U_SUCCESS (uc_err)) { + if (!U_SUCCESS(uc_err)) { return RSPAMD_UNICODE_NORM_ERROR; } @@ -111,7 +111,7 @@ rspamd_normalise_unicode_inplace(char *start, size_t *len) icu::StringCharacterIterator it{input}; size_t i = 0; - while(it.hasNext()) { + while (it.hasNext()) { /* libicu is very 'special' if it comes to 'safe' macro */ if (i >= *len) { ret |= RSPAMD_UNICODE_NORM_ERROR; @@ -129,7 +129,7 @@ rspamd_normalise_unicode_inplace(char *start, size_t *len) if (uc == 0xFFFD) { ret |= RSPAMD_UNICODE_NORM_UNNORMAL; } - U8_APPEND((uint8_t*)start, i, *len, uc, err); + U8_APPEND((uint8_t *) start, i, *len, uc, err); if (err) { ret |= RSPAMD_UNICODE_NORM_ERROR; @@ -147,7 +147,7 @@ rspamd_normalise_unicode_inplace(char *start, size_t *len) auto normalised = nfkc_norm->normalize(uc_string, uc_err); - if (!U_SUCCESS (uc_err)) { + if (!U_SUCCESS(uc_err)) { return RSPAMD_UNICODE_NORM_ERROR; } @@ -160,7 +160,7 @@ rspamd_normalise_unicode_inplace(char *start, size_t *len) return static_cast<enum rspamd_utf8_normalise_result>(ret); } -gchar* +gchar * rspamd_utf8_transliterate(const gchar *start, gsize len, gsize *target_len) { UErrorCode uc_err = U_ZERO_ERROR; @@ -177,14 +177,13 @@ rspamd_utf8_transliterate(const gchar *start, gsize len, gsize *target_len) ":: Latin-ASCII;" ":: Lower();" ":: NULL;" - "[:Space Separator:] > ' '" - }; + "[:Space Separator:] > ' '"}; transliterator = std::unique_ptr<icu::Transliterator>( icu::Transliterator::createFromRules("RspamdTranslit", rules, UTRANS_FORWARD, parse_err, uc_err)); if (U_FAILURE(uc_err) || !transliterator) { auto context = icu::UnicodeString(parse_err.postContext, sizeof(parse_err.preContext) / sizeof(UChar)); - g_error ("fatal error: cannot init libicu transliteration engine: %s, line: %d, offset: %d", + g_error("fatal error: cannot init libicu transliteration engine: %s, line: %d, offset: %d", u_errorName(uc_err), parse_err.line, parse_err.offset); abort(); } @@ -195,7 +194,7 @@ rspamd_utf8_transliterate(const gchar *start, gsize len, gsize *target_len) // We assume that all characters are now ascii auto dest_len = uc_string.length(); - gchar *dest = (gchar *)g_malloc(dest_len + 1); + gchar *dest = (gchar *) g_malloc(dest_len + 1); auto sink = icu::CheckedArrayByteSink(dest, dest_len); uc_string.toUTF8(sink); @@ -206,13 +205,14 @@ rspamd_utf8_transliterate(const gchar *start, gsize len, gsize *target_len) } struct rspamd_icu_collate_storage { - icu::Collator* collator = nullptr; - rspamd_icu_collate_storage() { + icu::Collator *collator = nullptr; + rspamd_icu_collate_storage() + { UErrorCode uc_err = U_ZERO_ERROR; collator = icu::Collator::createInstance(icu::Locale::getEnglish(), uc_err); if (U_FAILURE(uc_err) || collator == nullptr) { - g_error ("fatal error: cannot init libicu collation engine: %s", + g_error("fatal error: cannot init libicu collation engine: %s", u_errorName(uc_err)); abort(); } @@ -220,7 +220,8 @@ struct rspamd_icu_collate_storage { collator->setStrength(icu::Collator::PRIMARY); } - ~rspamd_icu_collate_storage() { + ~rspamd_icu_collate_storage() + { if (collator) { delete collator; } @@ -229,8 +230,7 @@ struct rspamd_icu_collate_storage { static rspamd_icu_collate_storage collate_storage; -int -rspamd_utf8_strcmp_sizes(const char *s1, gsize n1, const char *s2, gsize n2) +int rspamd_utf8_strcmp_sizes(const char *s1, gsize n1, const char *s2, gsize n2) { if (n1 >= std::numeric_limits<int>::max() || n2 >= std::numeric_limits<int>::max()) { /* @@ -247,7 +247,7 @@ rspamd_utf8_strcmp_sizes(const char *s1, gsize n1, const char *s2, gsize n2) UErrorCode success = U_ZERO_ERROR; auto res = collate_storage.collator->compareUTF8({s1, (int) n1}, {s2, (int) n2}, - success); + success); switch (res) { case UCOL_EQUAL: @@ -260,81 +260,101 @@ rspamd_utf8_strcmp_sizes(const char *s1, gsize n1, const char *s2, gsize n2) } } -int -rspamd_utf8_strcmp(const char *s1, const char *s2, gsize n) +int rspamd_utf8_strcmp(const char *s1, const char *s2, gsize n) { return rspamd_utf8_strcmp_sizes(s1, n, s2, n); } -TEST_SUITE("utf8 utils") { -TEST_CASE("utf8 normalise") { - std::tuple<const char *, const char *, int> cases[] = { +TEST_SUITE("utf8 utils") +{ + TEST_CASE("utf8 normalise") + { + std::tuple<const char *, const char *, int> cases[] = { {"abc", "abc", RSPAMD_UNICODE_NORM_NORMAL}, {"тест", "тест", RSPAMD_UNICODE_NORM_NORMAL}, /* Zero width spaces */ - {"\xE2\x80\x8B""те""\xE2\x80\x8B""ст", "тест", RSPAMD_UNICODE_NORM_ZERO_SPACES}, + {"\xE2\x80\x8B" + "те" + "\xE2\x80\x8B" + "ст", + "тест", RSPAMD_UNICODE_NORM_ZERO_SPACES}, /* Special case of diacritic */ {"13_\u0020\u0308\u0301\u038e\u03ab", "13_ ̈́ΎΫ", RSPAMD_UNICODE_NORM_UNNORMAL}, // String containing a non-joiner character - { "س\u200Cت", "ست", RSPAMD_UNICODE_NORM_ZERO_SPACES }, + {"س\u200Cت", "ست", RSPAMD_UNICODE_NORM_ZERO_SPACES}, // String containing a soft hyphen - { "in\u00ADter\u00ADest\u00ADing", "interesting", RSPAMD_UNICODE_NORM_ZERO_SPACES }, + {"in\u00ADter\u00ADest\u00ADing", "interesting", RSPAMD_UNICODE_NORM_ZERO_SPACES}, // String with ligature - { "fish", "fish", RSPAMD_UNICODE_NORM_UNNORMAL }, + {"fish", "fish", RSPAMD_UNICODE_NORM_UNNORMAL}, // String with accented characters and zero-width spaces - { "café\u200Blatté\u200C", "cafélatté", RSPAMD_UNICODE_NORM_ZERO_SPACES }, + {"café\u200Blatté\u200C", "cafélatté", RSPAMD_UNICODE_NORM_ZERO_SPACES}, /* Same with zw spaces */ {"13\u200C_\u0020\u0308\u0301\u038e\u03ab", "13_ ̈́ΎΫ", - RSPAMD_UNICODE_NORM_UNNORMAL|RSPAMD_UNICODE_NORM_ZERO_SPACES}, + RSPAMD_UNICODE_NORM_UNNORMAL | RSPAMD_UNICODE_NORM_ZERO_SPACES}, /* Buffer overflow case */ - {"u\xC2\xC2\xC2\xC2\xC2\xC2""abcdef""abcdef", "u\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD", - RSPAMD_UNICODE_NORM_UNNORMAL|RSPAMD_UNICODE_NORM_ERROR}, + {"u\xC2\xC2\xC2\xC2\xC2\xC2" + "abcdef" + "abcdef", + "u\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD", + RSPAMD_UNICODE_NORM_UNNORMAL | RSPAMD_UNICODE_NORM_ERROR}, // String with a mix of special characters, ligatures, and zero-width spaces - { "fish\u200Bcafé\u200C\u200Dlatté\u200D\u00AD", "fishcafé\u200Dlatté\u200D", RSPAMD_UNICODE_NORM_UNNORMAL | RSPAMD_UNICODE_NORM_ZERO_SPACES }, + {"fish\u200Bcafé\u200C\u200Dlatté\u200D\u00AD", "fishcafé\u200Dlatté\u200D", RSPAMD_UNICODE_NORM_UNNORMAL | RSPAMD_UNICODE_NORM_ZERO_SPACES}, // Empty string - { "", "", RSPAMD_UNICODE_NORM_NORMAL}, - }; + {"", "", RSPAMD_UNICODE_NORM_NORMAL}, + }; - for (const auto &c : cases) { - std::string cpy{std::get<0>(c)}; - auto ns = cpy.size(); - auto res = rspamd_normalise_unicode_inplace(cpy.data(), &ns); - cpy.resize(ns); - CHECK(cpy == std::string(std::get<1>(c))); - CHECK(res == std::get<2>(c)); + for (const auto &c: cases) { + std::string cpy{std::get<0>(c)}; + auto ns = cpy.size(); + auto res = rspamd_normalise_unicode_inplace(cpy.data(), &ns); + cpy.resize(ns); + CHECK(cpy == std::string(std::get<1>(c))); + CHECK(res == std::get<2>(c)); + } } -} -TEST_CASE("utf8 trim") { - std::pair<const char *, const char *> cases[] = { - {" \u200B""abc ", "abc"}, - {" ", ""}, + TEST_CASE("utf8 trim") + { + std::pair<const char *, const char *> cases[] = { + {" \u200B" + "abc ", + "abc"}, + {" ", ""}, {" a", "a"}, {"a ", "a"}, - {"a a", "a a"}, - {"abc", "abc"}, + {"a a", "a a"}, + {"abc", "abc"}, {"a ", "a"}, {" abc ", "abc"}, {" abc ", "abc"}, - {" \xE2\x80\x8B""a\xE2\x80\x8B""bc ", "a\xE2\x80\x8B""bc"}, - {" \xE2\x80\x8B""abc\xE2\x80\x8B ", "abc"}, - {" \xE2\x80\x8B""abc \xE2\x80\x8B ", "abc"}, - }; + {" \xE2\x80\x8B" + "a\xE2\x80\x8B" + "bc ", + "a\xE2\x80\x8B" + "bc"}, + {" \xE2\x80\x8B" + "abc\xE2\x80\x8B ", + "abc"}, + {" \xE2\x80\x8B" + "abc \xE2\x80\x8B ", + "abc"}, + }; - for (const auto &c : cases) { - std::string cpy{c.first}; - auto ns = cpy.size(); - auto *nstart = rspamd_string_unicode_trim_inplace(cpy.data(), &ns); - std::string res{nstart, ns}; - CHECK(res == std::string{c.second}); + for (const auto &c: cases) { + std::string cpy{c.first}; + auto ns = cpy.size(); + auto *nstart = rspamd_string_unicode_trim_inplace(cpy.data(), &ns); + std::string res{nstart, ns}; + CHECK(res == std::string{c.second}); + } } -} -TEST_CASE("utf8 strcmp") { - std::tuple<const char *, const char *, int, int> cases[] = { + TEST_CASE("utf8 strcmp") + { + std::tuple<const char *, const char *, int, int> cases[] = { {"abc", "abc", -1, 0}, - {"", "", -1, 0}, + {"", "", -1, 0}, {"aBc", "AbC", -1, 0}, {"abc", "ab", 2, 0}, {"теСт", "ТесТ", -1, 0}, @@ -343,52 +363,58 @@ TEST_CASE("utf8 strcmp") { {"abc", "ABD", -1, -1}, {"\0a\0", "\0a\1", 2, 0}, {"\0a\0", "\0b\1", 3, -1}, - }; + }; - for (const auto &c : cases) { - auto [s1, s2, n, expected] = c; - if (n == -1) { - n = MIN(strlen(s1), strlen(s2)); - } - SUBCASE((std::string("test case: ") + s1 + " <=> " + s2).c_str()) { - auto ret = rspamd_utf8_strcmp(s1, s2, n); - CHECK(ret == expected); + for (const auto &c: cases) { + auto [s1, s2, n, expected] = c; + if (n == -1) { + n = MIN(strlen(s1), strlen(s2)); + } + SUBCASE((std::string("test case: ") + s1 + " <=> " + s2).c_str()) + { + auto ret = rspamd_utf8_strcmp(s1, s2, n); + CHECK(ret == expected); + } } } -} -TEST_CASE("transliterate") { - using namespace std::literals; - std::tuple<std::string_view, const char *> cases[] = { - {"abc"sv, "abc"}, - {""sv, ""}, - {"тест"sv, "test"}, - // Diacritic to ascii - {"Ύ"sv, "y"}, - // Chinese to pinyin - {"你好"sv, "ni hao"}, - // Japanese to romaji - {"こんにちは"sv, "konnichiha"}, - // Devanagari to latin - {"नमस्ते"sv, "namaste"}, - // Arabic to latin - {"مرحبا"sv, "mrhba"}, - // Remove of punctuation - {"a.b.c"sv, "abc"}, - // Lowercase - {"ABC"sv, "abc"}, - // Remove zero-width spaces - {"\xE2\x80\x8B""abc\xE2\x80\x8B""def"sv, "abcdef"}, - }; + TEST_CASE("transliterate") + { + using namespace std::literals; + std::tuple<std::string_view, const char *> cases[] = { + {"abc"sv, "abc"}, + {""sv, ""}, + {"тест"sv, "test"}, + // Diacritic to ascii + {"Ύ"sv, "y"}, + // Chinese to pinyin + {"你好"sv, "ni hao"}, + // Japanese to romaji + {"こんにちは"sv, "konnichiha"}, + // Devanagari to latin + {"नमस्ते"sv, "namaste"}, + // Arabic to latin + {"مرحبا"sv, "mrhba"}, + // Remove of punctuation + {"a.b.c"sv, "abc"}, + // Lowercase + {"ABC"sv, "abc"}, + // Remove zero-width spaces + {"\xE2\x80\x8B" + "abc\xE2\x80\x8B" + "def"sv, + "abcdef"}, + }; - for (const auto &c : cases) { - auto [s1, s2] = c; - SUBCASE((std::string("test case: ") + std::string(s1) + " => " + s2).c_str()) { - gsize tlen; - auto *ret = rspamd_utf8_transliterate(s1.data(), s1.length(), &tlen); - CHECK(tlen == strlen(s2)); - CHECK(strcmp(s2, ret) == 0); + for (const auto &c: cases) { + auto [s1, s2] = c; + SUBCASE((std::string("test case: ") + std::string(s1) + " => " + s2).c_str()) + { + gsize tlen; + auto *ret = rspamd_utf8_transliterate(s1.data(), s1.length(), &tlen); + CHECK(tlen == strlen(s2)); + CHECK(strcmp(s2, ret) == 0); + } } } -} }
\ No newline at end of file diff --git a/src/libutil/cxx/utf8_util.h b/src/libutil/cxx/utf8_util.h index 7f28ea45e..044beae36 100644 --- a/src/libutil/cxx/utf8_util.h +++ b/src/libutil/cxx/utf8_util.h @@ -22,7 +22,7 @@ #include "config.h" #include "mem_pool.h" -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -32,7 +32,7 @@ extern "C" { * @param len length * @return new length of the string trimmed */ -const char* rspamd_string_unicode_trim_inplace (const char *str, size_t *len); +const char *rspamd_string_unicode_trim_inplace(const char *str, size_t *len); enum rspamd_utf8_normalise_result { RSPAMD_UNICODE_NORM_NORMAL = 0, @@ -58,7 +58,7 @@ enum rspamd_utf8_normalise_result rspamd_normalise_unicode_inplace(gchar *start, * @param target_len * @return a new string that should be freed with g_free */ -gchar* rspamd_utf8_transliterate(const gchar *start, gsize len, gsize *target_len); +gchar *rspamd_utf8_transliterate(const gchar *start, gsize len, gsize *target_len); /** * Compare two strings using libicu collator @@ -78,8 +78,8 @@ int rspamd_utf8_strcmp(const char *s1, const char *s2, gsize n); */ int rspamd_utf8_strcmp_sizes(const char *s1, gsize n1, const char *s2, gsize n2); -#ifdef __cplusplus +#ifdef __cplusplus } #endif -#endif //RSPAMD_UTF8_UTIL_H +#endif//RSPAMD_UTF8_UTIL_H diff --git a/src/libutil/cxx/util.hxx b/src/libutil/cxx/util.hxx index 2d009c6cd..9ef2f6295 100644 --- a/src/libutil/cxx/util.hxx +++ b/src/libutil/cxx/util.hxx @@ -33,16 +33,14 @@ namespace rspamd { /* * Creates std::array from a standard C style array with automatic size calculation */ -template <typename... Ts> -constexpr auto array_of(Ts&&... t) -> std::array<typename std::decay_t<typename std::common_type_t<Ts...>>, sizeof...(Ts)> +template<typename... Ts> +constexpr auto array_of(Ts &&...t) -> std::array<typename std::decay_t<typename std::common_type_t<Ts...>>, sizeof...(Ts)> { using T = typename std::decay_t<typename std::common_type_t<Ts...>>; - return {{ std::forward<T>(t)... }}; + return {{std::forward<T>(t)...}}; } -template<class C, class K, class V = typename C::mapped_type, typename std::enable_if_t< - std::is_constructible_v<typename C::key_type, K> - && std::is_constructible_v<typename C::mapped_type, V>, bool> = false> +template<class C, class K, class V = typename C::mapped_type, typename std::enable_if_t<std::is_constructible_v<typename C::key_type, K> && std::is_constructible_v<typename C::mapped_type, V>, bool> = false> constexpr auto find_map(const C &c, const K &k) -> std::optional<std::reference_wrapper<const V>> { auto f = c.find(k); @@ -55,15 +53,14 @@ constexpr auto find_map(const C &c, const K &k) -> std::optional<std::reference_ } -template <typename _It> +template<typename _It> inline constexpr auto make_string_view_from_it(_It begin, _It end) { using result_type = std::string_view; return result_type{((begin != end) ? &*begin : nullptr), - (typename result_type::size_type)std::max(std::distance(begin, end), - (typename result_type::difference_type)0) - }; + (typename result_type::size_type) std::max(std::distance(begin, end), + (typename result_type::difference_type) 0)}; } /** @@ -74,8 +71,7 @@ inline constexpr auto make_string_view_from_it(_It begin, _It end) * @param functor * @return */ -template<class S, class F, typename std::enable_if_t<std::is_invocable_v<F, std::string_view> && - std::is_constructible_v<std::string_view, S>, bool> = true> +template<class S, class F, typename std::enable_if_t<std::is_invocable_v<F, std::string_view> && std::is_constructible_v<std::string_view, S>, bool> = true> inline auto string_foreach_line(const S &input, const F &functor) { auto it = input.begin(); @@ -105,7 +101,7 @@ inline auto string_split_on(const S &input, std::string_view::value_type chr) -> while (*pos == chr && pos != input.end()) { ++pos; } - auto last = std::string_view{pos, static_cast<std::size_t>(std::distance(pos, std::end(input)))}; + auto last = std::string_view{pos, static_cast<std::size_t>(std::distance(pos, std::end(input)))}; return {first, last}; } @@ -116,49 +112,73 @@ inline auto string_split_on(const S &input, std::string_view::value_type chr) -> /** * Enumerate for range loop */ -template <typename T, - typename TIter = decltype(std::begin(std::declval<T>())), - typename = decltype(std::end(std::declval<T>()))> -constexpr auto enumerate(T && iterable) +template<typename T, + typename TIter = decltype(std::begin(std::declval<T>())), + typename = decltype(std::end(std::declval<T>()))> +constexpr auto enumerate(T &&iterable) { - struct iterator - { + struct iterator { size_t i; TIter iter; - bool operator != (const iterator & other) const { return iter != other.iter; } - void operator ++ () { ++i; ++iter; } - auto operator * () const { return std::tie(i, *iter); } + bool operator!=(const iterator &other) const + { + return iter != other.iter; + } + void operator++() + { + ++i; + ++iter; + } + auto operator*() const + { + return std::tie(i, *iter); + } }; - struct iterable_wrapper - { + struct iterable_wrapper { T iterable; - auto begin() { return iterator{ 0, std::begin(iterable) }; } - auto end() { return iterator{ 0, std::end(iterable) }; } + auto begin() + { + return iterator{0, std::begin(iterable)}; + } + auto end() + { + return iterator{0, std::end(iterable)}; + } }; - return iterable_wrapper{ std::forward<T>(iterable) }; + return iterable_wrapper{std::forward<T>(iterable)}; } /** * Allocator that cleans up memory in a secure way on destruction * @tparam T */ -template <class T> class secure_mem_allocator : public std::allocator<T> -{ +template<class T> +class secure_mem_allocator : public std::allocator<T> { public: using value_type = typename std::allocator<T>::value_type; using size_type = typename std::allocator<T>::size_type; - template<class U> struct rebind { typedef secure_mem_allocator<U> other; }; + template<class U> + struct rebind { + typedef secure_mem_allocator<U> other; + }; secure_mem_allocator() noexcept = default; - secure_mem_allocator(const secure_mem_allocator &_) noexcept : std::allocator<T>(_) {} - template <class U> explicit secure_mem_allocator(const secure_mem_allocator<U>&) noexcept {} + secure_mem_allocator(const secure_mem_allocator &_) noexcept + : std::allocator<T>(_) + { + } + template<class U> + explicit secure_mem_allocator(const secure_mem_allocator<U> &) noexcept + { + } - void deallocate(value_type *p, size_type num) noexcept { - rspamd_explicit_memzero((void *)p, num); + void deallocate(value_type *p, size_type num) noexcept + { + rspamd_explicit_memzero((void *) p, num); std::allocator<T>::deallocate(p, num); } }; -} +}// namespace rspamd -#endif //RSPAMD_UTIL_HXX +#endif//RSPAMD_UTIL_HXX diff --git a/src/libutil/cxx/util_tests.cxx b/src/libutil/cxx/util_tests.cxx index 6d7f4dd55..2b3092779 100644 --- a/src/libutil/cxx/util_tests.cxx +++ b/src/libutil/cxx/util_tests.cxx @@ -22,23 +22,25 @@ using namespace rspamd; using namespace std::literals::string_view_literals; -TEST_SUITE("cxx utils") { -TEST_CASE("string_split_on") { - std::tuple<std::string_view, char, std::pair<std::string_view, std::string_view>> cases[] = { - {"test test"sv, ' ', std::pair{"test"sv, "test"sv}}, - {"test test"sv, ' ', std::pair{"test"sv, "test"sv}}, - {"test test "sv, ' ', std::pair{"test"sv, "test "sv}}, - {"testtest "sv, ' ', std::pair{"testtest"sv, ""sv}}, - {" testtest "sv, ' ', std::pair{""sv, "testtest "sv}}, - {"testtest"sv, ' ', std::pair{"testtest"sv, ""sv}}, - {""sv, ' ', std::pair{""sv, ""sv}}, - }; +TEST_SUITE("cxx utils") +{ + TEST_CASE("string_split_on") + { + std::tuple<std::string_view, char, std::pair<std::string_view, std::string_view>> cases[] = { + {"test test"sv, ' ', std::pair{"test"sv, "test"sv}}, + {"test test"sv, ' ', std::pair{"test"sv, "test"sv}}, + {"test test "sv, ' ', std::pair{"test"sv, "test "sv}}, + {"testtest "sv, ' ', std::pair{"testtest"sv, ""sv}}, + {" testtest "sv, ' ', std::pair{""sv, "testtest "sv}}, + {"testtest"sv, ' ', std::pair{"testtest"sv, ""sv}}, + {""sv, ' ', std::pair{""sv, ""sv}}, + }; - for (const auto& c : cases) { - auto res = string_split_on(std::get<0>(c), std::get<1>(c)); - auto expected = std::get<2>(c); - CHECK(res.first == expected.first); - CHECK(res.second == expected.second); + for (const auto &c: cases) { + auto res = string_split_on(std::get<0>(c), std::get<1>(c)); + auto expected = std::get<2>(c); + CHECK(res.first == expected.first); + CHECK(res.second == expected.second); + } } -} }
\ No newline at end of file |