mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 03:42:47 +08:00
Co-authored-by: Alexander Trofimov <alexander.trofimov@onlyoffice.com> Co-committed-by: Alexander Trofimov <alexander.trofimov@onlyoffice.com>
409 lines
8.7 KiB
C++
409 lines
8.7 KiB
C++
/*
|
|
* Copyright (C) Ascensio System SIA, 2009-2026
|
|
*
|
|
* This program is a free software product. You can redistribute it and/or
|
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
* version 3 as published by the Free Software Foundation, together with the
|
|
* additional terms provided in the LICENSE file.
|
|
*
|
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
* details, see the GNU AGPL at: https://www.gnu.org/licenses/agpl-3.0.html
|
|
*
|
|
* You can contact Ascensio System SIA by email at info@onlyoffice.com
|
|
* or by postal mail at 20A-6 Ernesta Birznieka-Upisha Street, Riga,
|
|
* LV-1050, Latvia, European Union.
|
|
*
|
|
* The interactive user interfaces in modified versions of the Program
|
|
* are required to display Appropriate Legal Notices in accordance with
|
|
* Section 5 of the GNU AGPL version 3.
|
|
*
|
|
* No trademark rights are granted under this License.
|
|
*
|
|
* All non-code elements of the Product, including illustrations,
|
|
* icon sets, and technical writing content, are licensed under the
|
|
* Creative Commons Attribution-ShareAlike 4.0 International License:
|
|
* https://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
*
|
|
* This license applies only to such non-code elements and does not
|
|
* modify or replace the licensing terms applicable to the Program's
|
|
* source code, which remains licensed under the GNU Affero General
|
|
* Public License v3.
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
#include "HWPStream.h"
|
|
|
|
#include "../../DesktopEditor/common/StringExt.h"
|
|
|
|
namespace HWP
|
|
{
|
|
CHWPStream::CHWPStream()
|
|
: m_pBegin(nullptr), m_pCur(nullptr), m_pEnd(nullptr), m_bExternalBuffer(false)
|
|
{}
|
|
|
|
CHWPStream::CHWPStream(unsigned long ulSize)
|
|
: m_pBegin(nullptr), m_pCur(nullptr), m_pEnd(nullptr), m_bExternalBuffer(false)
|
|
{
|
|
Expand(ulSize);
|
|
}
|
|
|
|
CHWPStream::CHWPStream(HWP_BYTE* pBuffer, unsigned long ulSize, bool bExternalBuffer)
|
|
: m_pBegin(pBuffer), m_pCur(pBuffer), m_pEnd(pBuffer + ulSize), m_bExternalBuffer(bExternalBuffer)
|
|
{}
|
|
|
|
CHWPStream::~CHWPStream()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void CHWPStream::Clear()
|
|
{
|
|
if (nullptr != m_pBegin && !m_bExternalBuffer)
|
|
free(m_pBegin);
|
|
|
|
m_pBegin = nullptr;
|
|
m_pCur = nullptr;
|
|
m_pEnd = nullptr;
|
|
|
|
while (!m_arSavedPositions.empty())
|
|
m_arSavedPositions.pop();
|
|
}
|
|
|
|
void CHWPStream::Copy(CHWPStream& oStream, unsigned long ulSize)
|
|
{
|
|
memcpy(m_pCur, oStream.GetCurPtr(), (std::min)(SizeToEnd(), (unsigned long)(std::min)(ulSize, oStream.SizeToEnd())));
|
|
}
|
|
|
|
void CHWPStream::SetStream(HWP_BYTE* pBuffer, unsigned long ulSize, bool bExternalBuffer)
|
|
{
|
|
m_pBegin = pBuffer;
|
|
m_pCur = pBuffer;
|
|
m_pEnd = pBuffer + ulSize;
|
|
|
|
m_bExternalBuffer = bExternalBuffer;
|
|
}
|
|
|
|
HWP_BYTE* CHWPStream::GetCurPtr()
|
|
{
|
|
return m_pCur;
|
|
}
|
|
|
|
const HWP_BYTE *CHWPStream::GetCurPtr() const
|
|
{
|
|
return m_pCur;
|
|
}
|
|
|
|
unsigned long CHWPStream::Tell() const
|
|
{
|
|
return (!IsValid()) ? 0 : m_pCur - m_pBegin;
|
|
}
|
|
|
|
unsigned long CHWPStream::SizeToEnd() const
|
|
{
|
|
return (!IsValid() || IsEof()) ? 0 : m_pEnd - m_pCur;
|
|
}
|
|
|
|
void CHWPStream::Expand(unsigned long ulSize)
|
|
{
|
|
if (nullptr != m_pBegin)
|
|
{
|
|
unsigned long ulCurrentPos = Tell();
|
|
unsigned long ulNewSize = GetSize() + ulSize;
|
|
|
|
m_pBegin = (HWP_BYTE*)realloc(m_pBegin, ulNewSize);
|
|
m_pEnd = m_pBegin + ulNewSize;
|
|
m_pCur = m_pBegin + ulCurrentPos;
|
|
}
|
|
else
|
|
{
|
|
m_pBegin = (HWP_BYTE*)malloc(ulSize);
|
|
m_pBegin[0] = 0x11;
|
|
m_pEnd = m_pBegin + ulSize;
|
|
m_pCur = m_pBegin;
|
|
}
|
|
}
|
|
|
|
bool CHWPStream::ReadChar(HWP_CHAR& chValue)
|
|
{
|
|
if (m_pCur + 2 > m_pEnd)
|
|
return false;
|
|
|
|
chValue = (HWP_CHAR)(((m_pCur[1] << 8) & 0x0000FF00) | (m_pCur[0] & 0x000000FF));
|
|
m_pCur += 2;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CHWPStream::ReadFloat(float& fValue)
|
|
{
|
|
//TODO:: Verify
|
|
int nValue;
|
|
if (!ReadInt(nValue))
|
|
return false;
|
|
|
|
fValue = *(float*)&nValue;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CHWPStream::ReadDouble(double& dValue)
|
|
{
|
|
//TODO:: Implement
|
|
long long lValue;
|
|
if (!ReadLong(lValue))
|
|
return false;
|
|
|
|
dValue = *(double*)&lValue;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CHWPStream::ReadLong(long long& lValue)
|
|
{
|
|
if (m_pCur + 8 > m_pEnd)
|
|
return false;
|
|
|
|
lValue = ((m_pCur[7] << 24) & 0xFF000000) | ((m_pCur[6 ]<< 16) & 0xFF0000) | ((m_pCur[5] << 8) & 0xFF00) | (m_pCur[4] & 0xFF);
|
|
lValue = (lValue << 32) | ((m_pCur[3] << 24) & 0xFF000000) | ((m_pCur[2] << 16) & 0xFF0000) | ((m_pCur[1] << 8) & 0xFF00) | (m_pCur[0] & 0xFF);
|
|
|
|
m_pCur += 8;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CHWPStream::ReadInt(int& nValue)
|
|
{
|
|
if (m_pCur + 4 > m_pEnd)
|
|
return false;
|
|
|
|
nValue = ((m_pCur[3] << 24) & 0xFF000000) | ((m_pCur[2] << 16) & 0x00FF0000) | ((m_pCur[1] << 8) & 0x0000FF00) | (m_pCur[0] & 0x000000FF);
|
|
m_pCur += 4;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CHWPStream::ReadColor(int& nValue)
|
|
{
|
|
if (m_pCur + 4 > m_pEnd)
|
|
return false;
|
|
|
|
nValue = ((m_pCur[3] << 24) & 0xFF000000) | ((m_pCur[0] << 16) & 0x00FF0000) | ((m_pCur[1] << 8) & 0x0000FF00) | (m_pCur[2] & 0x000000FF);
|
|
m_pCur += 4;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CHWPStream::ReadShort(short& shValue)
|
|
{
|
|
if (m_pCur + 2 > m_pEnd)
|
|
return false;
|
|
|
|
shValue = (short)(((m_pCur[1] << 8) & 0x0000FF00) | (m_pCur[0] & 0x000000FF));
|
|
m_pCur += 2;
|
|
|
|
return true;
|
|
}
|
|
|
|
short CHWPStream::ReadShort()
|
|
{
|
|
if (m_pCur + 1 > m_pEnd)
|
|
return 0;
|
|
|
|
short shValue = (short)(((m_pCur[1] << 8) & 0x0000FF00) | (m_pCur[0] & 0x000000FF));
|
|
m_pCur += 2;
|
|
|
|
return shValue;
|
|
}
|
|
|
|
bool CHWPStream::ReadByte(HWP_BYTE& chValue)
|
|
{
|
|
if (m_pCur + 1 > m_pEnd)
|
|
return false;
|
|
|
|
chValue = m_pCur[0];
|
|
++m_pCur;
|
|
|
|
return true;
|
|
}
|
|
|
|
HWP_BYTE CHWPStream::ReadByte()
|
|
{
|
|
if (m_pCur + 1 > m_pEnd)
|
|
return 0;
|
|
|
|
HWP_BYTE chValue = m_pCur[0]++;
|
|
++m_pCur;
|
|
|
|
return chValue;
|
|
}
|
|
|
|
void Trim(HWP_STRING& sValue)
|
|
{
|
|
HWP_STRING::const_iterator itBegin = std::find_if(sValue.cbegin(), sValue.cend(), [](wchar_t wChar){ return !iswcntrl(wChar); });
|
|
|
|
if (itBegin != sValue.cend())
|
|
sValue.erase(0, itBegin - sValue.cbegin());
|
|
|
|
HWP_STRING::const_reverse_iterator itEnd = std::find_if(sValue.crbegin(), sValue.crend(), [](wchar_t wChar){ return !iswcntrl(wChar); });
|
|
|
|
if (itEnd != sValue.crbegin())
|
|
sValue.erase(itEnd.base());
|
|
}
|
|
|
|
bool CHWPStream::ReadString(HWP_STRING& sValue, EStringCharacter eCharacter)
|
|
{
|
|
short shLen;
|
|
if (!ReadShort(shLen))
|
|
return false;
|
|
|
|
return ReadString(sValue, (int)shLen * 2, eCharacter);
|
|
}
|
|
|
|
bool CHWPStream::ReadString(HWP_STRING& sValue, int nLength, EStringCharacter eCharacter)
|
|
{
|
|
sValue.clear();
|
|
|
|
if (0 == nLength)
|
|
return true;
|
|
|
|
if (!CanRead(nLength))
|
|
nLength = m_pEnd - GetCurPtr();
|
|
|
|
switch (eCharacter)
|
|
{
|
|
case EStringCharacter::ASCII:
|
|
{
|
|
sValue = NSStringExt::CConverter::GetUnicodeFromSingleByteString((unsigned char*)GetCurPtr(), nLength);
|
|
break;
|
|
}
|
|
case EStringCharacter::UTF16:
|
|
{
|
|
sValue = NSStringExt::CConverter::GetUnicodeFromUTF16((unsigned short*)GetCurPtr(), nLength / 2);
|
|
break;
|
|
}
|
|
case EStringCharacter::UTF32:
|
|
{
|
|
sValue = NSStringExt::CConverter::GetUnicodeFromUTF32((unsigned int*)GetCurPtr(), nLength / 4);
|
|
break;
|
|
}
|
|
}
|
|
|
|
Trim(sValue);
|
|
Skip(nLength);
|
|
|
|
return true;
|
|
}
|
|
|
|
unsigned long CHWPStream::ReadBytes(HWP_BYTE* pBytes, unsigned long unSize)
|
|
{
|
|
if (!IsValid() || IsEof())
|
|
return 0;
|
|
|
|
unsigned long ulNewSize = (std::min)(unSize, SizeToEnd());
|
|
|
|
memcpy(pBytes, m_pCur, ulNewSize);
|
|
m_pCur += ulNewSize;
|
|
return ulNewSize;
|
|
}
|
|
|
|
void CHWPStream::Skip(int nStep)
|
|
{
|
|
if (nStep > 0)
|
|
{
|
|
if (m_pCur + nStep > m_pEnd)
|
|
m_pCur = m_pEnd;
|
|
else
|
|
m_pCur += nStep;
|
|
}
|
|
else if (nStep < 0)
|
|
{
|
|
if (m_pCur + nStep > m_pBegin)
|
|
m_pCur += nStep;
|
|
else
|
|
m_pCur = m_pBegin;
|
|
}
|
|
}
|
|
|
|
void CHWPStream::MoveToStart()
|
|
{
|
|
m_pCur = m_pBegin;
|
|
|
|
while (!m_arSavedPositions.empty())
|
|
m_arSavedPositions.pop();
|
|
}
|
|
|
|
void CHWPStream::MoveTo(unsigned int unPosition)
|
|
{
|
|
if (unPosition < m_pEnd - m_pBegin)
|
|
m_pCur = m_pBegin + unPosition;
|
|
else
|
|
m_pCur = m_pEnd;
|
|
}
|
|
|
|
bool CHWPStream::CanRead(int nSize) const
|
|
{
|
|
if (!IsValid())
|
|
return false;
|
|
|
|
return m_pCur + nSize <= m_pEnd;
|
|
}
|
|
|
|
bool CHWPStream::IsValid() const
|
|
{
|
|
return nullptr != m_pBegin;
|
|
}
|
|
|
|
bool CHWPStream::IsEof() const
|
|
{
|
|
return m_pCur > m_pEnd;
|
|
}
|
|
|
|
unsigned int CHWPStream::GetSize() const
|
|
{
|
|
return (unsigned int)(m_pEnd - m_pBegin);
|
|
}
|
|
|
|
void CHWPStream::SavePosition()
|
|
{
|
|
m_arSavedPositions.push(m_pCur);
|
|
}
|
|
|
|
void CHWPStream::RemoveLastSavedPos()
|
|
{
|
|
if (!m_arSavedPositions.empty())
|
|
m_arSavedPositions.pop();
|
|
}
|
|
|
|
int CHWPStream::GetDistanceToLastPos(bool bRemoveLastPos)
|
|
{
|
|
int nDistance = (!m_arSavedPositions.empty()) ? m_pCur - m_arSavedPositions.top() : 0;
|
|
|
|
if (bRemoveLastPos)
|
|
RemoveLastSavedPos();
|
|
|
|
return nDistance;
|
|
}
|
|
|
|
HWP_BYTE CHWPStream::operator[](unsigned int unPosition) const
|
|
{
|
|
if (m_pCur > m_pEnd)
|
|
return *(m_pEnd - 1);
|
|
|
|
return *(m_pCur + unPosition);
|
|
}
|
|
|
|
bool CHWPStream::WriteBytes(const HWP_BYTE* pBuffer, unsigned long ulSize)
|
|
{
|
|
unsigned long ulSizeToEnd = SizeToEnd();
|
|
|
|
if (ulSize > ulSizeToEnd)
|
|
Expand(ulSize - ulSizeToEnd);
|
|
|
|
memcpy(m_pCur, pBuffer, ulSize);
|
|
m_pCur += ulSize;
|
|
return true;
|
|
}
|
|
}
|