cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

mem.h (16741B)


      1/*
      2 * Licensed to the Apache Software Foundation (ASF) under one
      3 * or more contributor license agreements.  See the NOTICE file
      4 * distributed with this work for additional information
      5 * regarding copyright ownership.  The ASF licenses this file
      6 * to you under the Apache License, Version 2.0 (the
      7 * "License"); you may not use this file except in compliance
      8 * with the License.  You may obtain a copy of the License at
      9 *
     10 *   http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing,
     13 * software distributed under the License is distributed on an
     14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15 * KIND, either express or implied.  See the License for the
     16 * specific language governing permissions and limitations
     17 * under the License.
     18 */
     19
     20#ifndef GUAC_MEM_H
     21#define GUAC_MEM_H
     22
     23/**
     24 * Provides convenience macros/functions for performing arithmetic on size_t
     25 * values and for allocating memory, particularly memory related to images,
     26 * audio, etc. where there are multiple factors affecting the final size.
     27 *
     28 * @file mem.h
     29 */
     30
     31#include "private/mem.h"
     32
     33#include <stddef.h>
     34
     35/**
     36 * Allocates a contiguous block of memory with the specified size, returning a
     37 * pointer to the first byte of that block of memory. If multiple sizes are
     38 * provided, these sizes are multiplied together to produce the final size of
     39 * the new block. If memory of the specified size cannot be allocated, or if
     40 * multiplying the sizes would result in integer overflow, guac_error is set
     41 * appropriately and NULL is returned.
     42 *
     43 * This macro is analogous to the standard malloc(), but accepts a list of size
     44 * factors instead of a single integer size.
     45 *
     46 * The pointer returned by guac_mem_alloc() SHOULD be freed with a subsequent call
     47 * to guac_mem_free(), but MAY instead be freed with a subsequent call to free().
     48 *
     49 * @param ...
     50 *     A series of one or more size_t values that should be multiplied together
     51 *     to produce the desired block size. At least one value MUST be provided.
     52 *
     53 * @returns
     54 *     A pointer to the first byte of the allocated block of memory, or NULL if
     55 *     such a block could not be allocated. If a block of memory could not be
     56 *     allocated, guac_error is set appropriately.
     57 */
     58#define guac_mem_alloc(...) \
     59    PRIV_guac_mem_alloc(                                                      \
     60        sizeof((const size_t[]) { __VA_ARGS__ }) / sizeof(const size_t),      \
     61        (const size_t[]) { __VA_ARGS__ }                                      \
     62    )
     63
     64/**
     65 * Allocates a contiguous block of memory with the specified size and with all
     66 * bytes initialized to zero, returning a pointer to the first byte of that
     67 * block of memory. If multiple sizes are provided, these sizes are multiplied
     68 * together to produce the final size of the new block. If memory of the
     69 * specified size cannot be allocated, or if multiplying the sizes would result
     70 * in integer overflow, guac_error is set appropriately and NULL is returned.
     71 *
     72 * This macro is analogous to the standard calloc(), but accepts a list of size
     73 * factors instead of a requiring exactly two integer sizes.
     74 *
     75 * The pointer returned by guac_mem_zalloc() SHOULD be freed with a subsequent call
     76 * to guac_mem_free(), but MAY instead be freed with a subsequent call to free().
     77 *
     78 * @param ...
     79 *     A series of one or more size_t values that should be multiplied together
     80 *     to produce the desired block size. At least one value MUST be provided.
     81 *
     82 * @returns
     83 *     A pointer to the first byte of the allocated block of memory, or NULL if
     84 *     such a block could not be allocated. If a block of memory could not be
     85 *     allocated, guac_error is set appropriately.
     86 */
     87#define guac_mem_zalloc(...) \
     88    PRIV_guac_mem_zalloc(                                                     \
     89        sizeof((const size_t[]) { __VA_ARGS__ }) / sizeof(const size_t),      \
     90        (const size_t[]) { __VA_ARGS__ }                                      \
     91    )
     92
     93/**
     94 * Multiplies together each of the given values, storing the result in a size_t
     95 * variable via the provided pointer. If the result of the multiplication
     96 * overflows the limits of a size_t, non-zero is returned to signal failure.
     97 *
     98 * If the multiplication operation fails, the nature of any result stored in
     99 * the provided pointer is undefined, as is whether a result is stored at all.
    100 *
    101 * For example, the following:
    102 * @code
    103 *     size_t some_result;
    104 *     int failed = guac_mem_ckd_mul(&some_result, a, b, c);
    105 * @endcode
    106 *
    107 * is equivalent in principle to:
    108 * @code
    109 *     size_t some_result = a * b * c;
    110 * @endcode
    111 *
    112 * except that it is possible for interested callers to handle overflow.
    113 *
    114 * @param result
    115 *     A pointer to the size_t variable that should receive the result of
    116 *     multiplying the given values.
    117 *
    118 * @param ...
    119 *     The size_t values that should be multiplied together.
    120 *
    121 * @returns
    122 *     Zero if the multiplication was successful and did not overflow the
    123 *     limits of a size_t, non-zero otherwise.
    124 */
    125#define guac_mem_ckd_mul(result, ...) \
    126    PRIV_guac_mem_ckd_mul(                                                    \
    127        result,                                                               \
    128        sizeof((const size_t[]) { __VA_ARGS__ }) / sizeof(const size_t),      \
    129        (const size_t[]) { __VA_ARGS__ }                                      \
    130    )
    131
    132/**
    133 * Adds together each of the given values, storing the result in a size_t
    134 * variable via the provided pointer. If the result of the addition overflows
    135 * the limits of a size_t, non-zero is returned to signal failure.
    136 *
    137 * If the addition operation fails, the nature of any result stored in the
    138 * provided pointer is undefined, as is whether a result is stored at all.
    139 *
    140 * For example, the following:
    141 * @code
    142 *     size_t some_result;
    143 *     int failed = guac_mem_ckd_add(&some_result, a, b, c);
    144 * @endcode
    145 *
    146 * is equivalent in principle to:
    147 * @code
    148 *     size_t some_result = a + b + c;
    149 * @endcode
    150 *
    151 * except that it is possible for interested callers to handle overflow.
    152 *
    153 * @param result
    154 *     A pointer to the size_t variable that should receive the result of
    155 *     adding the given values.
    156 *
    157 * @param ...
    158 *     The size_t values that should be added together.
    159 *
    160 * @returns
    161 *     Zero if the addition was successful and did not overflow the limits of a
    162 *     size_t, non-zero otherwise.
    163 */
    164#define guac_mem_ckd_add(result, ...) \
    165    PRIV_guac_mem_ckd_add(                                                    \
    166        result,                                                               \
    167        sizeof((const size_t[]) { __VA_ARGS__ }) / sizeof(const size_t),      \
    168        (const size_t[]) { __VA_ARGS__ }                                      \
    169    )
    170
    171/**
    172 * Subtracts each of the given values from each other, storing the result in a
    173 * size_t variable via the provided pointer. If the result of the subtraction
    174 * overflows the limits of a size_t (goes below zero), non-zero is returned to
    175 * signal failure.
    176 *
    177 * If the subtraction operation fails, the nature of any result stored in the
    178 * provided pointer is undefined, as is whether a result is stored at all.
    179 *
    180 * For example, the following:
    181 * @code
    182 *     size_t some_result;
    183 *     int failed = guac_mem_ckd_sub(&some_result, a, b, c);
    184 * @endcode
    185 *
    186 * is equivalent in principle to:
    187 * @code
    188 *     size_t some_result = a - b - c;
    189 * @endcode
    190 *
    191 * except that it is possible for interested callers to handle overflow.
    192 *
    193 * @param result
    194 *     A pointer to the size_t variable that should receive the result of
    195 *     subtracting the given values from each other.
    196 *
    197 * @param ...
    198 *     The size_t values that should be subtracted from each other.
    199 *
    200 * @returns
    201 *     Zero if the subtraction was successful and did not overflow the limits
    202 *     of a size_t (did not go below zero), non-zero otherwise.
    203 */
    204#define guac_mem_ckd_sub(result, ...) \
    205    PRIV_guac_mem_ckd_sub(                                                    \
    206        result,                                                               \
    207        sizeof((const size_t[]) { __VA_ARGS__ }) / sizeof(const size_t),      \
    208        (const size_t[]) { __VA_ARGS__ }                                      \
    209    )
    210
    211/**
    212 * Multiplies together each of the given values, returning the result directly.
    213 * If the result of the multiplication overflows the limits of a size_t,
    214 * execution of the current process is aborted entirely, and this function does
    215 * not return.
    216 *
    217 * For example, the following:
    218 * @code
    219 *     size_t some_result = guac_mem_ckd_mul_or_die(a, b, c);
    220 * @endcode
    221 *
    222 * is equivalent in principle to:
    223 * @code
    224 *     size_t some_result = a * b * c;
    225 * @endcode
    226 *
    227 * except that an overflow condition will result in the process immediately
    228 * terminating.
    229 *
    230 * @param ...
    231 *     The size_t values that should be multiplied together.
    232 *
    233 * @returns
    234 *     The result of the multiplication. If the multiplication operation would
    235 *     overflow the limits of a size_t, execution of the current process is
    236 *     aborted, and this function does not return.
    237 */
    238#define guac_mem_ckd_mul_or_die(...) \
    239    PRIV_guac_mem_ckd_mul_or_die(                                             \
    240        sizeof((const size_t[]) { __VA_ARGS__ }) / sizeof(const size_t),      \
    241        (const size_t[]) { __VA_ARGS__ }                                      \
    242    )
    243
    244/**
    245 * Adds together each of the given values, returning the result directly. If
    246 * the result of the addition overflows the limits of a size_t, execution of
    247 * the current process is aborted entirely, and this function does not return.
    248 *
    249 * For example, the following:
    250 * @code
    251 *     size_t some_result = guac_mem_ckd_add_or_die(a, b, c);
    252 * @endcode
    253 *
    254 * is equivalent in principle to:
    255 * @code
    256 *     size_t some_result = a + b + c;
    257 * @endcode
    258 *
    259 * except that an overflow condition will result in the process immediately
    260 * terminating.
    261 *
    262 * @param ...
    263 *     The size_t values that should be added together.
    264 *
    265 * @returns
    266 *     The result of the addition. If the addition operation would overflow the
    267 *     limits of a size_t, execution of the current process is aborted, and
    268 *     this function does not return.
    269 */
    270#define guac_mem_ckd_add_or_die(...) \
    271    PRIV_guac_mem_ckd_add_or_die(                                             \
    272        sizeof((const size_t[]) { __VA_ARGS__ }) / sizeof(const size_t),      \
    273        (const size_t[]) { __VA_ARGS__ }                                      \
    274    )
    275
    276/**
    277 * Subtracts each of the given values from each other, returning the result
    278 * directly. If the result of the subtraction overflows the limits of a size_t
    279 * (goes below zero), execution of the current process is aborted entirely, and
    280 * this function does not return.
    281 *
    282 * For example, the following:
    283 * @code
    284 *     size_t some_result = guac_mem_ckd_sub_or_die(a, b, c);
    285 * @endcode
    286 *
    287 * is equivalent in principle to:
    288 * @code
    289 *     size_t some_result = a - b - c;
    290 * @endcode
    291 *
    292 * except that an overflow condition will result in the process immediately
    293 * terminating.
    294 *
    295 * @param ...
    296 *     The size_t values that should be subtracted from each other.
    297 *
    298 * @returns
    299 *     The result of the subtraction. If the subtraction operation would
    300 *     overflow the limits of a size_t (go below zero), execution of the
    301 *     current process is aborted, and this function does not return.
    302 */
    303#define guac_mem_ckd_sub_or_die(...) \
    304    PRIV_guac_mem_ckd_sub_or_die(                                             \
    305        sizeof((const size_t[]) { __VA_ARGS__ }) / sizeof(const size_t),      \
    306        (const size_t[]) { __VA_ARGS__ }                                      \
    307    )
    308
    309/**
    310 * Reallocates a contiguous block of memory that was previously allocated with
    311 * guac_mem_alloc(), guac_mem_zalloc(), guac_mem_realloc(), or one of their
    312 * *_or_die() variants, returning a pointer to the first byte of that
    313 * reallocated block of memory. If multiple sizes are provided, these sizes are
    314 * multiplied together to produce the final size of the new block. If memory of
    315 * the specified size cannot be allocated, or if multiplying the sizes would
    316 * result in integer overflow, guac_error is set appropriately, the original
    317 * block of memory is left untouched, and NULL is returned.
    318 *
    319 * This macro is analogous to the standard realloc(), but accepts a list of
    320 * size factors instead of a requiring exactly one integer size.
    321 *
    322 * The returned pointer may be the same as the original pointer, but this is
    323 * not guaranteed. If the returned pointer is different, the original pointer
    324 * is automatically freed.
    325 *
    326 * The pointer returned by guac_mem_realloc() SHOULD be freed with a subsequent
    327 * call to guac_mem_free(), but MAY instead be freed with a subsequent call to
    328 * free().
    329 *
    330 * @param ...
    331 *     A series of one or more size_t values that should be multiplied together
    332 *     to produce the desired block size. At least one value MUST be provided.
    333 *
    334 * @returns
    335 *     A pointer to the first byte of the reallocated block of memory, or NULL
    336 *     if such a block could not be allocated. If a block of memory could not
    337 *     be allocated, guac_error is set appropriately and the original block of
    338 *     memory is left untouched.
    339 */
    340#define guac_mem_realloc(mem, ...) \
    341    PRIV_guac_mem_realloc(                                                    \
    342        mem,                                                                  \
    343        sizeof((const size_t[]) { __VA_ARGS__ }) / sizeof(const size_t),      \
    344        (const size_t[]) { __VA_ARGS__ }                                      \
    345    )
    346
    347/**
    348 * Reallocates a contiguous block of memory that was previously allocated with
    349 * guac_mem_alloc(), guac_mem_zalloc(), guac_mem_realloc(), or one of their
    350 * *_or_die() variants, returning a pointer to the first byte of that
    351 * reallocated block of memory. If multiple sizes are provided, these sizes are
    352 * multiplied together to produce the final size of the new block. If memory of
    353 * the specified size cannot be allocated, execution of the current process is
    354 * aborted entirely, and this function does not return.
    355 *
    356 * This macro is analogous to the standard realloc(), but accepts a list of
    357 * size factors instead of a requiring exactly one integer size and does not
    358 * return in the event a block cannot be allocated.
    359 *
    360 * The returned pointer may be the same as the original pointer, but this is
    361 * not guaranteed. If the returned pointer is different, the original pointer
    362 * is automatically freed.
    363 *
    364 * The pointer returned by guac_mem_realloc() SHOULD be freed with a subsequent
    365 * call to guac_mem_free(), but MAY instead be freed with a subsequent call to
    366 * free().
    367 *
    368 * @param ...
    369 *     A series of one or more size_t values that should be multiplied together
    370 *     to produce the desired block size. At least one value MUST be provided.
    371 *
    372 * @returns
    373 *     A pointer to the first byte of the reallocated block of memory. If a
    374 *     block of memory could not be allocated, execution of the current process
    375 *     is aborted, and this function does not return.
    376 */
    377#define guac_mem_realloc_or_die(mem, ...) \
    378    PRIV_guac_mem_realloc_or_die(                                             \
    379        mem,                                                                  \
    380        sizeof((const size_t[]) { __VA_ARGS__ }) / sizeof(const size_t),      \
    381        (const size_t[]) { __VA_ARGS__ }                                      \
    382    )
    383
    384/**
    385 * Frees the memory block at the given pointer, which MUST have been allocated
    386 * with guac_mem_alloc(), guac_mem_zalloc(), guac_mem_realloc(), or one of
    387 * their *_or_die() variants. The pointer is automatically assigned a value of
    388 * NULL after memory is freed. If the provided pointer is already NULL, this
    389 * macro has no effect.
    390 *
    391 * @param mem
    392 *     A pointer to the memory to be freed.
    393 */
    394#define guac_mem_free(mem) (PRIV_guac_mem_free(mem), (mem) = NULL, (void) 0)
    395
    396/**
    397 * Frees the memory block at the given const pointer, which MUST have been
    398 * allocated with guac_mem_alloc(), guac_mem_zalloc(), guac_mem_realloc(), or
    399 * one of their *_or_die() variants. As the pointer is presumed constant, it is
    400 * not automatically assigned a value of NULL after memory is freed. If the
    401 * provided pointer is NULL, this macro has no effect.
    402 *
    403 * The guac_mem_free() macro should be used in favor of this macro. This macro
    404 * should only be used in cases where a constant pointer is absolutely
    405 * necessary.
    406 *
    407 * @param mem
    408 *     A pointer to the memory to be freed.
    409 */
    410#define guac_mem_free_const(mem) PRIV_guac_mem_free((void*) (mem))
    411
    412#endif
    413