Merge to XFA: Remove typdefs for pointer types in fx_system.h.
[pdfium.git] / xfa / src / fgas / src / crt / fx_memory.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../fgas_base.h"\r
8 #include "fx_memory.h"\r
9 #define FX_4BYTEALIGN(size)     (((size) + 3) / 4 * 4)\r
10 IFX_MEMAllocator* FX_CreateAllocator(FX_ALLOCTYPE eType, size_t chunkSize, size_t blockSize)\r
11 {\r
12     switch (eType) {\r
13 #ifndef _FXEMB\r
14         case FX_ALLOCTYPE_Dynamic:\r
15             return FXTARGET_New CFX_DynamicStore(chunkSize);\r
16 #endif\r
17         case FX_ALLOCTYPE_Default:\r
18             return FXTARGET_New CFX_DefStore();\r
19         case FX_ALLOCTYPE_Static:\r
20             return FXTARGET_New CFX_StaticStore(chunkSize);\r
21         case FX_ALLOCTYPE_Fixed:\r
22             return FXTARGET_New CFX_FixedStore(blockSize, chunkSize);\r
23         default:\r
24             return NULL;\r
25     }\r
26 }\r
27 CFX_StaticStore::CFX_StaticStore(size_t iDefChunkSize)\r
28     : m_iAllocatedSize(0)\r
29     , m_iDefChunkSize(iDefChunkSize)\r
30     , m_pChunk(NULL)\r
31     , m_pLastChunk(NULL)\r
32 {\r
33     FXSYS_assert(m_iDefChunkSize != 0);\r
34 }\r
35 CFX_StaticStore::~CFX_StaticStore()\r
36 {\r
37     register FX_LPSTATICSTORECHUNK pChunk, pNext;\r
38     pChunk = m_pChunk;\r
39     while (pChunk != NULL) {\r
40         pNext = pChunk->pNextChunk;\r
41         FX_Free(pChunk);\r
42         pChunk = pNext;\r
43     }\r
44 }\r
45 FX_LPSTATICSTORECHUNK CFX_StaticStore::AllocChunk(size_t size)\r
46 {\r
47     FXSYS_assert(size != 0);\r
48     register FX_LPSTATICSTORECHUNK pChunk = (FX_LPSTATICSTORECHUNK)FX_Alloc(uint8_t, sizeof(FX_STATICSTORECHUNK) + size);\r
49     if (pChunk == NULL) {\r
50         return NULL;\r
51     }\r
52     pChunk->iChunkSize = size;\r
53     pChunk->iFreeSize = size;\r
54     pChunk->pNextChunk = NULL;\r
55     if (m_pLastChunk == NULL) {\r
56         m_pChunk = pChunk;\r
57     } else {\r
58         m_pLastChunk->pNextChunk = pChunk;\r
59     }\r
60     m_pLastChunk = pChunk;\r
61     return pChunk;\r
62 }\r
63 FX_LPSTATICSTORECHUNK CFX_StaticStore::FindChunk(size_t size)\r
64 {\r
65     FXSYS_assert(size != 0);\r
66     if (m_pLastChunk == NULL || m_pLastChunk->iFreeSize < size) {\r
67         return AllocChunk(FX_MAX(m_iDefChunkSize, size));\r
68     }\r
69     return m_pLastChunk;\r
70 }\r
71 void* CFX_StaticStore::Alloc(size_t size)\r
72 {\r
73     size = FX_4BYTEALIGN(size);\r
74     FXSYS_assert(size != 0);\r
75     register FX_LPSTATICSTORECHUNK pChunk = FindChunk(size);\r
76     FXSYS_assert(pChunk != NULL && pChunk->iFreeSize >= size);\r
77     register uint8_t* p = (uint8_t*)pChunk;\r
78     p += sizeof(FX_STATICSTORECHUNK) + pChunk->iChunkSize - pChunk->iFreeSize;\r
79     pChunk->iFreeSize -= size;\r
80     m_iAllocatedSize += size;\r
81     return p;\r
82 }\r
83 size_t CFX_StaticStore::SetDefChunkSize(size_t size)\r
84 {\r
85     FXSYS_assert(size != 0);\r
86     size_t v = m_iDefChunkSize;\r
87     m_iDefChunkSize = size;\r
88     return v;\r
89 }\r
90 CFX_FixedStore::CFX_FixedStore(size_t iBlockSize, size_t iBlockNumsInChunk)\r
91     : m_iBlockSize(FX_4BYTEALIGN(iBlockSize))\r
92     , m_iDefChunkSize(FX_4BYTEALIGN(iBlockNumsInChunk))\r
93     , m_pChunk(NULL)\r
94 {\r
95     FXSYS_assert(m_iBlockSize != 0 && m_iDefChunkSize != 0);\r
96 }\r
97 CFX_FixedStore::~CFX_FixedStore()\r
98 {\r
99     register FX_LPFIXEDSTORECHUNK pChunk, pNext;\r
100     pChunk = m_pChunk;\r
101     while (pChunk != NULL) {\r
102         pNext = pChunk->pNextChunk;\r
103         FX_Free(pChunk);\r
104         pChunk = pNext;\r
105     }\r
106 }\r
107 FX_LPFIXEDSTORECHUNK CFX_FixedStore::AllocChunk()\r
108 {\r
109     int32_t iTotalSize = sizeof(FX_FIXEDSTORECHUNK) + m_iDefChunkSize + m_iBlockSize * m_iDefChunkSize;\r
110     register FX_LPFIXEDSTORECHUNK pChunk = (FX_LPFIXEDSTORECHUNK)FX_Alloc(uint8_t, iTotalSize);\r
111     if (pChunk == NULL) {\r
112         return NULL;\r
113     }\r
114     FXSYS_memset(pChunk->FirstFlag(), 0, m_iDefChunkSize);\r
115     pChunk->pNextChunk = m_pChunk;\r
116     pChunk->iChunkSize = m_iDefChunkSize;\r
117     pChunk->iFreeNum = m_iDefChunkSize;\r
118     m_pChunk = pChunk;\r
119     return pChunk;\r
120 }\r
121 void* CFX_FixedStore::Alloc(size_t size)\r
122 {\r
123     if (size > m_iBlockSize) {\r
124         return NULL;\r
125     }\r
126     register FX_LPFIXEDSTORECHUNK pChunk = m_pChunk;\r
127     while (pChunk != NULL) {\r
128         if (pChunk->iFreeNum > 0) {\r
129             break;\r
130         }\r
131         pChunk = pChunk->pNextChunk;\r
132     }\r
133     if (pChunk == NULL) {\r
134         pChunk = AllocChunk();\r
135     }\r
136     FXSYS_assert(pChunk != NULL);\r
137     register uint8_t* pFlags = pChunk->FirstFlag();\r
138     register size_t i = 0;\r
139     for (; i < pChunk->iChunkSize; i ++)\r
140         if (pFlags[i] == 0) {\r
141             break;\r
142         }\r
143     FXSYS_assert(i < pChunk->iChunkSize);\r
144     pFlags[i] = 1;\r
145     pChunk->iFreeNum --;\r
146     return pChunk->FirstBlock() + i * m_iBlockSize;\r
147 }\r
148 void CFX_FixedStore::Free(void* pBlock)\r
149 {\r
150     FXSYS_assert(pBlock != NULL);\r
151     register FX_LPFIXEDSTORECHUNK pPrior, pChunk;\r
152     pPrior = NULL, pChunk = m_pChunk;\r
153     uint8_t* pStart = NULL;\r
154     uint8_t* pEnd;\r
155     while (pChunk != NULL) {\r
156         pStart = pChunk->FirstBlock();\r
157         if (pBlock >= pStart) {\r
158             pEnd = pStart + m_iBlockSize * pChunk->iChunkSize;\r
159             if (pBlock < pEnd) {\r
160                 break;\r
161             }\r
162         }\r
163         pPrior = pChunk, pChunk = pChunk->pNextChunk;\r
164     }\r
165     FXSYS_assert(pChunk != NULL);\r
166     register size_t iPos = ((uint8_t*)pBlock - pStart) / m_iBlockSize;\r
167     FXSYS_assert(iPos < pChunk->iChunkSize);\r
168     register uint8_t* pFlags = pChunk->FirstFlag();\r
169     if (pFlags[iPos] == 0) {\r
170         return;\r
171     }\r
172     pFlags[iPos] = 0;\r
173     pChunk->iFreeNum ++;\r
174     if (pChunk->iFreeNum == pChunk->iChunkSize) {\r
175         if (pPrior == NULL) {\r
176             m_pChunk = pChunk->pNextChunk;\r
177         } else {\r
178             pPrior->pNextChunk = pChunk->pNextChunk;\r
179         }\r
180         FX_Free(pChunk);\r
181     }\r
182 }\r
183 size_t CFX_FixedStore::SetDefChunkSize(size_t iChunkSize)\r
184 {\r
185     FXSYS_assert(iChunkSize != 0);\r
186     size_t v = m_iDefChunkSize;\r
187     m_iDefChunkSize = FX_4BYTEALIGN(iChunkSize);\r
188     return v;\r
189 }\r
190 #ifndef _FXEMB\r
191 CFX_DynamicStore::CFX_DynamicStore(size_t iDefChunkSize)\r
192     : m_iDefChunkSize(iDefChunkSize)\r
193     , m_pChunk(NULL)\r
194 {\r
195     FXSYS_assert(m_iDefChunkSize != 0);\r
196 }\r
197 CFX_DynamicStore::~CFX_DynamicStore()\r
198 {\r
199     register FX_LPDYNAMICSTORECHUNK pChunk, pNext;\r
200     pChunk = m_pChunk;\r
201     while (pChunk != NULL) {\r
202         pNext = pChunk->pNextChunk;\r
203         FX_Free(pChunk);\r
204         pChunk = pNext;\r
205     }\r
206 }\r
207 FX_LPDYNAMICSTORECHUNK CFX_DynamicStore::AllocChunk(size_t size)\r
208 {\r
209     FXSYS_assert(size != 0);\r
210     register FX_LPDYNAMICSTORECHUNK pChunk = (FX_LPDYNAMICSTORECHUNK)FX_Alloc(uint8_t, sizeof(FX_DYNAMICSTORECHUNK) + sizeof(FX_DYNAMICSTOREBLOCK) * 2 + size);\r
211     if (pChunk == NULL) {\r
212         return NULL;\r
213     }\r
214     pChunk->iChunkSize = size;\r
215     pChunk->iFreeSize = size;\r
216     register FX_LPDYNAMICSTOREBLOCK pBlock = pChunk->FirstBlock();\r
217     pBlock->iBlockSize = size;\r
218     pBlock->bUsed = FALSE;\r
219     pBlock = pBlock->NextBlock();\r
220     pBlock->iBlockSize = 0;\r
221     pBlock->bUsed = TRUE;\r
222     if (m_pChunk != NULL && size >= m_iDefChunkSize) {\r
223         FX_LPDYNAMICSTORECHUNK pLast = m_pChunk;\r
224         while (pLast->pNextChunk != NULL) {\r
225             pLast = pLast->pNextChunk;\r
226         }\r
227         pLast->pNextChunk = pChunk;\r
228         pChunk->pNextChunk = NULL;\r
229     } else {\r
230         pChunk->pNextChunk = m_pChunk;\r
231         m_pChunk = pChunk;\r
232     }\r
233     return pChunk;\r
234 }\r
235 void* CFX_DynamicStore::Alloc(size_t size)\r
236 {\r
237     size = FX_4BYTEALIGN(size);\r
238     FXSYS_assert(size != 0);\r
239     register FX_LPDYNAMICSTORECHUNK pChunk = m_pChunk;\r
240     register FX_LPDYNAMICSTOREBLOCK pBlock = NULL;\r
241     while (pChunk != NULL) {\r
242         if (pChunk->iFreeSize >= size) {\r
243             pBlock = pChunk->FirstBlock();\r
244             register FX_BOOL bFind = FALSE;\r
245             while(pBlock->iBlockSize != 0) {\r
246                 if (!pBlock->bUsed && pBlock->iBlockSize >= size) {\r
247                     bFind = TRUE;\r
248                     break;\r
249                 }\r
250                 pBlock = pBlock->NextBlock();\r
251             }\r
252             if (bFind) {\r
253                 break;\r
254             }\r
255         }\r
256         pChunk = pChunk->pNextChunk;\r
257     }\r
258     if (pChunk == NULL) {\r
259         pChunk = AllocChunk(FX_MAX(m_iDefChunkSize, size));\r
260         pBlock = pChunk->FirstBlock();\r
261     }\r
262     FXSYS_assert(pChunk != NULL && pBlock != NULL);\r
263     register size_t m = size + sizeof(FX_DYNAMICSTOREBLOCK);\r
264     pBlock->bUsed = TRUE;\r
265     if (pBlock->iBlockSize > m) {\r
266         register size_t n = pBlock->iBlockSize;\r
267         pBlock->iBlockSize = size;\r
268         register FX_LPDYNAMICSTOREBLOCK pNextBlock = pBlock->NextBlock();\r
269         pNextBlock->bUsed = FALSE;\r
270         pNextBlock->iBlockSize = n - size - sizeof(FX_DYNAMICSTOREBLOCK);\r
271         pChunk->iFreeSize -= size + sizeof(FX_DYNAMICSTOREBLOCK);\r
272     } else {\r
273         pChunk->iFreeSize -= pBlock->iBlockSize;\r
274     }\r
275     return pBlock->Data();\r
276 }\r
277 void CFX_DynamicStore::Free(void* pBlock)\r
278 {\r
279     FXSYS_assert(pBlock != NULL);\r
280     register FX_LPDYNAMICSTORECHUNK pPriorChunk, pChunk;\r
281     pPriorChunk = NULL, pChunk = m_pChunk;\r
282     while (pChunk != NULL) {\r
283         if (pBlock > pChunk && pBlock <= ((uint8_t*)pChunk + sizeof(FX_DYNAMICSTORECHUNK) + pChunk->iChunkSize)) {\r
284             break;\r
285         }\r
286         pPriorChunk = pChunk, pChunk = pChunk->pNextChunk;\r
287     }\r
288     FXSYS_assert(pChunk != NULL);\r
289     register FX_LPDYNAMICSTOREBLOCK pPriorBlock, pFindBlock;\r
290     pPriorBlock = NULL, pFindBlock = pChunk->FirstBlock();\r
291     while(pFindBlock->iBlockSize != 0) {\r
292         if (pBlock == (void*)pFindBlock->Data()) {\r
293             break;\r
294         }\r
295         pPriorBlock = pFindBlock;\r
296         pFindBlock = pFindBlock->NextBlock();\r
297     }\r
298     FXSYS_assert(pFindBlock->iBlockSize != 0 && pFindBlock->bUsed && pBlock == (void*)pFindBlock->Data());\r
299     pFindBlock->bUsed = FALSE;\r
300     pChunk->iFreeSize += pFindBlock->iBlockSize;\r
301     if (pPriorBlock == NULL) {\r
302         pPriorBlock = pChunk->FirstBlock();\r
303     } else if (pPriorBlock->bUsed) {\r
304         pPriorBlock = pFindBlock;\r
305     }\r
306     pFindBlock = pPriorBlock;\r
307     register size_t sizeFree = 0;\r
308     register size_t sizeBlock = 0;\r
309     while (pFindBlock->iBlockSize != 0 && !pFindBlock->bUsed) {\r
310         if (pFindBlock != pPriorBlock) {\r
311             sizeFree += sizeof(FX_DYNAMICSTOREBLOCK);\r
312             sizeBlock += sizeof(FX_DYNAMICSTOREBLOCK);\r
313         }\r
314         sizeBlock += pFindBlock->iBlockSize;\r
315         pFindBlock = pFindBlock->NextBlock();\r
316     }\r
317     pPriorBlock->iBlockSize = sizeBlock;\r
318     pChunk->iFreeSize += sizeFree;\r
319     if (pChunk->iFreeSize == pChunk->iChunkSize) {\r
320         if (pPriorChunk == NULL) {\r
321             m_pChunk = pChunk->pNextChunk;\r
322         } else {\r
323             pPriorChunk->pNextChunk = pChunk->pNextChunk;\r
324         }\r
325         FX_Free(pChunk);\r
326     }\r
327 }\r
328 size_t CFX_DynamicStore::SetDefChunkSize(size_t size)\r
329 {\r
330     FXSYS_assert(size != 0);\r
331     size_t v = m_iDefChunkSize;\r
332     m_iDefChunkSize = size;\r
333     return v;\r
334 }\r
335 #endif\r