Left this as an ff_ funtion for now since it's only used by the j2k
code

/Tomas
From 5d36d431ffe4c8ba0f698d0c288ebc16b83f0bbc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= <g...@haerdin.se>
Date: Tue, 14 Jun 2022 13:35:18 +0200
Subject: [PATCH 06/13] lavu/mem: Add ff_fast_recalloc()

---
 libavutil/mem.c | 24 +++++++++++++++++++++
 libavutil/mem.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/libavutil/mem.c b/libavutil/mem.c
index a0c9a42849..7781b715a0 100644
--- a/libavutil/mem.c
+++ b/libavutil/mem.c
@@ -530,6 +530,30 @@ void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
     return ptr;
 }
 
+int ff_fast_recalloc(void *ptr, unsigned int *size, size_t nelem, size_t elsize)
+{
+    void *val;
+    void *new_ptr;
+    unsigned int new_size = *size;
+    size_t product;
+    int ret;
+    memcpy(&val, ptr, sizeof(val));
+
+    if ((ret = av_size_mult(nelem, elsize, &product)) < 0)
+        return ret;
+
+    if (!(new_ptr = av_fast_realloc(val, &new_size, product)))
+        return AVERROR(ENOMEM);
+
+    if (new_size > *size) {
+        memset((uint8_t*)new_ptr + *size, 0, new_size - *size);
+        *size = new_size;
+        memcpy(ptr, &new_ptr, sizeof(new_ptr));
+    }
+
+    return 0;
+}
+
 static inline void fast_malloc(void *ptr, unsigned int *size, size_t min_size, int zero_realloc)
 {
     size_t max_size;
diff --git a/libavutil/mem.h b/libavutil/mem.h
index d91174196c..74abf3dce2 100644
--- a/libavutil/mem.h
+++ b/libavutil/mem.h
@@ -380,6 +380,61 @@ int av_reallocp_array(void *ptr, size_t nmemb, size_t size);
  */
 void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size);
 
+/**
+ * Reallocate the pointed-to buffer if it is not large enough, otherwise do
+ * nothing. Old data is memcpy()'d to the start of the new buffer. The newly
+ * allocated space at the end of the buffer is zero-initialized. In other
+ * words the buffer is expanded with zeroes when necessary.
+ *
+ * If the pointed-to buffer is `NULL`, then a new zero-initialized buffer is
+ * allocated.
+ *
+ * If the pointed-to buffer is not large enough, and reallocation fails,
+ * `AVERROR(ENOMEM)` is returned.
+ *
+ * If nelem*elsize is too large then `AVERROR(EINVAL)` is returned.
+ *
+ * Contrary to av_fast_malloc(), *ptr and *size are not touched in case of
+ * error, to allow for proper cleanup.
+ *
+ * *ptr is not guaranteed to be an exact multiple of elsize bytes.
+ *
+ * This function is intended for use with arrays of structures that contain
+ * pointers that are allowed to grow and typically don't shrink.
+ *
+ * A typical use pattern follows:
+ *
+ * @code{.c}
+ * int foo_work(SomeContext *s) {
+ *     if (ff_fast_recalloc(&s->foo, &s->foo_size, s->nfoo, sizeof(Foo)))
+ *         return AVERROR(ENOMEM);
+ *     for (x = 0; x < s->nfoo; x++)
+ *         do stuff with s->foo[x]
+ *     return 0;
+ * }
+ *
+ * void foo_close(SomeContext *s) {
+ *     // note the use of s->foo_size, not s->nfoo
+ *     for (x = 0; x < s->foo_size/sizeof(Foo); x++)
+ *         av_freep(&s->foo[x].bar);
+ *     av_freep(&s->foo);
+ * }
+ * @endcode
+ *
+ * @param[in,out] ptr      Pointer to pointer to an already allocated buffer.
+ *                         `*ptr` will be overwritten with pointer to new
+ *                         buffer on success and will be left alone on failure
+ * @param[in,out] size     Pointer to the size of buffer `*ptr`. `*size` is
+ *                         updated to the new allocated size and will be left
+ *                         along on failure.
+ * @param[in]     nelem    Number of desired elements in *ptr
+ * @param[in]     elsize   Size of each element in *ptr
+ * @return Zero on success, <0 on error.
+ * @see av_fast_realloc()
+ * @see av_fast_malloc()
+ */
+int ff_fast_recalloc(void *ptr, unsigned int *size, size_t nelem, size_t elsize);
+
 /**
  * Allocate a buffer, reusing the given one if large enough.
  *
-- 
2.30.2

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to