From: Remi Gacogne Date: Mon, 18 Mar 2024 09:19:06 +0000 (+0100) Subject: misc: Implement pdns::UniqueFilePtr X-Git-Tag: rec-5.1.0-alpha1~117^2~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=20b2f2041a04a2e16f6bf4781c177a6aa3adec2b;p=thirdparty%2Fpdns.git misc: Implement pdns::UniqueFilePtr Using a deleter instead of `decltype(&fclose)` has two big advantages: - the deleter is included in the type and does not have to be passed when creating a new object (easier to use, less memory usage, in theory better inlining) - we avoid the annoying `ignoring attributes on template argument ‘int (*)(FILE*)’` warning from the compiler, which is there because `fclose` is tagged as `__nonnull((1))` --- diff --git a/pdns/misc.cc b/pdns/misc.cc index 3e9fa6b68a..71518f1790 100644 --- a/pdns/misc.cc +++ b/pdns/misc.cc @@ -861,7 +861,7 @@ bool stringfgets(FILE* fp, std::string& line) bool readFileIfThere(const char* fname, std::string* line) { line->clear(); - auto fp = std::unique_ptr(fopen(fname, "r"), fclose); + auto fp = pdns::UniqueFilePtr(fopen(fname, "r")); if (!fp) { return false; } @@ -1751,9 +1751,16 @@ bool constantTimeStringEquals(const std::string& a, const std::string& b) namespace pdns { +struct CloseDirDeleter +{ + void operator()(DIR* dir) { + closedir(dir); + } +}; + std::optional visit_directory(const std::string& directory, const std::function& visitor) { - auto dirHandle = std::unique_ptr(opendir(directory.c_str()), closedir); + auto dirHandle = std::unique_ptr(opendir(directory.c_str())); if (!dirHandle) { auto err = errno; return std::string("Error opening directory '" + directory + "': " + stringerror(err)); diff --git a/pdns/misc.hh b/pdns/misc.hh index 209de32e06..8d63dd54d7 100644 --- a/pdns/misc.hh +++ b/pdns/misc.hh @@ -836,4 +836,20 @@ private: namespace pdns { [[nodiscard]] std::optional visit_directory(const std::string& directory, const std::function& visitor); + +struct FilePtrDeleter +{ + /* using a deleter instead of decltype(&fclose) has two big advantages: + - the deleter is included in the type and does not have to be passed + when creating a new object (easier to use, less memory usage, in theory + better inlining) + - we avoid the annoying "ignoring attributes on template argument ‘int (*)(FILE*)’" + warning from the compiler, which is there because fclose is tagged as __nonnull((1)) + */ + void operator()(FILE* filePtr) { + fclose(filePtr); + } +}; + +using UniqueFilePtr = std::unique_ptr; }