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