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 <brotli/types.h> 15 16 #include "../common/platform.h" 17 18 #if defined(__cplusplus) || defined(c_plusplus) 19 extern "C" { 20 #endif 21 22 #if !defined(BROTLI_ENCODER_CLEANUP_ON_OOM) && \ 23 !defined(BROTLI_ENCODER_EXIT_ON_OOM) 24 #define BROTLI_ENCODER_EXIT_ON_OOM 25 #endif 26 27 #if !defined(BROTLI_ENCODER_EXIT_ON_OOM) 28 #if defined(BROTLI_EXPERIMENTAL) 29 #define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS (48*1024) 30 #else /* BROTLI_EXPERIMENTAL */ 31 #define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 256 32 #endif /* BROTLI_EXPERIMENTAL */ 33 #else /* BROTLI_ENCODER_EXIT_ON_OOM */ 34 #define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 0 35 #endif /* BROTLI_ENCODER_EXIT_ON_OOM */ 36 37 typedef struct MemoryManager { 38 brotli_alloc_func alloc_func; 39 brotli_free_func free_func; 40 void* opaque; 41 #if !defined(BROTLI_ENCODER_EXIT_ON_OOM) 42 BROTLI_BOOL is_oom; 43 size_t perm_allocated; 44 size_t new_allocated; 45 size_t new_freed; 46 void* pointers[BROTLI_ENCODER_MEMORY_MANAGER_SLOTS]; 47 #endif /* BROTLI_ENCODER_EXIT_ON_OOM */ 48 } MemoryManager; 49 50 BROTLI_INTERNAL void BrotliInitMemoryManager( 51 MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func, 52 void* opaque); 53 54 BROTLI_INTERNAL void* BrotliAllocate(MemoryManager* m, size_t n); 55 #define BROTLI_ALLOC(M, T, N) \ 56 ((N) > 0 ? ((T*)BrotliAllocate((M), (N) * sizeof(T))) : NULL) 57 58 BROTLI_INTERNAL void BrotliFree(MemoryManager* m, void* p); 59 #define BROTLI_FREE(M, P) { \ 60 BrotliFree((M), (P)); \ 61 P = NULL; \ 62 } 63 64 #if defined(BROTLI_ENCODER_EXIT_ON_OOM) 65 #define BROTLI_IS_OOM(M) (!!0) 66 #else /* BROTLI_ENCODER_EXIT_ON_OOM */ 67 #define BROTLI_IS_OOM(M) (!!(M)->is_oom) 68 #endif /* BROTLI_ENCODER_EXIT_ON_OOM */ 69 70 /* 71 BROTLI_IS_NULL is a fake check, BROTLI_IS_OOM does the heavy lifting. 72 The only purpose of it is to explain static analyzers the state of things. 73 NB: use ONLY together with BROTLI_IS_OOM 74 AND ONLY for allocations in the current scope. 75 */ 76 #if defined(__clang_analyzer__) && !defined(BROTLI_ENCODER_EXIT_ON_OOM) 77 #define BROTLI_IS_NULL(A) ((A) == nullptr) 78 #else /* defined(__clang_analyzer__) */ 79 #define BROTLI_IS_NULL(A) (!!0) 80 #endif /* defined(__clang_analyzer__) */ 81 82 BROTLI_INTERNAL void BrotliWipeOutMemoryManager(MemoryManager* m); 83 84 /* 85 Dynamically grows array capacity to at least the requested size 86 M: MemoryManager 87 T: data type 88 A: array 89 C: capacity 90 R: requested size 91 */ 92 #define BROTLI_ENSURE_CAPACITY(M, T, A, C, R) { \ 93 if (C < (R)) { \ 94 size_t _new_size = (C == 0) ? (R) : C; \ 95 T* new_array; \ 96 while (_new_size < (R)) _new_size *= 2; \ 97 new_array = BROTLI_ALLOC((M), T, _new_size); \ 98 if (!BROTLI_IS_OOM(M) && !BROTLI_IS_NULL(new_array) && C != 0) \ 99 memcpy(new_array, A, C * sizeof(T)); \ 100 BROTLI_FREE((M), A); \ 101 A = new_array; \ 102 C = _new_size; \ 103 } \ 104 } 105 106 /* 107 Appends value and dynamically grows array capacity when needed 108 M: MemoryManager 109 T: data type 110 A: array 111 C: array capacity 112 S: array size 113 V: value to append 114 */ 115 #define BROTLI_ENSURE_CAPACITY_APPEND(M, T, A, C, S, V) { \ 116 (S)++; \ 117 BROTLI_ENSURE_CAPACITY(M, T, A, C, S); \ 118 A[(S) - 1] = (V); \ 119 } 120 121 /* "Bootstrap" allocations are not tracked by memory manager; should be used 122 only to allocate MemoryManager itself (or structure containing it). */ 123 BROTLI_INTERNAL void* BrotliBootstrapAlloc(size_t size, 124 brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); 125 BROTLI_INTERNAL void BrotliBootstrapFree(void* address, MemoryManager* m); 126 127 #if defined(__cplusplus) || defined(c_plusplus) 128 } /* extern "C" */ 129 #endif 130 131 #endif /* BROTLI_ENC_MEMORY_H_ */ 132