C++程序  |  414行  |  13.27 KB

// 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

#ifndef _FXCRT_EXTENSION_IMP_
#define _FXCRT_EXTENSION_IMP_
class IFXCRT_FileAccess
{
public:
    virtual ~IFXCRT_FileAccess() {}
    virtual FX_BOOL		Open(FX_BSTR fileName, FX_DWORD dwMode) = 0;
    virtual FX_BOOL		Open(FX_WSTR fileName, FX_DWORD dwMode) = 0;
    virtual void		Close() = 0;
    virtual void		Release(IFX_Allocator* pAllocator = NULL) = 0;
    virtual FX_FILESIZE	GetSize() const = 0;
    virtual FX_FILESIZE	GetPosition() const = 0;
    virtual FX_FILESIZE	SetPosition(FX_FILESIZE pos) = 0;
    virtual size_t		Read(void* pBuffer, size_t szBuffer) = 0;
    virtual size_t		Write(const void* pBuffer, size_t szBuffer) = 0;
    virtual size_t		ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0;
    virtual size_t		WritePos(const void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0;
    virtual FX_BOOL		Flush() = 0;
    virtual FX_BOOL		Truncate(FX_FILESIZE szFile) = 0;
};
IFXCRT_FileAccess*	FXCRT_FileAccess_Create(IFX_Allocator* pAllocator = NULL);
class CFX_CRTFileStream : public IFX_FileStream, public CFX_Object
{
public:
    CFX_CRTFileStream(IFXCRT_FileAccess* pFA, IFX_Allocator* pAllocator) : m_pAllocator(pAllocator), m_pFile(pFA), m_dwCount(1), m_bUseRange(FALSE), m_nOffset(0), m_nSize(0) {}
    ~CFX_CRTFileStream()
    {
        if (m_pFile) {
            m_pFile->Release(m_pAllocator);
        }
    }
    virtual IFX_FileStream*		Retain()
    {
        m_dwCount ++;
        return this;
    }
    virtual void				Release()
    {
        FX_DWORD nCount = -- m_dwCount;
        if (!nCount) {
            if (m_pAllocator) {
                FX_DeleteAtAllocator(this, m_pAllocator, CFX_CRTFileStream);
            } else {
                delete this;
            }
        }
    }
    virtual FX_FILESIZE			GetSize()
    {
        return m_bUseRange ? m_nSize : m_pFile->GetSize();
    }
    virtual FX_BOOL				IsEOF()
    {
        return GetPosition() >= GetSize();
    }
    virtual FX_FILESIZE			GetPosition()
    {
        FX_FILESIZE pos = m_pFile->GetPosition();
        if (m_bUseRange) {
            pos -= m_nOffset;
        }
        return pos;
    }
    virtual FX_BOOL				SetRange(FX_FILESIZE offset, FX_FILESIZE size)
    {
        if (offset < 0 || offset + size > m_pFile->GetSize()) {
            return FALSE;
        }
        m_nOffset = offset, m_nSize = size;
        m_bUseRange = TRUE;
        m_pFile->SetPosition(m_nOffset);
        return TRUE;
    }
    virtual void				ClearRange()
    {
        m_bUseRange = FALSE;
    }
    virtual FX_BOOL				ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
    {
        if (m_bUseRange) {
            if (offset + size > (size_t)GetSize()) {
                return FALSE;
            }
            offset += m_nOffset;
        }
        return (FX_BOOL)m_pFile->ReadPos(buffer, size, offset);
    }
    virtual size_t				ReadBlock(void* buffer, size_t size)
    {
        if (m_bUseRange) {
            FX_FILESIZE availSize = m_nOffset + m_nSize - m_pFile->GetPosition();
            if ((size_t)availSize < size) {
                size -= size - (size_t)availSize;
            }
        }
        return m_pFile->Read(buffer, size);
    }
    virtual	FX_BOOL				WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size)
    {
        if (m_bUseRange) {
            offset += m_nOffset;
        }
        return (FX_BOOL)m_pFile->WritePos(buffer, size, offset);
    }
    virtual FX_BOOL				Flush()
    {
        return m_pFile->Flush();
    }
    IFX_Allocator*		m_pAllocator;
    IFXCRT_FileAccess*	m_pFile;
    FX_DWORD			m_dwCount;
    FX_BOOL				m_bUseRange;
    FX_FILESIZE			m_nOffset;
    FX_FILESIZE			m_nSize;
};
#define FX_MEMSTREAM_BlockSize		(64 * 1024)
#define FX_MEMSTREAM_Consecutive	0x01
#define FX_MEMSTREAM_TakeOver		0x02
class CFX_MemoryStream : public IFX_MemoryStream, public CFX_Object
{
public:
    CFX_MemoryStream(FX_BOOL bConsecutive, IFX_Allocator* pAllocator)
        : m_Blocks(pAllocator)
        , m_dwCount(1)
        , m_nTotalSize(0)
        , m_nCurSize(0)
        , m_nCurPos(0)
        , m_nGrowSize(FX_MEMSTREAM_BlockSize)
        , m_bUseRange(FALSE)
    {
        m_dwFlags = FX_MEMSTREAM_TakeOver | (bConsecutive ? FX_MEMSTREAM_Consecutive : 0);
    }
    CFX_MemoryStream(FX_LPBYTE pBuffer, size_t nSize, FX_BOOL bTakeOver, IFX_Allocator* pAllocator)
        : m_Blocks(pAllocator)
        , m_dwCount(1)
        , m_nTotalSize(nSize)
        , m_nCurSize(nSize)
        , m_nCurPos(0)
        , m_nGrowSize(FX_MEMSTREAM_BlockSize)
        , m_bUseRange(FALSE)
    {
        m_Blocks.Add(pBuffer);
        m_dwFlags = FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
    }
    ~CFX_MemoryStream()
    {
        IFX_Allocator* pAllocator = m_Blocks.m_pAllocator;
        if (m_dwFlags & FX_MEMSTREAM_TakeOver) {
            for (FX_INT32 i = 0; i < m_Blocks.GetSize(); i ++) {
                FX_Allocator_Free(pAllocator, (FX_LPBYTE)m_Blocks[i]);
            }
        }
        m_Blocks.RemoveAll();
    }
    virtual IFX_FileStream*		Retain()
    {
        m_dwCount ++;
        return this;
    }
    virtual void				Release()
    {
        FX_DWORD nCount = -- m_dwCount;
        if (nCount) {
            return;
        }
        IFX_Allocator* pAllocator = m_Blocks.m_pAllocator;
        if (pAllocator) {
            FX_DeleteAtAllocator(this, pAllocator, CFX_MemoryStream);
        } else {
            delete this;
        }
    }
    virtual FX_FILESIZE			GetSize()
    {
        return m_bUseRange ? (FX_FILESIZE) m_nSize : (FX_FILESIZE)m_nCurSize;
    }
    virtual FX_BOOL				IsEOF()
    {
        return m_nCurPos >= (size_t)GetSize();
    }
    virtual FX_FILESIZE			GetPosition()
    {
        FX_FILESIZE pos = (FX_FILESIZE)m_nCurPos;
        if (m_bUseRange) {
            pos -= (FX_FILESIZE)m_nOffset;
        }
        return pos;
    }
    virtual FX_BOOL				SetRange(FX_FILESIZE offset, FX_FILESIZE size)
    {
        if (offset < 0 || (size_t)(offset + size) > m_nCurSize) {
            return FALSE;
        }
        m_nOffset = (size_t)offset, m_nSize = (size_t)size;
        m_bUseRange = TRUE;
        m_nCurPos = m_nOffset;
        return TRUE;
    }
    virtual void				ClearRange()
    {
        m_bUseRange = FALSE;
    }
    virtual FX_BOOL				ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
    {
        if (!buffer || !size) {
            return FALSE;
        }
        if (m_bUseRange) {
            offset += (FX_FILESIZE)m_nOffset;
        }
        if ((size_t)offset + size > m_nCurSize) {
            return FALSE;
        }
        m_nCurPos = (size_t)offset + size;
        if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
            FXSYS_memcpy32(buffer, (FX_LPBYTE)m_Blocks[0] + (size_t)offset, size);
            return TRUE;
        }
        size_t nStartBlock = (size_t)offset / m_nGrowSize;
        offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
        while (size) {
            size_t nRead = m_nGrowSize - (size_t)offset;
            if (nRead > size) {
                nRead = size;
            }
            FXSYS_memcpy32(buffer, (FX_LPBYTE)m_Blocks[(int)nStartBlock] + (size_t)offset, nRead);
            buffer = ((FX_LPBYTE)buffer) + nRead;
            size -= nRead;
            nStartBlock ++;
            offset = 0;
        }
        return TRUE;
    }
    virtual size_t				ReadBlock(void* buffer, size_t size)
    {
        if (m_nCurPos >= m_nCurSize) {
            return 0;
        }
        if (m_bUseRange) {
            size_t availSize = m_nOffset + m_nSize - m_nCurPos;
            if (availSize < size) {
                size -= size - (size_t)availSize;
            }
        }
        size_t nRead = FX_MIN(size, m_nCurSize - m_nCurPos);
        if (!ReadBlock(buffer, (FX_INT32)m_nCurPos, nRead)) {
            return 0;
        }
        return nRead;
    }
    virtual	FX_BOOL				WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size)
    {
        if (!buffer || !size) {
            return FALSE;
        }
        if (m_bUseRange) {
            offset += (FX_FILESIZE)m_nOffset;
        }
        if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
            m_nCurPos = (size_t)offset + size;
            if (m_nCurPos > m_nTotalSize) {
                IFX_Allocator* pAllocator = m_Blocks.m_pAllocator;
                m_nTotalSize = (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize;
                if (m_Blocks.GetSize() < 1) {
                    void* block = FX_Allocator_Alloc(pAllocator, FX_BYTE, m_nTotalSize);
                    m_Blocks.Add(block);
                } else {
                    m_Blocks[0] = FX_Allocator_Realloc(pAllocator, FX_BYTE, m_Blocks[0], m_nTotalSize);
                }
                if (!m_Blocks[0]) {
                    m_Blocks.RemoveAll();
                    return FALSE;
                }
            }
            FXSYS_memcpy32((FX_LPBYTE)m_Blocks[0] + (size_t)offset, buffer, size);
            if (m_nCurSize < m_nCurPos) {
                m_nCurSize = m_nCurPos;
            }
            return TRUE;
        }
        if (!ExpandBlocks((size_t)offset + size)) {
            return FALSE;
        }
        m_nCurPos = (size_t)offset + size;
        size_t nStartBlock = (size_t)offset / m_nGrowSize;
        offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
        while (size) {
            size_t nWrite = m_nGrowSize - (size_t)offset;
            if (nWrite > size) {
                nWrite = size;
            }
            FXSYS_memcpy32((FX_LPBYTE)m_Blocks[(int)nStartBlock] + (size_t)offset, buffer, nWrite);
            buffer = ((FX_LPBYTE)buffer) + nWrite;
            size -= nWrite;
            nStartBlock ++;
            offset = 0;
        }
        return TRUE;
    }
    virtual FX_BOOL				Flush()
    {
        return TRUE;
    }
    virtual FX_BOOL				IsConsecutive() const
    {
        return m_dwFlags & FX_MEMSTREAM_Consecutive;
    }
    virtual void				EstimateSize(size_t nInitSize, size_t nGrowSize)
    {
        if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
            if (m_Blocks.GetSize() < 1) {
                FX_LPBYTE pBlock = FX_Allocator_Alloc(m_Blocks.m_pAllocator, FX_BYTE, FX_MAX(nInitSize, 4096));
                if (pBlock) {
                    m_Blocks.Add(pBlock);
                }
            }
            m_nGrowSize = FX_MAX(nGrowSize, 4096);
        } else if (m_Blocks.GetSize() < 1) {
            m_nGrowSize = FX_MAX(nGrowSize, 4096);
        }
    }
    virtual FX_LPBYTE			GetBuffer() const
    {
        return m_Blocks.GetSize() ? (FX_LPBYTE)m_Blocks[0] : NULL;
    }
    virtual void				AttachBuffer(FX_LPBYTE pBuffer, size_t nSize, FX_BOOL bTakeOver = FALSE)
    {
        if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
            return;
        }
        m_Blocks.RemoveAll();
        m_Blocks.Add(pBuffer);
        m_nTotalSize = m_nCurSize = nSize;
        m_nCurPos = 0;
        m_dwFlags = FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
        ClearRange();
    }
    virtual void				DetachBuffer()
    {
        if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
            return;
        }
        m_Blocks.RemoveAll();
        m_nTotalSize = m_nCurSize = m_nCurPos = 0;
        m_dwFlags = FX_MEMSTREAM_TakeOver;
        ClearRange();
    }
protected:
    CFX_PtrArray	m_Blocks;
    FX_DWORD		m_dwCount;
    size_t			m_nTotalSize;
    size_t			m_nCurSize;
    size_t			m_nCurPos;
    size_t			m_nGrowSize;
    FX_DWORD		m_dwFlags;
    FX_BOOL			m_bUseRange;
    size_t			m_nOffset;
    size_t			m_nSize;
    FX_BOOL	ExpandBlocks(size_t size)
    {
        if (m_nCurSize < size) {
            m_nCurSize = size;
        }
        if (size <= m_nTotalSize) {
            return TRUE;
        }
        FX_INT32 iCount = m_Blocks.GetSize();
        size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize;
        m_Blocks.SetSize(m_Blocks.GetSize() + (FX_INT32)size, -1);
        IFX_Allocator* pAllocator = m_Blocks.m_pAllocator;
        while (size --) {
            FX_LPBYTE pBlock = FX_Allocator_Alloc(pAllocator, FX_BYTE, m_nGrowSize);
            if (!pBlock) {
                return FALSE;
            }
            m_Blocks.SetAt(iCount ++, pBlock);
            m_nTotalSize += m_nGrowSize;
        }
        return TRUE;
    }
};
#ifdef __cplusplus
extern "C" {
#endif
#define MT_N			848
#define MT_M			456
#define MT_Matrix_A		0x9908b0df
#define MT_Upper_Mask	0x80000000
#define MT_Lower_Mask	0x7fffffff
typedef struct _FX_MTRANDOMCONTEXT {
    _FX_MTRANDOMCONTEXT()
    {
        mti = MT_N + 1;
        bHaveSeed = FALSE;
    }
    FX_DWORD mti;
    FX_BOOL	 bHaveSeed;
    FX_DWORD mt[MT_N];
} FX_MTRANDOMCONTEXT, * FX_LPMTRANDOMCONTEXT;
typedef FX_MTRANDOMCONTEXT const * FX_LPCMTRANDOMCONTEXT;
#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
FX_BOOL FX_GenerateCryptoRandom(FX_LPDWORD pBuffer, FX_INT32 iCount);
#endif
#ifdef __cplusplus
}
#endif
#endif