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) 18extern "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 26typedef 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 39BROTLI_INTERNAL void BrotliInitMemoryManager( 40 MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func, 41 void* opaque); 42 43BROTLI_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 47BROTLI_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/* 60BROTLI_IS_NULL is a fake check, BROTLI_IS_OOM does the heavy lifting. 61The only purpose of it is to explain static analyzers the state of things. 62NB: 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 71BROTLI_INTERNAL void BrotliWipeOutMemoryManager(MemoryManager* m); 72 73/* 74Dynamically grows array capacity to at least the requested size 75M: MemoryManager 76T: data type 77A: array 78C: capacity 79R: 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/* 96Appends value and dynamically grows array capacity when needed 97M: MemoryManager 98T: data type 99A: array 100C: array capacity 101S: array size 102V: 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