LCOV - code coverage report
Current view: top level - src - pl_alloc.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 1 1 100.0 %
Date: 2025-03-29 09:04:10 Functions: 0 0 -
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * This file is part of libplacebo.
       3                 :            :  *
       4                 :            :  * libplacebo is free software; you can redistribute it and/or
       5                 :            :  * modify it under the terms of the GNU Lesser General Public
       6                 :            :  * License as published by the Free Software Foundation; either
       7                 :            :  * version 2.1 of the License, or (at your option) any later version.
       8                 :            :  *
       9                 :            :  * libplacebo is distributed in the hope that it will be useful,
      10                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12                 :            :  * GNU Lesser General Public License for more details.
      13                 :            :  *
      14                 :            :  * You should have received a copy of the GNU Lesser General Public
      15                 :            :  * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
      16                 :            :  */
      17                 :            : 
      18                 :            : #pragma once
      19                 :            : 
      20                 :            : #include <stdalign.h>
      21                 :            : #include <stdarg.h>
      22                 :            : #include <stddef.h>
      23                 :            : #include <stdint.h>
      24                 :            : #include <string.h>
      25                 :            : 
      26                 :            : // Unlike standard malloc, `size` may be 0, in which case this returns an empty
      27                 :            : // allocation which can still be used as a parent for other allocations.
      28                 :            : void *pl_alloc(void *parent, size_t size);
      29                 :            : void *pl_zalloc(void *parent, size_t size);
      30                 :            : void *pl_realloc(void *parent, void *ptr, size_t size);
      31                 :            : 
      32                 :            : static inline void *pl_calloc(void *parent, size_t count, size_t size)
      33                 :            : {
      34                 :       7079 :     return pl_zalloc(parent, count * size);
      35                 :            : }
      36                 :            : 
      37                 :            : #define pl_tmp(parent) pl_alloc(parent, 0)
      38                 :            : 
      39                 :            : // Variants of the above which resolve to sizeof(*ptr)
      40                 :            : #define pl_alloc_ptr(parent, ptr) \
      41                 :            :     (__typeof__(ptr)) pl_alloc(parent, sizeof(*(ptr)))
      42                 :            : #define pl_zalloc_ptr(parent, ptr) \
      43                 :            :     (__typeof__(ptr)) pl_zalloc(parent, sizeof(*(ptr)))
      44                 :            : #define pl_calloc_ptr(parent, num, ptr) \
      45                 :            :     (__typeof__(ptr)) pl_calloc(parent, num, sizeof(*(ptr)))
      46                 :            : 
      47                 :            : // Helper function to allocate a struct and immediately assign it
      48                 :            : #define pl_alloc_struct(parent, type, ...) \
      49                 :            :     (type *) pl_memdup(parent, &(type) __VA_ARGS__, sizeof(type))
      50                 :            : 
      51                 :            : // Free an allocation and its children (recursively)
      52                 :            : void pl_free(void *ptr);
      53                 :            : void pl_free_children(void *ptr);
      54                 :            : 
      55                 :            : #define pl_free_ptr(ptr)    \
      56                 :            :     do {                    \
      57                 :            :         pl_free(*(ptr));    \
      58                 :            :         *(ptr) = NULL;      \
      59                 :            :     } while (0)
      60                 :            : 
      61                 :            : // Get the current size of an allocation.
      62                 :            : size_t pl_get_size(const void *ptr);
      63                 :            : 
      64                 :            : #define pl_grow(parent, ptr, size)                      \
      65                 :            :     do {                                                \
      66                 :            :         size_t _size = (size);                          \
      67                 :            :         if (_size > pl_get_size(*(ptr)))                \
      68                 :            :             *(ptr) = pl_realloc(parent, *(ptr), _size); \
      69                 :            :     } while (0)
      70                 :            : 
      71                 :            : // Reparent an allocation onto a new parent
      72                 :            : void *pl_steal(void *parent, void *ptr);
      73                 :            : 
      74                 :            : // Wrapper functions around common string utilities
      75                 :            : void *pl_memdup(void *parent, const void *ptr, size_t size);
      76                 :            : char *pl_str0dup0(void *parent, const char *str);
      77                 :            : char *pl_strndup0(void *parent, const char *str, size_t size);
      78                 :            : 
      79                 :            : #define pl_memdup_ptr(parent, ptr) \
      80                 :            :     (__typeof__(ptr)) pl_memdup(parent, ptr, sizeof(*(ptr)))
      81                 :            : 
      82                 :            : // Helper functions for allocating public/private pairs, done by allocating
      83                 :            : // `priv` at the address of `pub` + sizeof(pub), rounded up to the maximum
      84                 :            : // alignment requirements.
      85                 :            : 
      86                 :            : #define PL_ALIGN_MEM(size) PL_ALIGN2(size, alignof(max_align_t))
      87                 :            : 
      88                 :            : #define PL_PRIV(pub) \
      89                 :            :     (void *) ((uintptr_t) (pub) + PL_ALIGN_MEM(sizeof(*(pub))))
      90                 :            : 
      91                 :            : #define pl_alloc_obj(parent, ptr, priv) \
      92                 :            :     (__typeof__(ptr)) pl_alloc(parent, PL_ALIGN_MEM(sizeof(*(ptr))) + sizeof(priv))
      93                 :            : 
      94                 :            : #define pl_zalloc_obj(parent, ptr, priv) \
      95                 :            :     (__typeof__(ptr)) pl_zalloc(parent, PL_ALIGN_MEM(sizeof(*(ptr))) + sizeof(priv))
      96                 :            : 
      97                 :            : // Helper functions for dealing with arrays
      98                 :            : 
      99                 :            : #define PL_ARRAY(type) struct { type *elem; int num; }
     100                 :            : 
     101                 :            : #define PL_ARRAY_REALLOC(parent, arr, len)                                      \
     102                 :            :     do {                                                                        \
     103                 :            :         size_t _new_size = (len) * sizeof((arr).elem[0]);                       \
     104                 :            :         (arr).elem = pl_realloc((void *) parent, (arr).elem, _new_size);        \
     105                 :            :     } while (0)
     106                 :            : 
     107                 :            : #define PL_ARRAY_RESIZE(parent, arr, len)                                       \
     108                 :            :     do {                                                                        \
     109                 :            :         size_t _avail = pl_get_size((arr).elem) / sizeof((arr).elem[0]);        \
     110                 :            :         size_t _min_len = (len);                                                \
     111                 :            :         if (_avail < _min_len)                                                  \
     112                 :            :             PL_ARRAY_REALLOC(parent, arr, _min_len);                            \
     113                 :            :     } while (0)
     114                 :            : 
     115                 :            : #define PL_ARRAY_MEMDUP(parent, arr, ptr, len)                                  \
     116                 :            :     do {                                                                        \
     117                 :            :         size_t _len = (len);                                                    \
     118                 :            :         PL_ARRAY_RESIZE(parent, arr, _len);                                     \
     119                 :            :         memcpy((arr).elem, ptr, _len * sizeof((arr).elem[0]));                  \
     120                 :            :         (arr).num = _len;                                                       \
     121                 :            :     } while (0)
     122                 :            : 
     123                 :            : #define PL_ARRAY_GROW(parent, arr)                                              \
     124                 :            :     do {                                                                        \
     125                 :            :         size_t _avail = pl_get_size((arr).elem) / sizeof((arr).elem[0]);        \
     126                 :            :         if (_avail < 10) {                                                      \
     127                 :            :             PL_ARRAY_REALLOC(parent, arr, 10);                                  \
     128                 :            :         } else if ((arr).num == _avail) {                                       \
     129                 :            :             PL_ARRAY_REALLOC(parent, arr, (arr).num * 1.5);                     \
     130                 :            :         } else {                                                                \
     131                 :            :             assert((arr).elem);                                                 \
     132                 :            :         }                                                                       \
     133                 :            :     } while (0)
     134                 :            : 
     135                 :            : #define PL_ARRAY_APPEND(parent, arr, ...)                                       \
     136                 :            :     do {                                                                        \
     137                 :            :         PL_ARRAY_GROW(parent, arr);                                             \
     138                 :            :         (arr).elem[(arr).num++] = __VA_ARGS__;                                  \
     139                 :            :     } while (0)
     140                 :            : 
     141                 :            : #define PL_ARRAY_CONCAT(parent, to, from)                                       \
     142                 :            :     do {                                                                        \
     143                 :            :         if ((from).num) {                                                       \
     144                 :            :             PL_ARRAY_RESIZE(parent, to, (to).num + (from).num);                 \
     145                 :            :             memmove(&(to).elem[(to).num], (from).elem,                          \
     146                 :            :                     (from).num * sizeof((from).elem[0]));                       \
     147                 :            :             (to).num += (from).num;                                             \
     148                 :            :         }                                                                       \
     149                 :            :     } while (0)
     150                 :            : 
     151                 :            : #define PL_ARRAY_REMOVE_RANGE(arr, idx, count)                                  \
     152                 :            :     do {                                                                        \
     153                 :            :         ptrdiff_t _idx = (idx);                                                 \
     154                 :            :         if (_idx < 0)                                                           \
     155                 :            :             _idx += (arr).num;                                                  \
     156                 :            :         size_t _count = (count);                                                \
     157                 :            :         assert(_idx >= 0 && _idx + _count <= (arr).num);                        \
     158                 :            :         memmove(&(arr).elem[_idx], &(arr).elem[_idx + _count],                  \
     159                 :            :                 ((arr).num - _idx - _count) * sizeof((arr).elem[0]));           \
     160                 :            :         (arr).num -= _count;                                                    \
     161                 :            :     } while (0)
     162                 :            : 
     163                 :            : #define PL_ARRAY_REMOVE_AT(arr, idx) PL_ARRAY_REMOVE_RANGE(arr, idx, 1)
     164                 :            : 
     165                 :            : #define PL_ARRAY_INSERT_AT(parent, arr, idx, ...)                               \
     166                 :            :     do {                                                                        \
     167                 :            :         ptrdiff_t _idx = (idx);                                                 \
     168                 :            :         if (_idx < 0)                                                           \
     169                 :            :             _idx += (arr).num + 1;                                              \
     170                 :            :         assert(_idx >= 0 && _idx <= (arr).num);                                 \
     171                 :            :         PL_ARRAY_GROW(parent, arr);                                             \
     172                 :            :         memmove(&(arr).elem[_idx + 1], &(arr).elem[_idx],                       \
     173                 :            :                 ((arr).num++ - _idx) * sizeof((arr).elem[0]));                  \
     174                 :            :         (arr).elem[_idx] = __VA_ARGS__;                                         \
     175                 :            :     } while (0)
     176                 :            : 
     177                 :            : // Returns whether or not there was any element to pop
     178                 :            : #define PL_ARRAY_POP(arr, out)                                                  \
     179                 :            :     ((arr).num > 0                                                              \
     180                 :            :         ? (*(out) = (arr).elem[--(arr).num], true)                              \
     181                 :            :         : false                                                                 \
     182                 :            :     )
     183                 :            : 
     184                 :            : // Wrapper for dealing with non-PL_ARRAY arrays
     185                 :            : #define PL_ARRAY_APPEND_RAW(parent, arr, idxvar, ...)                           \
     186                 :            :     do {                                                                        \
     187                 :            :         PL_ARRAY(__typeof__((arr)[0])) _arr = { (arr), (idxvar) };              \
     188                 :            :         PL_ARRAY_APPEND(parent, _arr, __VA_ARGS__);                             \
     189                 :            :         (arr) = _arr.elem;                                                      \
     190                 :            :         (idxvar) = _arr.num;                                                    \
     191                 :            :     } while (0)

Generated by: LCOV version 1.16