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