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