From 4cdb4e9daaba4bfdaf28552344f3d6aff49884d3 Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Fri, 27 Aug 2021 09:28:03 +0200
Subject: [PATCH] LIB: Add a way to do the `if (ptr) free(ptr)` in a generic
 way

---
 src/Lib/Audio.hh | 37 ++++++++++++++-----------------------
 src/Lib/Utils.hh | 16 ++++++++++++++++
 2 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/src/Lib/Audio.hh b/src/Lib/Audio.hh
index 3a7ad817..ee0efab5 100644
--- a/src/Lib/Audio.hh
+++ b/src/Lib/Audio.hh
@@ -37,24 +37,17 @@ public:
     class Stream final {
         VIVY_UNMOVABLE_OBJECT(Stream)
 
-        // All the needed deleters
-        static inline constexpr auto codecContexteleter = [](AVCodecContext *ptr) noexcept -> void {
-            if (ptr)
-                avcodec_free_context(&ptr);
-        };
-        static constexpr inline auto dataDeleter = [](double *ptr) noexcept -> void {
-            if (ptr)
-                av_free(ptr);
-        };
-        static constexpr inline auto avFrameDeleter = [](AVFrame *ptr) noexcept -> void {
-            if (ptr)
-                av_frame_free(&ptr);
-        };
-
-        static constexpr inline auto swrContenxtDeleter = [](SwrContext *swr) noexcept -> void {
-            if (swr)
-                swr_free(&swr);
-        };
+        static inline Utils::DeleterFunctionType<double> dataDeleter =
+            std::bind_front(Utils::freePtrIfNotNull<double>, av_free);
+
+        static inline Utils::DeleterFunctionType<AVCodecContext> codecContexteleter =
+            std::bind_front(Utils::freePPtrIfNotNull<AVCodecContext>, avcodec_free_context);
+
+        static inline Utils::DeleterFunctionType<AVFrame> avFrameDeleter =
+            std::bind_front(Utils::freePPtrIfNotNull<AVFrame>, av_frame_free);
+
+        static inline Utils::DeleterFunctionType<SwrContext> swrContenxtDeleter =
+            std::bind_front(Utils::freePPtrIfNotNull<SwrContext>, swr_free);
 
         // All the used types
         using AVCodecContextPtr = std::unique_ptr<AVCodecContext, decltype(codecContexteleter)>;
@@ -135,11 +128,9 @@ public:
 
 private:
     // Regarding the format
-    static inline constexpr auto avFormatContextDeleter =
-        [](AVFormatContext *ptr) noexcept -> void {
-        if (ptr)
-            avformat_free_context(ptr);
-    };
+    static inline Utils::DeleterFunctionType<AVFormatContext> avFormatContextDeleter =
+        std::bind_front(Utils::freePtrIfNotNull<AVFormatContext>, avformat_free_context);
+
     using AVFormatContextPtr = std::unique_ptr<AVFormatContext, decltype(avFormatContextDeleter)>;
     AVFormatContextPtr format{ avformat_alloc_context(), avFormatContextDeleter };
 
diff --git a/src/Lib/Utils.hh b/src/Lib/Utils.hh
index 3f065353..bf4d0025 100644
--- a/src/Lib/Utils.hh
+++ b/src/Lib/Utils.hh
@@ -172,6 +172,22 @@ QString getBaseName(const QString &) noexcept;
 
 void writeAssertLocation(const char *msg);
 
+template <typename T> using DeleterFunctionType = const std::function<void(T *)>;
+
+template <typename Type> static inline void
+freePtrIfNotNull(DeleterFunctionType<Type> callback, Type *ptr) noexcept
+{
+    if (ptr != nullptr)
+        callback(ptr);
+}
+
+template <typename Type> static inline void
+freePPtrIfNotNull(DeleterFunctionType<Type *> callback, Type *ptr) noexcept
+{
+    if (ptr != nullptr)
+        callback(&ptr);
+}
+
 struct OsSpecificAspects final {
 private:
     OsSpecificAspects() {}
-- 
GitLab