Files
core/PdfReader/Src/UnicodeMap.cpp
Ilya.Kirillov 65d72ae4ec Убраны лишние файлы. Все файлы сконвертированы в UTF8.
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62550 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-21 00:02:55 +03:00

319 lines
7.1 KiB
C++

#include <stdio.h>
#include <string.h>
#include "MemoryUtils.h"
#include "File.h"
#include "StringExt.h"
#include "List.h"
#include "GlobalParams.h"
#include "UnicodeMap.h"
#include "../../DesktopEditor/graphics/TemporaryCS.h"
#include "CharTypes.h"
//-------------------------------------------------------------------------------------------------------------------------------
#define maxExtCode 16
namespace PdfReader
{
struct UnicodeMapExt
{
Unicode nUnicode;
char arrCode[maxExtCode];
unsigned int unBytesCount;
};
//-------------------------------------------------------------------------------------------------------------------------------
UnicodeMap *UnicodeMap::Parse(StringExt *seEncodingName, GlobalParams *pGlobalParams)
{
FILE *pFile = NULL;
if (pGlobalParams && !(pFile = pGlobalParams->GetUnicodeMapFile(seEncodingName)))
{
// TO DO: Error "Couldn't find UnicodeMap file for the encoding"
return NULL;
}
UnicodeMap *pMap = new UnicodeMap(seEncodingName->Copy());
int nSize = 8;
pMap->m_pRanges = (UnicodeMapRange *)MemUtilsMallocArray(nSize, sizeof(UnicodeMapRange));
int nEMapsSize = 0;
int nLineNum = 1;
char sBuffer[256];
while (GetLine(sBuffer, sizeof(sBuffer), pFile))
{
char *sToken1, *sToken2, *sToken3;
if ((sToken1 = strtok(sBuffer, " \t\r\n")) && (sToken2 = strtok(NULL, " \t\r\n")))
{
if (!(sToken3 = strtok(NULL, " \t\r\n")))
{
sToken3 = sToken2;
sToken2 = sToken1;
}
int nBytesCount = strlen(sToken3) / 2;
if (nBytesCount <= 4)
{
if (pMap->m_nLen == nSize)
{
nSize *= 2;
pMap->m_pRanges = (UnicodeMapRange *)MemUtilsReallocArray(pMap->m_pRanges, nSize, sizeof(UnicodeMapRange));
}
UnicodeMapRange *pRange = &pMap->m_pRanges[pMap->m_nLen];
sscanf(sToken1, "%x", &pRange->nStart);
sscanf(sToken2, "%x", &pRange->nEnd);
sscanf(sToken3, "%x", &pRange->unCode);
pRange->nBytesCount = nBytesCount;
++pMap->m_nLen;
}
else if (sToken2 == sToken1)
{
if (pMap->m_nEMapsLen == nEMapsSize)
{
nEMapsSize += 16;
pMap->m_pEMaps = (UnicodeMapExt *)MemUtilsReallocArray(pMap->m_pEMaps, nEMapsSize, sizeof(UnicodeMapExt));
}
UnicodeMapExt *pEMap = &pMap->m_pEMaps[pMap->m_nEMapsLen];
sscanf(sToken1, "%x", &pEMap->nUnicode);
for (int nIndex = 0; nIndex < nBytesCount; ++nIndex)
{
int nValue = 0;
sscanf(sToken3 + nIndex * 2, "%2x", &nValue);
pEMap->arrCode[nIndex] = (char)nValue;
}
pEMap->unBytesCount = nBytesCount;
++pMap->m_nEMapsLen;
}
else
{
// TO DO: Error "Bad line in unicodeMap file for encoding"
}
}
else
{
// TO DO: Error "Bad line in unicodeMap file for encoding"
}
++nLineNum;
}
fclose(pFile);
return pMap;
}
UnicodeMap::UnicodeMap(StringExt *seEncodingName)
{
m_seEncodingName = seEncodingName;
m_bUnicodeOut = false;
m_eType = unicodeMapUser;
m_pRanges = NULL;
m_nLen = 0;
m_pEMaps = NULL;
m_nEMapsLen = 0;
m_nRefCount = 1;
m_oCS.InitializeCriticalSection();
}
UnicodeMap::UnicodeMap(char *sEncodingName, bool bUnicodeOut, UnicodeMapRange *pRanges, int nLen)
{
m_seEncodingName = new StringExt(sEncodingName);
m_bUnicodeOut = bUnicodeOut;
m_eType = unicodeMapResident;
m_pRanges = pRanges;
m_nLen = nLen;
m_pEMaps = NULL;
m_nEMapsLen = 0;
m_nRefCount = 1;
m_oCS.InitializeCriticalSection();
}
UnicodeMap::UnicodeMap(char *sEncodingName, bool bUnicodeOut, UnicodeMapFunc pFunction)
{
m_seEncodingName = new StringExt(sEncodingName);
m_bUnicodeOut = bUnicodeOut;
m_eType = unicodeMapFunc;
m_pFunction = pFunction;
m_pEMaps = NULL;
m_nEMapsLen = 0;
m_nRefCount = 1;
m_oCS.InitializeCriticalSection();
}
UnicodeMap::~UnicodeMap()
{
if (m_seEncodingName)
delete m_seEncodingName;
if (m_eType == unicodeMapUser && m_pRanges)
{
MemUtilsFree(m_pRanges);
}
if (m_pEMaps)
{
MemUtilsFree(m_pEMaps);
}
m_oCS.DeleteCriticalSection();
}
void UnicodeMap::AddRef()
{
CTemporaryCS *pCS = new CTemporaryCS(&m_oCS);
++m_nRefCount;
RELEASEOBJECT(pCS);
}
void UnicodeMap::Release()
{
CTemporaryCS *pCS = new CTemporaryCS(&m_oCS);
bool bDone = (--m_nRefCount == 0);
RELEASEOBJECT(pCS);
if (bDone)
{
delete this;
}
}
bool UnicodeMap::Match(StringExt *seEncodingName)
{
return (!m_seEncodingName->Compare(seEncodingName));
}
int UnicodeMap::MapUnicode(Unicode nUnicode, char *sBuffer, int nBufferSize)
{
if (m_eType == unicodeMapFunc)
{
return (*m_pFunction)(nUnicode, sBuffer, nBufferSize);
}
int nFirst = 0;
int nLast = m_nLen;
if (nUnicode >= m_pRanges[nFirst].nStart)
{
// m_pRanges[nFirst].nStart <= nUnicode < m_pRanges[nLast].nStart
while (nLast - nFirst > 1)
{
int nMiddle = (nFirst + nLast) / 2;
if (nUnicode >= m_pRanges[nMiddle].nStart)
{
nFirst = nMiddle;
}
else if (nUnicode < m_pRanges[nMiddle].nStart)
{
nLast = nMiddle;
}
}
if (nUnicode <= m_pRanges[nFirst].nEnd)
{
int nLen = m_pRanges[nFirst].nBytesCount;
if (nLen > nBufferSize)
{
return 0;
}
unsigned int unCode = m_pRanges[nFirst].unCode + (nUnicode - m_pRanges[nFirst].nStart);
for (int nIndex = nLen - 1; nIndex >= 0; --nIndex)
{
sBuffer[nIndex] = (char)(unCode & 0xff);
unCode >>= 8;
}
return nLen;
}
}
for (int nIndex = 0; nIndex < m_nEMapsLen; ++nIndex)
{
if (m_pEMaps[nIndex].nUnicode == nUnicode)
{
int nLen = m_pEMaps[nIndex].unBytesCount;
for (int nJ = 0; nJ < nLen; ++nJ)
{
sBuffer[nJ] = m_pEMaps[nIndex].arrCode[nJ];
}
return nLen;
}
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------------------------
UnicodeMapCache::UnicodeMapCache()
{
for (int nIndex = 0; nIndex < unicodeMapCacheSize; ++nIndex)
{
m_ppCache[nIndex] = NULL;
}
}
UnicodeMapCache::~UnicodeMapCache()
{
for (int nIndex = 0; nIndex < unicodeMapCacheSize; ++nIndex)
{
if (m_ppCache[nIndex])
{
m_ppCache[nIndex]->Release();
}
}
}
UnicodeMap *UnicodeMapCache::GetUnicodeMap(StringExt *seEncodingName, GlobalParams *pGlobalParams)
{
if (m_ppCache[0] && m_ppCache[0]->Match(seEncodingName))
{
m_ppCache[0]->AddRef();
return m_ppCache[0];
}
UnicodeMap *pMap = NULL;
for (int nIndex = 1; nIndex < unicodeMapCacheSize; ++nIndex)
{
if (m_ppCache[nIndex] && m_ppCache[nIndex]->Match(seEncodingName))
{
pMap = m_ppCache[nIndex];
for (int nJ = nIndex; nJ >= 1; --nJ)
{
m_ppCache[nJ] = m_ppCache[nJ - 1];
}
m_ppCache[0] = pMap;
pMap->AddRef();
return pMap;
}
}
if ((pMap = UnicodeMap::Parse(seEncodingName, pGlobalParams)))
{
if (m_ppCache[unicodeMapCacheSize - 1])
{
m_ppCache[unicodeMapCacheSize - 1]->Release();
}
for (int nJ = unicodeMapCacheSize - 1; nJ >= 1; --nJ)
{
m_ppCache[nJ] = m_ppCache[nJ - 1];
}
m_ppCache[0] = pMap;
pMap->AddRef();
return pMap;
}
return NULL;
}
}