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 BROTLI_INTERNAL void BrotliWipeOutMemoryManager(MemoryManager* m);
60 
61 /*
62 Dynamically grows array capacity to at least the requested size
63 M: MemoryManager
64 T: data type
65 A: array
66 C: capacity
67 R: requested size
68 */
69 #define BROTLI_ENSURE_CAPACITY(M, T, A, C, R) {  \
70   if (C < (R)) {                                 \
71     size_t _new_size = (C == 0) ? (R) : C;       \
72     T* new_array;                                \
73     while (_new_size < (R)) _new_size *= 2;      \
74     new_array = BROTLI_ALLOC((M), T, _new_size); \
75     if (!BROTLI_IS_OOM(M) && C != 0)             \
76       memcpy(new_array, A, C * sizeof(T));       \
77     BROTLI_FREE((M), A);                         \
78     A = new_array;                               \
79     C = _new_size;                               \
80   }                                              \
81 }
82 
83 /*
84 Appends value and dynamically grows array capacity when needed
85 M: MemoryManager
86 T: data type
87 A: array
88 C: array capacity
89 S: array size
90 V: value to append
91 */
92 #define BROTLI_ENSURE_CAPACITY_APPEND(M, T, A, C, S, V) { \
93   (S)++;                                                  \
94   BROTLI_ENSURE_CAPACITY(M, T, A, C, S);                  \
95   A[(S) - 1] = (V);                                       \
96 }
97 
98 #if defined(__cplusplus) || defined(c_plusplus)
99 }  /* extern "C" */
100 #endif
101 
102 #endif  /* BROTLI_ENC_MEMORY_H_ */
103