// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
 
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "../../include/fxcrt/fx_ext.h"
#include "plex.h"
static void ConstructElement(CFX_ByteString* pNewData)
{
    new (pNewData) CFX_ByteString();
}
static void DestructElement(CFX_ByteString* pOldData)
{
    pOldData->~CFX_ByteString();
}
CFX_MapPtrToPtr::CFX_MapPtrToPtr(int nBlockSize, IFX_Allocator* pAllocator)
    : m_pAllocator(pAllocator)
    , m_pHashTable(NULL)
    , m_nHashTableSize(17)
    , m_nCount(0)
    , m_pFreeList(NULL)
    , m_pBlocks(NULL)
    , m_nBlockSize(nBlockSize)
{
    ASSERT(m_nBlockSize > 0);
}
void CFX_MapPtrToPtr::RemoveAll()
{
    if (m_pHashTable) {
        FX_Allocator_Free(m_pAllocator, m_pHashTable);
        m_pHashTable = NULL;
    }
    m_nCount = 0;
    m_pFreeList = NULL;
    m_pBlocks->FreeDataChain(m_pAllocator);
    m_pBlocks = NULL;
}
CFX_MapPtrToPtr::~CFX_MapPtrToPtr()
{
    RemoveAll();
    ASSERT(m_nCount == 0);
}
FX_DWORD CFX_MapPtrToPtr::HashKey(void* key) const
{
    return ((FX_DWORD)(FX_UINTPTR)key) >> 4;
}
void CFX_MapPtrToPtr::GetNextAssoc(FX_POSITION& rNextPosition, void*& rKey, void*& rValue) const
{
    ASSERT(m_pHashTable != NULL);
    CAssoc* pAssocRet = (CAssoc*)rNextPosition;
    ASSERT(pAssocRet != NULL);
    if (pAssocRet == (CAssoc*) - 1) {
        for (FX_DWORD nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
            if ((pAssocRet = m_pHashTable[nBucket]) != NULL) {
                break;
            }
        ASSERT(pAssocRet != NULL);
    }
    CAssoc* pAssocNext;
    if ((pAssocNext = pAssocRet->pNext) == NULL) {
        for (FX_DWORD nBucket = (HashKey(pAssocRet->key) % m_nHashTableSize) + 1; nBucket < m_nHashTableSize; nBucket ++) {
            if ((pAssocNext = m_pHashTable[nBucket]) != NULL) {
                break;
            }
        }
    }
    rNextPosition = (FX_POSITION) pAssocNext;
    rKey = pAssocRet->key;
    rValue = pAssocRet->value;
}
FX_BOOL CFX_MapPtrToPtr::Lookup(void* key, void*& rValue) const
{
    FX_DWORD nHash;
    CAssoc* pAssoc = GetAssocAt(key, nHash);
    if (pAssoc == NULL) {
        return FALSE;
    }
    rValue = pAssoc->value;
    return TRUE;
}
void* CFX_MapPtrToPtr::GetValueAt(void* key) const
{
    FX_DWORD nHash;
    CAssoc* pAssoc = GetAssocAt(key, nHash);
    if (pAssoc == NULL) {
        return NULL;
    }
    return pAssoc->value;
}
void*& CFX_MapPtrToPtr::operator[](void* key)
{
    FX_DWORD nHash;
    CAssoc* pAssoc;
    if ((pAssoc = GetAssocAt(key, nHash)) == NULL) {
        if (m_pHashTable == NULL) {
            InitHashTable(m_nHashTableSize);
        }
        pAssoc = NewAssoc();
        pAssoc->key = key;
        pAssoc->pNext = m_pHashTable[nHash];
        m_pHashTable[nHash] = pAssoc;
    }
    return pAssoc->value;
}
CFX_MapPtrToPtr::CAssoc*
CFX_MapPtrToPtr::GetAssocAt(void* key, FX_DWORD& nHash) const
{
    nHash = HashKey(key) % m_nHashTableSize;
    if (m_pHashTable == NULL) {
        return NULL;
    }
    CAssoc* pAssoc;
    for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext) {
        if (pAssoc->key == key) {
            return pAssoc;
        }
    }
    return NULL;
}
CFX_MapPtrToPtr::CAssoc*
CFX_MapPtrToPtr::NewAssoc()
{
    if (m_pFreeList == NULL) {
        CFX_Plex* newBlock = CFX_Plex::Create(m_pAllocator, m_pBlocks, m_nBlockSize, sizeof(CFX_MapPtrToPtr::CAssoc));
        CFX_MapPtrToPtr::CAssoc* pAssoc = (CFX_MapPtrToPtr::CAssoc*)newBlock->data();
        pAssoc += m_nBlockSize - 1;
        for (int i = m_nBlockSize - 1; i >= 0; i--, pAssoc--) {
            pAssoc->pNext = m_pFreeList;
            m_pFreeList = pAssoc;
        }
    }
    ASSERT(m_pFreeList != NULL);
    CFX_MapPtrToPtr::CAssoc* pAssoc = m_pFreeList;
    m_pFreeList = m_pFreeList->pNext;
    m_nCount++;
    ASSERT(m_nCount > 0);
    pAssoc->key = 0;
    pAssoc->value = 0;
    return pAssoc;
}
void CFX_MapPtrToPtr::InitHashTable(
    FX_DWORD nHashSize, FX_BOOL bAllocNow)
{
    ASSERT(m_nCount == 0);
    ASSERT(nHashSize > 0);
    if (m_pHashTable != NULL) {
        FX_Allocator_Free(m_pAllocator, m_pHashTable);
        m_pHashTable = NULL;
    }
    if (bAllocNow) {
        m_pHashTable = FX_Allocator_Alloc(m_pAllocator, CAssoc*, nHashSize);
        if (m_pHashTable) {
            FXSYS_memset32(m_pHashTable, 0, sizeof(CAssoc*) * nHashSize);
        }
    }
    m_nHashTableSize = nHashSize;
}
FX_BOOL CFX_MapPtrToPtr::RemoveKey(void* key)
{
    if (m_pHashTable == NULL) {
        return FALSE;
    }
    CAssoc** ppAssocPrev;
    ppAssocPrev = &m_pHashTable[HashKey(key) % m_nHashTableSize];
    CAssoc* pAssoc;
    for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext) {
        if (pAssoc->key == key) {
            *ppAssocPrev = pAssoc->pNext;
            FreeAssoc(pAssoc);
            return TRUE;
        }
        ppAssocPrev = &pAssoc->pNext;
    }
    return FALSE;
}
void CFX_MapPtrToPtr::FreeAssoc(CFX_MapPtrToPtr::CAssoc* pAssoc)
{
    pAssoc->pNext = m_pFreeList;
    m_pFreeList = pAssoc;
    m_nCount--;
    ASSERT(m_nCount >= 0);
    if (m_nCount == 0) {
        RemoveAll();
    }
}
CFX_MapByteStringToPtr::CFX_MapByteStringToPtr(int nBlockSize, IFX_Allocator* pAllocator)
    : m_pAllocator(pAllocator)
    , m_pHashTable(NULL)
    , m_nHashTableSize(17)
    , m_nCount(0)
    , m_pFreeList(NULL)
    , m_pBlocks(NULL)
    , m_nBlockSize(nBlockSize)
{
    ASSERT(m_nBlockSize > 0);
}
void CFX_MapByteStringToPtr::RemoveAll()
{
    if (m_pHashTable != NULL) {
        for (FX_DWORD nHash = 0; nHash < m_nHashTableSize; nHash++) {
            CAssoc* pAssoc;
            for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
                    pAssoc = pAssoc->pNext) {
                DestructElement(&pAssoc->key);
            }
        }
        FX_Allocator_Free(m_pAllocator, m_pHashTable);
        m_pHashTable = NULL;
    }
    m_nCount = 0;
    m_pFreeList = NULL;
    m_pBlocks->FreeDataChain(m_pAllocator);
    m_pBlocks = NULL;
}
CFX_MapByteStringToPtr::~CFX_MapByteStringToPtr()
{
    RemoveAll();
    ASSERT(m_nCount == 0);
}
void CFX_MapByteStringToPtr::GetNextAssoc(FX_POSITION& rNextPosition,
        CFX_ByteString& rKey, void*& rValue) const
{
    ASSERT(m_pHashTable != NULL);
    CAssoc* pAssocRet = (CAssoc*)rNextPosition;
    ASSERT(pAssocRet != NULL);
    if (pAssocRet == (CAssoc*) - 1) {
        for (FX_DWORD nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
            if ((pAssocRet = m_pHashTable[nBucket]) != NULL) {
                break;
            }
        ASSERT(pAssocRet != NULL);
    }
    CAssoc* pAssocNext;
    if ((pAssocNext = pAssocRet->pNext) == NULL) {
        for (FX_DWORD nBucket = pAssocRet->nHashValue + 1;
                nBucket < m_nHashTableSize; nBucket++)
            if ((pAssocNext = m_pHashTable[nBucket]) != NULL) {
                break;
            }
    }
    rNextPosition = (FX_POSITION) pAssocNext;
    rKey = pAssocRet->key;
    rValue = pAssocRet->value;
}
FX_LPVOID CFX_MapByteStringToPtr::GetNextValue(FX_POSITION& rNextPosition) const
{
    ASSERT(m_pHashTable != NULL);
    CAssoc* pAssocRet = (CAssoc*)rNextPosition;
    ASSERT(pAssocRet != NULL);
    if (pAssocRet == (CAssoc*) - 1) {
        for (FX_DWORD nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
            if ((pAssocRet = m_pHashTable[nBucket]) != NULL) {
                break;
            }
        ASSERT(pAssocRet != NULL);
    }
    CAssoc* pAssocNext;
    if ((pAssocNext = pAssocRet->pNext) == NULL) {
        for (FX_DWORD nBucket = pAssocRet->nHashValue + 1;
                nBucket < m_nHashTableSize; nBucket++)
            if ((pAssocNext = m_pHashTable[nBucket]) != NULL) {
                break;
            }
    }
    rNextPosition = (FX_POSITION) pAssocNext;
    return pAssocRet->value;
}
void*& CFX_MapByteStringToPtr::operator[](FX_BSTR key)
{
    FX_DWORD nHash;
    CAssoc* pAssoc;
    if ((pAssoc = GetAssocAt(key, nHash)) == NULL) {
        if (m_pHashTable == NULL) {
            InitHashTable(m_nHashTableSize);
        }
        pAssoc = NewAssoc();
        pAssoc->nHashValue = nHash;
        pAssoc->key = key;
        pAssoc->pNext = m_pHashTable[nHash];
        m_pHashTable[nHash] = pAssoc;
    }
    return pAssoc->value;
}
CFX_MapByteStringToPtr::CAssoc*
CFX_MapByteStringToPtr::NewAssoc()
{
    if (m_pFreeList == NULL) {
        CFX_Plex* newBlock = CFX_Plex::Create(m_pAllocator, m_pBlocks, m_nBlockSize, sizeof(CFX_MapByteStringToPtr::CAssoc));
        CFX_MapByteStringToPtr::CAssoc* pAssoc = (CFX_MapByteStringToPtr::CAssoc*)newBlock->data();
        pAssoc += m_nBlockSize - 1;
        for (int i = m_nBlockSize - 1; i >= 0; i--, pAssoc--) {
            pAssoc->pNext = m_pFreeList;
            m_pFreeList = pAssoc;
        }
    }
    ASSERT(m_pFreeList != NULL);
    CFX_MapByteStringToPtr::CAssoc* pAssoc = m_pFreeList;
    m_pFreeList = m_pFreeList->pNext;
    m_nCount++;
    ASSERT(m_nCount > 0);
    ConstructElement(&pAssoc->key);
    pAssoc->value = 0;
    return pAssoc;
}
void CFX_MapByteStringToPtr::FreeAssoc(CFX_MapByteStringToPtr::CAssoc* pAssoc)
{
    DestructElement(&pAssoc->key);
    pAssoc->pNext = m_pFreeList;
    m_pFreeList = pAssoc;
    m_nCount--;
    ASSERT(m_nCount >= 0);
    if (m_nCount == 0) {
        RemoveAll();
    }
}
CFX_MapByteStringToPtr::CAssoc*
CFX_MapByteStringToPtr::GetAssocAt(FX_BSTR key, FX_DWORD& nHash) const
{
    nHash = HashKey(key) % m_nHashTableSize;
    if (m_pHashTable == NULL) {
        return NULL;
    }
    CAssoc* pAssoc;
    for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext) {
        if (pAssoc->key == key) {
            return pAssoc;
        }
    }
    return NULL;
}
FX_BOOL CFX_MapByteStringToPtr::Lookup(FX_BSTR key, void*& rValue) const
{
    FX_DWORD nHash;
    CAssoc* pAssoc = GetAssocAt(key, nHash);
    if (pAssoc == NULL) {
        return FALSE;
    }
    rValue = pAssoc->value;
    return TRUE;
}
void CFX_MapByteStringToPtr::InitHashTable(
    FX_DWORD nHashSize, FX_BOOL bAllocNow)
{
    ASSERT(m_nCount == 0);
    ASSERT(nHashSize > 0);
    if (m_pHashTable != NULL) {
        FX_Allocator_Free(m_pAllocator, m_pHashTable);
        m_pHashTable = NULL;
    }
    if (bAllocNow) {
        m_pHashTable = FX_Allocator_Alloc(m_pAllocator, CAssoc*, nHashSize);
        if (m_pHashTable) {
            FXSYS_memset32(m_pHashTable, 0, sizeof(CAssoc*) * nHashSize);
        }
    }
    m_nHashTableSize = nHashSize;
}
inline FX_DWORD CFX_MapByteStringToPtr::HashKey(FX_BSTR key) const
{
    FX_DWORD nHash = 0;
    int len = key.GetLength();
    FX_LPCBYTE buf = key;
    for (int i = 0; i < len; i ++) {
        nHash = (nHash << 5) + nHash + buf[i];
    }
    return nHash;
}
FX_BOOL CFX_MapByteStringToPtr::RemoveKey(FX_BSTR key)
{
    if (m_pHashTable == NULL) {
        return FALSE;
    }
    CAssoc** ppAssocPrev;
    ppAssocPrev = &m_pHashTable[HashKey(key) % m_nHashTableSize];
    CAssoc* pAssoc;
    for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext) {
        if (pAssoc->key == key) {
            *ppAssocPrev = pAssoc->pNext;
            FreeAssoc(pAssoc);
            return TRUE;
        }
        ppAssocPrev = &pAssoc->pNext;
    }
    return FALSE;
}
struct _CompactString {
    FX_BYTE		m_CompactLen;
    FX_BYTE		m_LenHigh;
    FX_BYTE		m_LenLow;
    FX_BYTE		m_Unused;
    FX_LPBYTE	m_pBuffer;
};
static void _CompactStringRelease(IFX_Allocator* pAllocator, _CompactString* pCompact)
{
    if (pCompact->m_CompactLen == 0xff) {
        FX_Allocator_Free(pAllocator, pCompact->m_pBuffer);
    }
}
static FX_BOOL _CompactStringSame(_CompactString* pCompact, FX_LPCBYTE pStr, int len)
{
    if (len < sizeof(_CompactString)) {
        if (pCompact->m_CompactLen != len) {
            return FALSE;
        }
        return FXSYS_memcmp32(&pCompact->m_LenHigh, pStr, len) == 0;
    }
    if (pCompact->m_CompactLen != 0xff || pCompact->m_LenHigh * 256 + pCompact->m_LenLow != len) {
        return FALSE;
    }
    return FXSYS_memcmp32(pCompact->m_pBuffer, pStr, len) == 0;
}
static void _CompactStringStore(IFX_Allocator* pAllocator, _CompactString* pCompact, FX_LPCBYTE pStr, int len)
{
    if (len < (int)sizeof(_CompactString)) {
        pCompact->m_CompactLen = (FX_BYTE)len;
        FXSYS_memcpy32(&pCompact->m_LenHigh, pStr, len);
        return;
    }
    pCompact->m_CompactLen = 0xff;
    pCompact->m_LenHigh = len / 256;
    pCompact->m_LenLow = len % 256;
    pCompact->m_pBuffer = FX_Allocator_Alloc(pAllocator, FX_BYTE, len);
    if (pCompact->m_pBuffer) {
        FXSYS_memcpy32(pCompact->m_pBuffer, pStr, len);
    }
}
static CFX_ByteStringC _CompactStringGet(_CompactString* pCompact)
{
    if (pCompact->m_CompactLen == 0xff) {
        return CFX_ByteStringC(pCompact->m_pBuffer, pCompact->m_LenHigh * 256 + pCompact->m_LenLow);
    }
    if (pCompact->m_CompactLen == 0xfe) {
        return CFX_ByteStringC();
    }
    return CFX_ByteStringC(&pCompact->m_LenHigh, pCompact->m_CompactLen);
}
#define CMAP_ALLOC_STEP		8
#define CMAP_INDEX_SIZE		8
CFX_CMapByteStringToPtr::CFX_CMapByteStringToPtr(IFX_Allocator* pAllocator)
    : m_Buffer(sizeof(_CompactString) + sizeof(void*), CMAP_ALLOC_STEP, CMAP_INDEX_SIZE, pAllocator)
{
}
CFX_CMapByteStringToPtr::~CFX_CMapByteStringToPtr()
{
    RemoveAll();
}
void CFX_CMapByteStringToPtr::RemoveAll()
{
    IFX_Allocator* pAllocator = m_Buffer.m_pAllocator;
    int size = m_Buffer.GetSize();
    for (int i = 0; i < size; i ++) {
        _CompactStringRelease(pAllocator, (_CompactString*)m_Buffer.GetAt(i));
    }
    m_Buffer.RemoveAll();
}
FX_POSITION CFX_CMapByteStringToPtr::GetStartPosition() const
{
    int size = m_Buffer.GetSize();
    for (int i = 0; i < size; i ++) {
        _CompactString* pKey = (_CompactString*)m_Buffer.GetAt(i);
        if (pKey->m_CompactLen != 0xfe) {
            return (FX_POSITION)(FX_UINTPTR)(i + 1);
        }
    }
    return NULL;
}
void CFX_CMapByteStringToPtr::GetNextAssoc(FX_POSITION& rNextPosition, CFX_ByteString& rKey, void*& rValue) const
{
    if (rNextPosition == NULL) {
        return;
    }
    int index = (int)(FX_UINTPTR)rNextPosition - 1;
    _CompactString* pKey = (_CompactString*)m_Buffer.GetAt(index);
    rKey = _CompactStringGet(pKey);
    rValue = *(void**)(pKey + 1);
    index ++;
    int size = m_Buffer.GetSize();
    while (index < size) {
        pKey = (_CompactString*)m_Buffer.GetAt(index);
        if (pKey->m_CompactLen != 0xfe) {
            rNextPosition = (FX_POSITION)(FX_UINTPTR)(index + 1);
            return;
        }
        index ++;
    }
    rNextPosition = NULL;
}
FX_LPVOID CFX_CMapByteStringToPtr::GetNextValue(FX_POSITION& rNextPosition) const
{
    if (rNextPosition == NULL) {
        return NULL;
    }
    int index = (int)(FX_UINTPTR)rNextPosition - 1;
    _CompactString* pKey = (_CompactString*)m_Buffer.GetAt(index);
    FX_LPVOID rValue = *(void**)(pKey + 1);
    index ++;
    int size = m_Buffer.GetSize();
    while (index < size) {
        pKey = (_CompactString*)m_Buffer.GetAt(index);
        if (pKey->m_CompactLen != 0xfe) {
            rNextPosition = (FX_POSITION)(FX_UINTPTR)(index + 1);
            return rValue;
        }
        index ++;
    }
    rNextPosition = NULL;
    return rValue;
}
FX_BOOL _CMapLookupCallback(void* param, void* pData)
{
    return !_CompactStringSame((_CompactString*)pData, ((CFX_ByteStringC*)param)->GetPtr(), ((CFX_ByteStringC*)param)->GetLength());
}
FX_BOOL CFX_CMapByteStringToPtr::Lookup(FX_BSTR key, void*& rValue) const
{
    void* p = m_Buffer.Iterate(_CMapLookupCallback, (void*)&key);
    if (!p) {
        return FALSE;
    }
    rValue = *(void**)((_CompactString*)p + 1);
    return TRUE;
}
void CFX_CMapByteStringToPtr::SetAt(FX_BSTR key, void* value)
{
    ASSERT(value != NULL);
    int index, key_len = key.GetLength();
    int size = m_Buffer.GetSize();
    for (index = 0; index < size; index ++) {
        _CompactString* pKey = (_CompactString*)m_Buffer.GetAt(index);
        if (!_CompactStringSame(pKey, (FX_LPCBYTE)key, key_len)) {
            continue;
        }
        *(void**)(pKey + 1) = value;
        return;
    }
    IFX_Allocator* pAllocator = m_Buffer.m_pAllocator;
    for (index = 0; index < size; index ++) {
        _CompactString* pKey = (_CompactString*)m_Buffer.GetAt(index);
        if (pKey->m_CompactLen) {
            continue;
        }
        _CompactStringStore(pAllocator, pKey, (FX_LPCBYTE)key, key_len);
        *(void**)(pKey + 1) = value;
        return;
    }
    _CompactString* pKey = (_CompactString*)m_Buffer.Add();
    _CompactStringStore(pAllocator, pKey, (FX_LPCBYTE)key, key_len);
    *(void**)(pKey + 1) = value;
}
void CFX_CMapByteStringToPtr::AddValue(FX_BSTR key, void* value)
{
    ASSERT(value != NULL);
    _CompactString* pKey = (_CompactString*)m_Buffer.Add();
    _CompactStringStore(m_Buffer.m_pAllocator, pKey, (FX_LPCBYTE)key, key.GetLength());
    *(void**)(pKey + 1) = value;
}
void CFX_CMapByteStringToPtr::RemoveKey(FX_BSTR key)
{
    int key_len = key.GetLength();
    IFX_Allocator* pAllocator = m_Buffer.m_pAllocator;
    int size = m_Buffer.GetSize();
    for (int index = 0; index < size; index ++) {
        _CompactString* pKey = (_CompactString*)m_Buffer.GetAt(index);
        if (!_CompactStringSame(pKey, (FX_LPCBYTE)key, key_len)) {
            continue;
        }
        _CompactStringRelease(pAllocator, pKey);
        pKey->m_CompactLen = 0xfe;
        return;
    }
}
int CFX_CMapByteStringToPtr::GetCount() const
{
    int count = 0;
    int size = m_Buffer.GetSize();
    for (int i = 0; i < size; i ++) {
        _CompactString* pKey = (_CompactString*)m_Buffer.GetAt(i);
        if (pKey->m_CompactLen != 0xfe) {
            count ++;
        }
    }
    return count;
}
extern "C" {
    static int _CompareDWord(const void* p1, const void* p2)
    {
        return (*(FX_DWORD*)p1) - (*(FX_DWORD*)p2);
    }
};
struct _DWordPair {
    FX_DWORD key;
    FX_DWORD value;
};
FX_BOOL CFX_CMapDWordToDWord::Lookup(FX_DWORD key, FX_DWORD& value) const
{
    FX_LPVOID pResult = FXSYS_bsearch(&key, m_Buffer.GetBuffer(), m_Buffer.GetSize() / sizeof(_DWordPair),
                                      sizeof(_DWordPair), _CompareDWord);
    if (pResult == NULL) {
        return FALSE;
    }
    value = ((FX_DWORD*)pResult)[1];
    return TRUE;
}
FX_POSITION CFX_CMapDWordToDWord::GetStartPosition() const
{
    FX_DWORD count = m_Buffer.GetSize() / sizeof(_DWordPair);
    if (count == 0) {
        return NULL;
    }
    return (FX_POSITION)1;
}
void CFX_CMapDWordToDWord::GetNextAssoc(FX_POSITION& pos, FX_DWORD& key, FX_DWORD& value) const
{
    if (pos == 0) {
        return;
    }
    FX_DWORD index = ((FX_DWORD)(FX_UINTPTR)pos) - 1;
    FX_DWORD count = m_Buffer.GetSize() / sizeof(_DWordPair);
    _DWordPair* buf = (_DWordPair*)m_Buffer.GetBuffer();
    key = buf[index].key;
    value = buf[index].value;
    if (index == count - 1) {
        pos = 0;
    } else {
        pos = (FX_POSITION)((FX_UINTPTR)pos + 1);
    }
}
void CFX_CMapDWordToDWord::SetAt(FX_DWORD key, FX_DWORD value)
{
    FX_DWORD count = m_Buffer.GetSize() / sizeof(_DWordPair);
    _DWordPair* buf = (_DWordPair*)m_Buffer.GetBuffer();
    _DWordPair pair = {key, value};
    if (count == 0 || key > buf[count - 1].key) {
        m_Buffer.AppendBlock(&pair, sizeof(_DWordPair));
        return;
    }
    int low = 0, high = count - 1;
    while (low <= high) {
        int mid = (low + high) / 2;
        if (buf[mid].key < key) {
            low = mid + 1;
        } else if (buf[mid].key > key) {
            high = mid - 1;
        } else {
            buf[mid].value = value;
            return;
        }
    }
    m_Buffer.InsertBlock(low * sizeof(_DWordPair), &pair, sizeof(_DWordPair));
}
void CFX_CMapDWordToDWord::EstimateSize(FX_DWORD size, FX_DWORD grow_by)
{
    m_Buffer.EstimateSize(size, grow_by);
}
