Home | History | Annotate | Line # | Download | only in enc
      1 /* Copyright 2016 Google Inc. All Rights Reserved.
      2 
      3    Distributed under MIT license.
      4    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
      5 */
      6 
      7 /* Macros for memory management. */
      8 
      9 #ifndef BROTLI_ENC_MEMORY_H_
     10 #define BROTLI_ENC_MEMORY_H_
     11 
     12 #include <string.h>  /* memcpy */
     13 
     14 #include "../common/platform.h"
     15 #include <brotli/types.h>
     16 
     17 #if defined(__cplusplus) || defined(c_plusplus)
     18 extern "C" {
     19 #endif
     20 
     21 #if !defined(BROTLI_ENCODER_CLEANUP_ON_OOM) && \
     22     !defined(BROTLI_ENCODER_EXIT_ON_OOM)
     23 #define BROTLI_ENCODER_EXIT_ON_OOM
     24 #endif
     25 
     26 typedef struct MemoryManager {
     27   brotli_alloc_func alloc_func;
     28   brotli_free_func free_func;
     29   void* opaque;
     30 #if !defined(BROTLI_ENCODER_EXIT_ON_OOM)
     31   BROTLI_BOOL is_oom;
     32   size_t perm_allocated;
     33   size_t new_allocated;
     34   size_t new_freed;
     35   void* pointers[256];
     36 #endif  /* BROTLI_ENCODER_EXIT_ON_OOM */
     37 } MemoryManager;
     38 
     39 BROTLI_INTERNAL void BrotliInitMemoryManager(
     40     MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func,
     41     void* opaque);
     42 
     43 BROTLI_INTERNAL void* BrotliAllocate(MemoryManager* m, size_t n);
     44 #define BROTLI_ALLOC(M, T, N)                               \
     45   ((N) > 0 ? ((T*)BrotliAllocate((M), (N) * sizeof(T))) : NULL)
     46 
     47 BROTLI_INTERNAL void BrotliFree(MemoryManager* m, void* p);
     48 #define BROTLI_FREE(M, P) { \
     49   BrotliFree((M), (P));     \
     50   P = NULL;                 \
     51 }
     52 
     53 #if defined(BROTLI_ENCODER_EXIT_ON_OOM)
     54 #define BROTLI_IS_OOM(M) (!!0)
     55 #else  /* BROTLI_ENCODER_EXIT_ON_OOM */
     56 #define BROTLI_IS_OOM(M) (!!(M)->is_oom)
     57 #endif  /* BROTLI_ENCODER_EXIT_ON_OOM */
     58 
     59 /*
     60 BROTLI_IS_NULL is a fake check, BROTLI_IS_OOM does the heavy lifting.
     61 The only purpose of it is to explain static analyzers the state of things.
     62 NB: use ONLY together with BROTLI_IS_OOM
     63     AND ONLY for allocations in the current scope.
     64  */
     65 #if defined(__clang_analyzer__) && !defined(BROTLI_ENCODER_EXIT_ON_OOM)
     66 #define BROTLI_IS_NULL(A) ((A) == nullptr)
     67 #else  /* defined(__clang_analyzer__) */
     68 #define BROTLI_IS_NULL(A) (!!0)
     69 #endif  /* defined(__clang_analyzer__) */
     70 
     71 BROTLI_INTERNAL void BrotliWipeOutMemoryManager(MemoryManager* m);
     72 
     73 /*
     74 Dynamically grows array capacity to at least the requested size
     75 M: MemoryManager
     76 T: data type
     77 A: array
     78 C: capacity
     79 R: requested size
     80 */
     81 #define BROTLI_ENSURE_CAPACITY(M, T, A, C, R) {                    \
     82   if (C < (R)) {                                                   \
     83     size_t _new_size = (C == 0) ? (R) : C;                         \
     84     T* new_array;                                                  \
     85     while (_new_size < (R)) _new_size *= 2;                        \
     86     new_array = BROTLI_ALLOC((M), T, _new_size);                   \
     87     if (!BROTLI_IS_OOM(M) && !BROTLI_IS_NULL(new_array) && C != 0) \
     88       memcpy(new_array, A, C * sizeof(T));                         \
     89     BROTLI_FREE((M), A);                                           \
     90     A = new_array;                                                 \
     91     C = _new_size;                                                 \
     92   }                                                                \
     93 }
     94 
     95 /*
     96 Appends value and dynamically grows array capacity when needed
     97 M: MemoryManager
     98 T: data type
     99 A: array
    100 C: array capacity
    101 S: array size
    102 V: value to append
    103 */
    104 #define BROTLI_ENSURE_CAPACITY_APPEND(M, T, A, C, S, V) { \
    105   (S)++;                                                  \
    106   BROTLI_ENSURE_CAPACITY(M, T, A, C, S);                  \
    107   A[(S) - 1] = (V);                                       \
    108 }
    109 
    110 #if defined(__cplusplus) || defined(c_plusplus)
    111 }  /* extern "C" */
    112 #endif
    113 
    114 #endif  /* BROTLI_ENC_MEMORY_H_ */
    115