1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// found in the LICENSE file.
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/fxcrt/fx_ext.h"
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "mem_int.h"
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef _FPDFAPI_MINI_
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic FX_MEMCONFIG g_MemConfig = {
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1,
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    5,
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    8,
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    4,
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    12,
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    8,
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    2,
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    4,
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    32,
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    64,
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic FX_MEMCONFIG g_MemConfig = {
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1,
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    8,
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    24,
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    8,
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    32,
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    16,
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    4,
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    8,
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    128,
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    64,
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid FXMEM_SetConfig(const FX_MEMCONFIG* memConfig)
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    g_MemConfig = *memConfig;
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef __cplusplus
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovextern "C" {
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void* FixedAlloc(FXMEM_SystemMgr* pMgr, size_t size, int flags)
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ((CFXMEM_FixedMgr*)pMgr->user)->Alloc(size);
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void* FixedAllocDebug(FXMEM_SystemMgr* pMgr, size_t size, int flags, FX_LPCSTR file, int line)
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ((CFXMEM_FixedMgr*)pMgr->user)->Alloc(size);
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void* FixedRealloc(FXMEM_SystemMgr* pMgr, void* pointer, size_t size, int flags)
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ((CFXMEM_FixedMgr*)pMgr->user)->Realloc(pointer, size);
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void* FixedReallocDebug(FXMEM_SystemMgr* pMgr, void* pointer, size_t size, int flags, FX_LPCSTR file, int line)
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ((CFXMEM_FixedMgr*)pMgr->user)->Realloc(pointer, size);
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void  FixedFree(FXMEM_SystemMgr* pMgr, void* pointer, int flags)
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ((CFXMEM_FixedMgr*)pMgr->user)->Free(pointer);
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void  FixedPurge(FXMEM_SystemMgr* pMgr)
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ((CFXMEM_FixedMgr*)pMgr->user)->Purge();
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void FixedCollectAll(FXMEM_SystemMgr* pMgr)
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ((CFXMEM_FixedMgr*)pMgr->user)->FreeAll();
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FIXEDMEM_MINIMUMSIZE	(1024 * 1024 * 8)
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFXMEM_FoxitMgr* FXMEM_CreateMemoryMgr(size_t size, FX_BOOL extensible)
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (size < FIXEDMEM_MINIMUMSIZE) {
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        size = FIXEDMEM_MINIMUMSIZE;
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPVOID pMemory = malloc(size);
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pMemory) {
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFixedMgr_Proxy* pProxy = (CFixedMgr_Proxy*)pMemory;
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t offsetSize = (sizeof(CFixedMgr_Proxy) + 15) / 16 * 16;
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXMEM_FoxitMgr* pFoxitMgr = pProxy->Initialize((FX_LPBYTE)pProxy + offsetSize, size - offsetSize, extensible);
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pFoxitMgr) {
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        free(pMemory);
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    g_pDefFoxitMgr = (CFX_MemoryMgr*)pFoxitMgr;
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    g_pDefFoxitMgr->m_pExternalMemory = pMemory;
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return pFoxitMgr;
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFXMEM_FoxitMgr* FXMEM_CreateFixedMgr(void* pMemory, size_t size, FXMEM_SystemMgr2* pSystemMgr)
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pMemory == NULL || size < FX_FIXEDMEM_PAGESIZE) {
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pSystemMgr && size >= FIXEDMEM_PROXYSIZE_1) {
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFixedMgr_Proxy* pProxy = (CFixedMgr_Proxy*)pMemory;
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        size_t offsetSize = (sizeof(CFixedMgr_Proxy) + 15) / 16 * 16;
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return pProxy->Initialize((FX_LPBYTE)pProxy + offsetSize, size - offsetSize, FALSE);
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_FixedMgr* pHeader = (CFXMEM_FixedMgr*)pMemory;
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pHeader->Initialize(size);
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pHeader->m_pExtender = pSystemMgr;
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_MemoryMgr* p = (CFX_MemoryMgr*)pHeader->Alloc(sizeof(CFX_MemoryMgr));
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p == NULL) {
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p->Init(&pHeader->m_SystemMgr);
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (FXMEM_FoxitMgr*)p;
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovsize_t FXMEM_GetBlockSizeInFixedMgr(FXMEM_FoxitMgr* pFoxitMgr, void* ptr)
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return pFoxitMgr ? ((CFXMEM_FixedMgr*)((CFX_MemoryMgr*)pFoxitMgr)->m_pSystemMgr->user)->GetSize(ptr) : 0;
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef __cplusplus
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovconst FX_MEMCONFIG g_ProxyMgr_MemConfigs[6] = {
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {1,      2,      4,      0,      2,      2,   2,       0,       0,     0},
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {1,      4,      8,      0,      2,      2,   2,       0,       0,     0},
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {1,      4,      16,     4,      8,      8,   2,       1,       16,    16},
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {1,      8,      24,     4,      12,     12,  4,       2,       32,    16},
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {1,      8,      24,     8,      16,     16,  4,       2,       64,    32},
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {1,      8,      24,     8,      24,     32,  4,       2,       128,   64},
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovconst FX_MEMCONFIG*	FixedMgr_GetConfig(size_t nSize)
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int index = 5;
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nSize <= FIXEDMEM_PROXYSIZE_0) {
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        index = 0;
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (nSize <= FIXEDMEM_PROXYSIZE_1) {
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        index = 1;
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (nSize <= FIXEDMEM_PROXYSIZE_2) {
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        index = 2;
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (nSize <= FIXEDMEM_PROXYSIZE_3) {
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        index = 3;
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (nSize <= FIXEDMEM_PROXYSIZE_4) {
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        index = 4;
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return &g_ProxyMgr_MemConfigs[index];
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFXMEM_FoxitMgr* CFixedMgr_Proxy::Initialize(FX_LPVOID pBuffer, size_t nSize, FX_BOOL bExtensible)
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(pBuffer != NULL && nSize >= FIXEDMEM_PROXYSIZE_1 - sizeof(CFixedMgr_Proxy));
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXMEM_SetConfig(FixedMgr_GetConfig(nSize));
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_SystemMgr.More = &CFixedMgr_Proxy::Common_More;
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_SystemMgr.Free = &CFixedMgr_Proxy::Common_Free;
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pFixedPage = (CFXMEM_Page*)((FX_LPBYTE)pBuffer + FIXEDMEM_PROXYSIZE_0);
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pFixedPage->Initialize(nSize - FIXEDMEM_PROXYSIZE_0);
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pBuffer = pBuffer;
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_nSize = nSize;
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bExtensible = bExtensible;
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FXMEM_CreateFixedMgr(pBuffer, FIXEDMEM_PROXYSIZE_0, &m_SystemMgr);
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFixedMgr_Proxy::Common_More(FXMEM_SystemMgr2* pMgr, size_t alloc_size, void** new_memory, size_t* new_size)
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFixedMgr_Proxy* pProxyMgr = (CFixedMgr_Proxy*)pMgr;
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(pProxyMgr != NULL && pProxyMgr->m_pFixedPage != NULL);
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *new_size = alloc_size;
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *new_memory = pProxyMgr->m_pFixedPage->Alloc(alloc_size);
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (*new_memory == NULL && pProxyMgr->m_bExtensible) {
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *new_memory = malloc(alloc_size);
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return *new_memory != NULL;
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFixedMgr_Proxy::Common_Free(FXMEM_SystemMgr2* pMgr, void* memory)
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFixedMgr_Proxy* pProxyMgr = (CFixedMgr_Proxy*)pMgr;
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(pProxyMgr != NULL && pProxyMgr->m_pFixedPage != NULL);
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (memory > pProxyMgr->m_pBuffer && memory < (FX_LPBYTE)pProxyMgr->m_pBuffer + pProxyMgr->m_nSize) {
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pProxyMgr->m_pFixedPage->Free(memory);
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (pProxyMgr->m_bExtensible) {
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        free(memory);
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_Page::Initialize(size_t size)
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Block *pFirstBlock = (CFXMEM_Block*)(this + 1);
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_nAvailSize = size - sizeof(CFXMEM_Page) - sizeof(CFXMEM_Block);
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pFirstBlock->m_nBlockSize = m_nAvailSize;
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pFirstBlock->m_pNextBlock = NULL;
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_AvailHead.m_nBlockSize = m_nAvailSize;
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_AvailHead.m_pNextBlock = pFirstBlock;
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pLimitPos = (CFXMEM_Block*)((FX_LPBYTE)this + size);
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_Page::Alloc(CFXMEM_Block* pPrevBlock, CFXMEM_Block* pNextBlock, size_t size, size_t oldsize)
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t gap = pNextBlock->m_nBlockSize - size;
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (gap <= 64 + sizeof(CFXMEM_Block)) {
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPrevBlock->m_pNextBlock = pNextBlock->m_pNextBlock;
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_nAvailSize -= pNextBlock->m_nBlockSize;
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_nAvailSize -= size + sizeof(CFXMEM_Block);
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pNextBlock->m_nBlockSize = size;
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFXMEM_Block *pNewBlock = (CFXMEM_Block*)((FX_LPBYTE)(pNextBlock + 1) + size);
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pNewBlock->m_nBlockSize = gap - sizeof(CFXMEM_Block);
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pNewBlock->m_pNextBlock = pNextBlock->m_pNextBlock;
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPrevBlock->m_pNextBlock = pNewBlock;
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (FX_LPVOID)(pNextBlock + 1);
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_Page::Alloc(size_t size)
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t oldsize = size;
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if _FX_WORDSIZE_ == _FX_W64_
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size = (size + 31) / 32 * 32;
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size = (size + 7) / 8 * 8;
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_nAvailSize < size) {
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Block *pNextBlock;
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Block *pPrevBlock = &m_AvailHead;
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (TRUE) {
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pNextBlock = pPrevBlock->m_pNextBlock;
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!pNextBlock) {
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return NULL;
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pNextBlock->m_nBlockSize >= size) {
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPrevBlock = pNextBlock;
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return Alloc(pPrevBlock, pNextBlock, size, oldsize);
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_Page::Realloc(FX_LPVOID p, size_t oldSize, size_t newSize)
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)m_pLimitPos);
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t oldnewSize = newSize;
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if _FX_WORDSIZE_ == _FX_W64_
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    newSize = (newSize + 31) / 32 * 32;
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    newSize = (newSize + 7) / 8 * 8;
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Block *pPrevBlock = &m_AvailHead;
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Block *pNextBlock, *pPrevPrev;
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Block *pBlock = (CFXMEM_Block*)p - 1;
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pPrevPrev = NULL;
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (TRUE) {
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pNextBlock = pPrevBlock->m_pNextBlock;
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pNextBlock == NULL || pNextBlock > pBlock) {
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pPrevBlock != &m_AvailHead && (FX_LPBYTE)pNextBlock == (FX_LPBYTE)(pPrevBlock + 1) + pPrevBlock->m_nBlockSize) {
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_nAvailSize += sizeof(CFXMEM_Block);
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pPrevBlock->m_nBlockSize += pNextBlock->m_nBlockSize + sizeof(CFXMEM_Block);
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pPrevBlock->m_pNextBlock = pNextBlock->m_pNextBlock;
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pPrevPrev = pPrevBlock;
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pPrevBlock = pNextBlock;
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pNextBlock) {
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFXMEM_Block* pCurBlock = pNextBlock->m_pNextBlock;
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        while ((FX_LPBYTE)pCurBlock == (FX_LPBYTE)(pNextBlock + 1) + pNextBlock->m_nBlockSize) {
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_nAvailSize += sizeof(CFXMEM_Block);
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pNextBlock->m_nBlockSize += pCurBlock->m_nBlockSize + sizeof(CFXMEM_Block);
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pCurBlock = pCurBlock->m_pNextBlock;
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pNextBlock->m_pNextBlock = pCurBlock;
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t size = 0;
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_DWORD dwFlags = 0;
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pPrevBlock != &m_AvailHead && (FX_LPBYTE)pBlock == (FX_LPBYTE)(pPrevBlock + 1) + pPrevBlock->m_nBlockSize) {
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        size += pPrevBlock->m_nBlockSize + oldSize + sizeof(CFXMEM_Block);
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dwFlags |= 0x10;
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pNextBlock && (FX_LPBYTE)pNextBlock == (FX_LPBYTE)p + oldSize) {
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        size += pNextBlock->m_nBlockSize + sizeof(CFXMEM_Block);
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dwFlags |= 0x01;
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (size >= newSize) {
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_nAvailSize += pBlock->m_nBlockSize;
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFXMEM_Block* pCurBlock = pBlock;
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (dwFlags & 0x10) {
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pCurBlock = pPrevBlock;
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_nAvailSize += sizeof(CFXMEM_Block);
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pCurBlock->m_nBlockSize += pBlock->m_nBlockSize + sizeof(CFXMEM_Block);
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pPrevBlock = pPrevPrev;
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (dwFlags & 0x01) {
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_nAvailSize += sizeof(CFXMEM_Block);
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pCurBlock->m_nBlockSize += pNextBlock->m_nBlockSize + sizeof(CFXMEM_Block);
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pCurBlock->m_pNextBlock = pNextBlock->m_pNextBlock;
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pCurBlock != pBlock) {
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FXSYS_memmove32((FX_LPVOID)(pCurBlock + 1), p, oldSize);
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return Alloc(pPrevBlock, pCurBlock, newSize, oldnewSize);
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_Page::Free(FX_LPVOID p)
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)m_pLimitPos);
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Block *pPrevBlock = &m_AvailHead;
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Block *pNextBlock;
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Block *pBlock = (CFXMEM_Block*)p - 1;
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_nAvailSize += pBlock->m_nBlockSize;
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (TRUE) {
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pNextBlock = pPrevBlock->m_pNextBlock;
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pNextBlock == NULL || pNextBlock > pBlock) {
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pPrevBlock != &m_AvailHead && (FX_LPBYTE)pNextBlock == (FX_LPBYTE)(pPrevBlock + 1) + pPrevBlock->m_nBlockSize) {
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_nAvailSize += sizeof(CFXMEM_Block);
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pPrevBlock->m_nBlockSize += pNextBlock->m_nBlockSize + sizeof(CFXMEM_Block);
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pPrevBlock->m_pNextBlock = pNextBlock->m_pNextBlock;
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pPrevBlock = pNextBlock;
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ((FX_LPBYTE)pNextBlock == (FX_LPBYTE)(pBlock + 1) + pBlock->m_nBlockSize) {
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_nAvailSize += sizeof(CFXMEM_Block);
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pBlock->m_nBlockSize += pNextBlock->m_nBlockSize + sizeof(CFXMEM_Block);
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pNextBlock = pNextBlock->m_pNextBlock;
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pBlock->m_pNextBlock = pNextBlock;
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pPrevBlock != &m_AvailHead && (FX_LPBYTE)pBlock == (FX_LPBYTE)(pPrevBlock + 1) + pPrevBlock->m_nBlockSize) {
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_nAvailSize += sizeof(CFXMEM_Block);
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPrevBlock->m_nBlockSize += pBlock->m_nBlockSize + sizeof(CFXMEM_Block);
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPrevBlock->m_pNextBlock = pBlock->m_pNextBlock;
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_assert(pPrevBlock != pBlock);
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPrevBlock->m_pNextBlock = pBlock;
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_Pages::Initialize(FX_LPBYTE pStart, size_t pageSize, size_t pages)
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pStartPage = m_pCurPage = (CFXMEM_Page*)pStart;
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_nPageSize = pageSize;
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (size_t n = 0; n < pages; n++) {
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ((CFXMEM_Page*)pStart)->Initialize(pageSize);
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pStart += pageSize;
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pLimitPos = (CFXMEM_Page*)pStart;
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFXMEM_Pages::IsEmpty() const
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pStartPage >= m_pLimitPos) {
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPBYTE pPage = (FX_LPBYTE)m_pStartPage;
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (pPage < (FX_LPBYTE)m_pLimitPos) {
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!((CFXMEM_Page*)pPage)->IsEmpty()) {
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPage += m_nPageSize;
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_Pages::Alloc(size_t size)
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Page *pCurPage = m_pCurPage;
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    do {
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPVOID p = m_pCurPage->Alloc(size);
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p) {
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return p;
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pCurPage = (CFXMEM_Page*)((FX_LPBYTE)m_pCurPage + m_nPageSize);
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_pCurPage == m_pLimitPos) {
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_pCurPage = m_pStartPage;
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } while (m_pCurPage != pCurPage);
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_Pages::Realloc(FX_LPVOID p, size_t oldSize, size_t newSize)
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert (p > (FX_LPVOID)m_pStartPage && p < (FX_LPVOID)m_pLimitPos);
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Page* pPage = (CFXMEM_Page*)((FX_LPBYTE)m_pStartPage + ((FX_LPBYTE)p - (FX_LPBYTE)m_pStartPage) / m_nPageSize * m_nPageSize);
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return pPage->Realloc(p, oldSize, newSize);
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_Pages::Free(FX_LPVOID p)
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert (p > (FX_LPVOID)m_pStartPage && p < (FX_LPVOID)m_pLimitPos);
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Page* pPage = (CFXMEM_Page*)((FX_LPBYTE)m_pStartPage + ((FX_LPBYTE)p - (FX_LPBYTE)m_pStartPage) / m_nPageSize * m_nPageSize);
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pPage->Free(p);
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_Pool::Initialize(const FX_MEMCONFIG* pMemConfig, size_t size, size_t pageNum8Bytes, size_t pageNum16Bytes, size_t pageNum32Bytes, size_t pageNumMid)
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pPrevPool = NULL;
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pNextPool = NULL;
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bAlone = FALSE;
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPBYTE pPage = (FX_LPBYTE)this + sizeof(CFXMEM_Pool);
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size -= sizeof(CFXMEM_Pool);
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_8BytesPages.Initialize(pPage, pageNum8Bytes);
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pPage += pageNum8Bytes * FX_FIXEDMEM_PAGESIZE;
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size -= pageNum8Bytes * FX_FIXEDMEM_PAGESIZE;
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_16BytesPages.Initialize(pPage, pageNum16Bytes);
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pPage += pageNum16Bytes * FX_FIXEDMEM_PAGESIZE;
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size -= pageNum16Bytes * FX_FIXEDMEM_PAGESIZE;
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_32BytesPages.Initialize(pPage, pageNum32Bytes);
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pPage += pageNum32Bytes * FX_FIXEDMEM_PAGESIZE;
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size -= pageNum32Bytes * FX_FIXEDMEM_PAGESIZE;
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_MidPages.Initialize(pPage, pMemConfig->nPageSize_Mid * FX_FIXEDMEM_PAGESIZE, pageNumMid);
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pPage += pageNumMid * pMemConfig->nPageSize_Mid * FX_FIXEDMEM_PAGESIZE;
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size -= pageNumMid * pMemConfig->nPageSize_Mid * FX_FIXEDMEM_PAGESIZE;
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (size < FX_FIXEDMEM_MIDBLOCKSIZE) {
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pLargePage = NULL;
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pLargePage = (CFXMEM_Page*)pPage;
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pLargePage->Initialize(size);
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pLimitPos = pPage + size;
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFXMEM_Pool::IsEmpty() const
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_8BytesPages.IsEmpty()) {
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_16BytesPages.IsEmpty()) {
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_32BytesPages.IsEmpty()) {
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_MidPages.IsEmpty()) {
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return !m_pLargePage || m_pLargePage->IsEmpty();
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovsize_t CFXMEM_Pool::GetSize(FX_LPVOID p) const
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)m_pLimitPos);
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p < (FX_LPVOID)m_8BytesPages.m_pLimitPos) {
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 8;
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p < (FX_LPVOID)m_16BytesPages.m_pLimitPos) {
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 16;
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p < (FX_LPVOID)m_32BytesPages.m_pLimitPos) {
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 32;
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ((CFXMEM_Block*)p - 1)->m_nBlockSize;
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_Pool::Realloc(FX_LPVOID p, size_t oldSize, size_t newSize)
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)m_pLimitPos);
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p > (FX_LPVOID)m_32BytesPages.m_pLimitPos) {
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p < (FX_LPVOID)m_MidPages.m_pLimitPos) {
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return m_MidPages.Realloc(p, oldSize, newSize);
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (m_pLargePage) {
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return m_pLargePage->Realloc(p, oldSize, newSize);
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_Pool::Free(FX_LPVOID p)
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)m_pLimitPos);
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p < (FX_LPVOID)m_32BytesPages.m_pLimitPos) {
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p < (FX_LPVOID)m_8BytesPages.m_pLimitPos) {
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_8BytesPages.Free(p);
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (p < (FX_LPVOID)m_16BytesPages.m_pLimitPos) {
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_16BytesPages.Free(p);
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_32BytesPages.Free(p);
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (p < (FX_LPVOID)m_MidPages.m_pLimitPos) {
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_MidPages.Free(p);
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pLargePage->Free(p);
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_FixedMgr::Initialize(size_t size)
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_MemConfig = g_MemConfig;
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memset32(&m_SystemMgr, 0, sizeof m_SystemMgr);
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_SystemMgr.Alloc = FixedAlloc;
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_SystemMgr.AllocDebug = FixedAllocDebug;
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_SystemMgr.Free = FixedFree;
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_SystemMgr.Realloc = FixedRealloc;
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_SystemMgr.ReallocDebug = FixedReallocDebug;
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_SystemMgr.CollectAll = FixedCollectAll;
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_SystemMgr.Purge = FixedPurge;
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_SystemMgr.user = this;
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size -= sizeof(CFXMEM_FixedMgr);
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t nMidPages = 0;
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_MemConfig.nPageSize_Mid) {
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        nMidPages = (size - (m_MemConfig.nPageNum_Init8 + m_MemConfig.nPageNum_Init16 + m_MemConfig.nPageNum_Init32) * FX_FIXEDMEM_PAGESIZE) / (m_MemConfig.nPageSize_Mid * FX_FIXEDMEM_PAGESIZE);
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (nMidPages > m_MemConfig.nPageNum_InitMid) {
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            nMidPages = m_MemConfig.nPageNum_InitMid;
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_FirstPool.Initialize(&m_MemConfig, size, m_MemConfig.nPageNum_Init8, m_MemConfig.nPageNum_Init16, m_MemConfig.nPageNum_Init32, nMidPages);
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_FixedMgr::Alloc16(CFXMEM_Pool **pp32Pool, size_t size)
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool *pPool = &m_FirstPool;
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    do {
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFXMEM_16BytesPages &pages = pPool->m_16BytesPages;
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pages.HasFreeBlock()) {
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return pages.Alloc(size);
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pp32Pool && pPool->m_32BytesPages.HasFreeBlock()) {
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            *pp32Pool = pPool;
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPool = pPool->m_pNextPool;
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } while(pPool);
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_FixedMgr::Alloc32(size_t size)
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (size <= 8) {
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFXMEM_8BytesPages &pages = m_FirstPool.m_8BytesPages;
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pages.HasFreeBlock()) {
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return pages.Alloc(size);
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool *p32BytesPool;
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (size <= 16) {
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p32BytesPool = NULL;
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPVOID p = Alloc16(&p32BytesPool, size);
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p) {
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return p;
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p32BytesPool = &m_FirstPool;
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (p32BytesPool) {
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFXMEM_32BytesPages &pages = p32BytesPool->m_32BytesPages;
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pages.HasFreeBlock()) {
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return pages.Alloc(size);
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p32BytesPool = p32BytesPool->m_pNextPool;
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_FixedMgr::AllocSmall(size_t size)
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPVOID p = Alloc32(size);
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p) {
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return p;
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_pExtender) {
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t requiredSize = (m_MemConfig.nPageNum_More16 + m_MemConfig.nPageNum_More32) * FX_FIXEDMEM_PAGESIZE;
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!requiredSize) {
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool *pNewPool = NULL;
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    requiredSize += sizeof(CFXMEM_Pool);
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t newSize = requiredSize;
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_pExtender->More(m_pExtender, newSize, (void**)&pNewPool, &newSize)) {
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t nMidPages = 0;
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_MemConfig.nPageSize_Mid) {
553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        nMidPages = (newSize - requiredSize) / (m_MemConfig.nPageSize_Mid * FX_FIXEDMEM_PAGESIZE);
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (nMidPages > m_MemConfig.nPageNum_MoreMid) {
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            nMidPages = m_MemConfig.nPageNum_MoreMid;
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pNewPool->Initialize(&m_MemConfig, newSize, 0, m_MemConfig.nPageNum_More16, m_MemConfig.nPageNum_More32, nMidPages);
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pNewPool->m_pPrevPool = &m_FirstPool;
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool *pPool = m_FirstPool.m_pNextPool;
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pNewPool->m_pNextPool = pPool;
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pPool) {
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPool->m_pPrevPool = pNewPool;
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_FirstPool.m_pNextPool = pNewPool;
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return Alloc32(size);
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_FixedMgr::AllocMid(size_t size)
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool *pPool = &m_FirstPool;
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    do {
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFXMEM_Pages &pages = pPool->m_MidPages;
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pages.m_pLimitPos > pages.m_pStartPage) {
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_LPVOID p = pages.Alloc(size);
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (p) {
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return p;
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPool = pPool->m_pNextPool;
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } while(pPool);
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_pExtender) {
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t newSize = m_MemConfig.nPageSize_Mid * FX_FIXEDMEM_PAGESIZE * m_MemConfig.nPageNum_MoreMid;
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!newSize) {
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool *pNewPool = NULL;
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    newSize += sizeof(CFXMEM_Pool);
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_pExtender->More(m_pExtender, newSize, (void**)&pNewPool, &newSize)) {
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t nMidPages = (newSize - sizeof(CFXMEM_Pool)) / (m_MemConfig.nPageSize_Mid * FX_FIXEDMEM_PAGESIZE);
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nMidPages > m_MemConfig.nPageNum_MoreMid) {
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        nMidPages = m_MemConfig.nPageNum_MoreMid;
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pNewPool->Initialize(&m_MemConfig, newSize, 0, 0, 0, nMidPages);
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pNewPool->m_pPrevPool = &m_FirstPool;
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pPool = m_FirstPool.m_pNextPool;
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pNewPool->m_pNextPool = pPool;
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pPool) {
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPool->m_pPrevPool = pNewPool;
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_FirstPool.m_pNextPool = pNewPool;
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return pNewPool->m_MidPages.Alloc(size);
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_FixedMgr::AllocLarge(size_t size)
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool *pPool = &m_FirstPool;
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    do {
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!pPool->m_bAlone && pPool->m_pLargePage) {
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_LPVOID p = pPool->m_pLargePage->Alloc(size);
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (p) {
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return p;
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPool = pPool->m_pNextPool;
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } while(pPool);
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_pExtender || !m_MemConfig.nPageSize_Large) {
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool *pNewPool = NULL;
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if _FX_WORDSIZE_ == _FX_W64_
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t newSize = ((size + 31) / 32 * 32 + sizeof(CFXMEM_Pool) + sizeof(CFXMEM_Page) + sizeof(CFXMEM_Block) + 4095) / 4096 * 4096;
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t newSize = (size + 7) / 8 * 8 + sizeof(CFXMEM_Pool) + sizeof(CFXMEM_Page) + sizeof(CFXMEM_Block);
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (newSize < m_MemConfig.nPageSize_Large * FX_FIXEDMEM_PAGESIZE) {
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        newSize = m_MemConfig.nPageSize_Large * FX_FIXEDMEM_PAGESIZE;
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_pExtender->More(m_pExtender, newSize, (void**)&pNewPool, &newSize)) {
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pNewPool->Initialize(&m_MemConfig, newSize, 0, 0, 0, 0);
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pNewPool->m_bAlone = size >= m_MemConfig.nPageSize_Alone * FX_FIXEDMEM_PAGESIZE;
636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pNewPool->m_pPrevPool = &m_FirstPool;
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pPool = m_FirstPool.m_pNextPool;
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pNewPool->m_pNextPool = pPool;
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pPool) {
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPool->m_pPrevPool = pNewPool;
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_FirstPool.m_pNextPool = pNewPool;
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return pNewPool->m_pLargePage->Alloc(size);
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovsize_t CFXMEM_FixedMgr::GetSize(FX_LPVOID p) const
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const CFXMEM_Pool *pFind = &m_FirstPool;
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    do {
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p > (FX_LPVOID)pFind && p < pFind->m_pLimitPos) {
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return pFind->GetSize(p);
651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pFind = pFind->m_pNextPool;
653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } while (pFind);
654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return 0;
655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
656ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_FixedMgr::Alloc(size_t size)
657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPVOID p;
659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (size <= 32) {
660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p = AllocSmall(size);
661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p) {
662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return p;
663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (size <= FX_FIXEDMEM_MIDBLOCKSIZE) {
666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p = AllocMid(size);
667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p) {
668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return p;
669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p = AllocLarge(size);
672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return p;
673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
674ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_FixedMgr::ReallocSmall(CFXMEM_Pool* pPool, FX_LPVOID p, size_t oldSize, size_t newSize)
675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPVOID np = AllocSmall(newSize);
677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!np) {
678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(np, p, oldSize);
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pPool->Free(p);
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return np;
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CFXMEM_FixedMgr::Realloc(FX_LPVOID p, size_t newSize)
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!p) {
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return Alloc(newSize);
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size_t oldSize = 0;
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool *pFind = &m_FirstPool;
691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    do {
692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p > (FX_LPVOID)pFind && p < pFind->m_pLimitPos) {
693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            oldSize = pFind->GetSize(p);
694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (oldSize >= newSize) {
695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return p;
696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pFind = pFind->m_pNextPool;
700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } while (pFind);
701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!oldSize || !pFind) {
702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return Alloc(newSize);
703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPVOID np = NULL;
705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (newSize <= 32) {
706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        np = ReallocSmall(pFind, p, oldSize, newSize);
707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (np) {
708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return np;
709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (newSize <= FX_FIXEDMEM_MIDBLOCKSIZE) {
712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        np = pFind->Realloc(p, oldSize, newSize);
713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (np) {
714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return np;
715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    np = Alloc(newSize);
718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (np) {
719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(np, p, oldSize);
720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pFind->Free(p);
721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pFind->m_bAlone && pFind->IsEmpty()) {
723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FreePool(pFind);
724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return np;
726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_FixedMgr::Free(FX_LPVOID p)
728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool *pFind = &m_FirstPool;
730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    do {
731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p > (FX_LPVOID)pFind && p < pFind->m_pLimitPos) {
732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pFind->Free(p);
733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (pFind->m_bAlone && pFind->IsEmpty()) {
734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FreePool(pFind);
735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return;
737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pFind = pFind->m_pNextPool;
739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } while (pFind);
740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_FixedMgr::FreePool(CFXMEM_Pool* pPool)
742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(pPool->m_bAlone && pPool->IsEmpty());
744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(m_pExtender != NULL);
745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool* pPrevPool = pPool->m_pPrevPool;
746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool* pNextPool = pPool->m_pNextPool;
747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pPrevPool) {
748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPrevPool->m_pNextPool = pNextPool;
749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pNextPool) {
751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pNextPool->m_pPrevPool = pPrevPool;
752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pExtender->Free(m_pExtender, pPool);
754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_FixedMgr::FreeAll()
756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_pExtender) {
758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool* pPool = m_FirstPool.m_pNextPool;
761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (pPool) {
762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFXMEM_Pool* pPrevPool = pPool;
763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPool = pPool->m_pNextPool;
764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pExtender->Free(m_pExtender, pPrevPool);
765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_FirstPool.m_pNextPool = NULL;
767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFXMEM_FixedMgr::Purge()
769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!m_pExtender) {
771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFXMEM_Pool* pPool = m_FirstPool.m_pNextPool;
774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (pPool) {
775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFXMEM_Pool* pNextPool = pPool->m_pNextPool;
776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pPool->IsEmpty()) {
777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CFXMEM_Pool* pPrevPool = pPool->m_pPrevPool;
778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pPrevPool->m_pNextPool = pNextPool;
779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (pNextPool) {
780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pNextPool->m_pPrevPool = pPrevPool;
781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_pExtender->Free(m_pExtender, pPool);
783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pPool = pNextPool;
785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovextern const FX_BYTE OneLeadPos[256] = {
788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovextern const FX_BYTE ZeroLeadPos[256] = {
806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
823