]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
misc: Implement pdns::UniqueFilePtr
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 18 Mar 2024 09:19:06 +0000 (10:19 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 18 Mar 2024 09:19:06 +0000 (10:19 +0100)
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))`

pdns/misc.cc
pdns/misc.hh

index 3e9fa6b68a05e8facd3b08c7e58df9085511633d..71518f1790d06e6ccc160a02c86404089b8eee34 100644 (file)
@@ -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<FILE, int(*)(FILE*)>(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<std::string> visit_directory(const std::string& directory, const std::function<bool(ino_t inodeNumber, const std::string_view& name)>& visitor)
 {
-  auto dirHandle = std::unique_ptr<DIR, decltype(&closedir)>(opendir(directory.c_str()), closedir);
+  auto dirHandle = std::unique_ptr<DIR, CloseDirDeleter>(opendir(directory.c_str()));
   if (!dirHandle) {
     auto err = errno;
     return std::string("Error opening directory '" + directory + "': " + stringerror(err));
index 209de32e060d23b9cdf91ca684be95f6feee9757..8d63dd54d7a84781eda490ab69fa69916990947f 100644 (file)
@@ -836,4 +836,20 @@ private:
 namespace pdns
 {
 [[nodiscard]] std::optional<std::string> visit_directory(const std::string& directory, const std::function<bool(ino_t inodeNumber, const std::string_view& name)>& 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<FILE, FilePtrDeleter>;
 }