Files
core/ASCOfficeRtfFile/RtfFormatLib/source/Utils.h
Alexander.Trofimov 04d197375c change license to 2017
2017-01-17 18:17:26 +03:00

884 lines
26 KiB
C++

/*
* (c) Copyright Ascensio System SIA 2010-2017
*
* 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. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* 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: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
* EU, LV-1021.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#pragma once
#include "RtfDefine.h"
#include "../../../Common/FileWriter.h"
#include "../../../Common/DocxFormat/Source/XML/Utils.h"
#ifdef _ASC_USE_UNICODE_CONVERTER_
#include "../../../UnicodeConverter/UnicodeConverter.h"
#endif
#include "UniversalConverterUtils.h"
#if !defined (_WIN32) && !defined (_WIN64)
#include "iconv.h"
#endif
#include <boost/date_time.hpp>
#define BUF_SIZE 2048
#define ONE_INCH 2.54
#ifndef CP_ACP //ansi code page
#define CP_ACP 0
#endif
#ifndef CP_MACCP //mac code page
#define CP_MACCP 2
#endif
#ifndef CP_SYMBOL //Symbol
#define CP_SYMBOL 42
#endif
#define GETBITS(from, numL, numH) ((from & (((1 << (numH - numL + 1)) - 1) << numL)) >> numL)
#define SETBITS(to , numL, numH, val) {to &= ~(((1 << (numH - numL + 1)) - 1) << numL); to |= ((val & ((1 << (numH - numL + 1)) - 1)) << numL);}
namespace Strings
{
static int ToDigit(wchar_t c)
{
if (c >= '0' && c <= '9')
return (int)(c - '0');
if (c >= 'a' && c <= 'f')
return 10 + (int)(c - 'a');
if (c >= 'A' && c <= 'F')
return 10 + (int)(c - 'A');
return 0;
}
static int ToColor(const std::wstring& strValue)
{
// variables
int blue = 0;
int green = 0;
int red = 0;
std::wstring color = strValue; //color = color.Trim();
if (color.find (L"0x") != -1)
color.erase (0, 2);
if (color.find (L"#") != -1)
color.erase (0, 1);
while (color.length() < 6)
color = L"0" + color;
red = 16 * ToDigit(color[0]) + ToDigit(color[1]);
green = 16 * ToDigit(color[2]) + ToDigit(color[3]);
blue = 16 * ToDigit(color[4]) + ToDigit(color[5]);
return RGB(red, green, blue);
}
static void ToColor(const std::wstring& strValue, int& nR, int& nG, int& nB, int& nA)
{
std::wstring color = strValue;// color = color.Trim();
if (color.find (L"0x")!=-1)
color.erase (0, 2);
if (color.find (L"#")!=-1)
color.erase (0, 1);
while (color.length() < 8)
color = L"0" + color;
nA = 16 * ToDigit(color[0]) + ToDigit(color[1]);
nR = 16 * ToDigit(color[2]) + ToDigit(color[3]);
nG = 16 * ToDigit(color[4]) + ToDigit(color[5]);
nB = 16 * ToDigit(color[6]) + ToDigit(color[7]);
}
static bool ToBoolean(const std::wstring& strValue)
{
std::wstring s = boost::algorithm::to_lower_copy(strValue);
return (s == L"true");
}
static int ToInteger(const std::wstring& strValue)
{
return _ttoi(strValue.c_str());
}
static double ToDouble(const std::wstring& strValue)
{
double d = 0;
_stscanf(strValue.c_str(), L" %lf", &d);
return d;
}
static std::wstring FromInteger(int Value, int Base = 10)
{
std::wstring str = std::to_wstring(Value);
return str;
}
static std::wstring FromDouble(double Value)
{
std::wstring str = std::to_wstring(Value);
return str;
}
static std::wstring FromBoolean(bool Value)
{
if (Value)
return L"true";
return L"false";
}
}
class Convert
{
public:
static std::wstring ToString(int i)
{
std::wstring result = std::to_wstring( i);
return result;
}
static std::wstring ToStringHex( int i, int nLen )
{
std::wstring result = XmlUtils::IntToString(i, L"%X");
for( int i = result.length(); i < nLen; i++ )
result.insert( result.begin() , '0' );
return result;
}
static int ToInt32(std::wstring str, int base = 10)
{
int nResult;
if(16 == base)
_stscanf(str.c_str(), L"%x", &nResult);
else if(8 == base)
_stscanf(str.c_str(), L"%o", &nResult);
else
_stscanf(str.c_str(), L"%d", &nResult);
return nResult;
}
};
static const int aCodePages[][2] =
{//charset codepage
0, 1252, //ANSI
1, 0,//Default
2, 42,//Symbol
77, 10000,//Mac Roman
78, 10001,//Mac Shift Jis
79, 10003,//Mac Hangul
80, 10008,//Mac GB2312
81, 10002,//Mac Big5
83, 10005,//Mac Hebrew
84, 10004,//Mac Arabic
85, 10006,//Mac Greek
86, 10081,//Mac Turkish
87, 10021,//Mac Thai
88, 10029,//Mac East Europe
89, 10007,//Mac Russian
128, 932,//Shift JIS
129, 949,//Hangul
130, 1361,//Johab
134, 936,//GB2312
136, 950,//Big5
238, 1250,//Greek
161, 1253,//Greek
162, 1254,//Turkish
163, 1258,//Vietnamese
177, 1255,//Hebrew
178, 1256, //Arabic
186, 1257,//Baltic
204, 1251,//Russian
222, 874,//Thai
238, 1250,//Eastern European
254, 437,//PC 437
255, 850//OEM
};
static const struct
{
std::wstring LCID_string;
int LCID_int;
} LCID_ms_convert[] =
{
{ L"af-ZA" , 0x0436 },
{ L"sq-AL" , 0x041C },
{ L"ar-DZ" , 0x1401 },
{ L"ar-BH" , 0x3C01 },
{ L"ar-EG" , 0x0C01 },
{ L"ar-IQ" , 0x0801 },
{ L"ar-JO" , 0x2C01 },
{ L"ar-KW" , 0x3401 },
{ L"ar-LB" , 0x3001 },
{ L"ar-LY" , 0x1001 },
{ L"ar-MA" , 0x1801 },
{ L"ar-OM" , 0x2001 },
{ L"ar-QA" , 0x4001 },
{ L"ar-SA" , 0x0401 },
{ L"ar-SY" , 0x2801 },
{ L"ar-TN" , 0x1C01 },
{ L"ar-AE" , 0x3801 },
{ L"ar-YE" , 0x2401 },
{ L"hy-AM" , 0x042B },
{ L"Cy-az-AZ" , 0x082C },
{ L"Lt-az-AZ" , 0x042C },
{ L"eu-ES" , 0x042D },
{ L"be-BY" , 0x0423 },
{ L"bg-BG" , 0x0402 },
{ L"ca-ES" , 0x0403 },
{ L"zh-CN" , 0x0804 },
{ L"zh-HK" , 0x0C04 },
{ L"zh-MO" , 0x1404 },
{ L"zh-SG" , 0x1004 },
{ L"zh-TW" , 0x0404 },
{ L"zh-CHS" , 0x0004 },
{ L"zh-CHT" , 0x7C04 },
{ L"hr-HR" , 0x041A },
{ L"cs-CZ" , 0x0405 },
{ L"da-DK" , 0x0406 },
{ L"div-MV" , 0x0465 },
{ L"nl-BE" , 0x0813 },
{ L"nl-NL" , 0x0413 },
{ L"en-AU" , 0x0C09 },
{ L"en-BZ" , 0x2809 },
{ L"en-CA" , 0x1009 },
{ L"en-CB" , 0x2409 },
{ L"en-IE" , 0x1809 },
{ L"en-JM" , 0x2009 },
{ L"en-NZ" , 0x1409 },
{ L"en-PH" , 0x3409 },
{ L"en-ZA" , 0x1C09 },
{ L"en-TT" , 0x2C09 },
{ L"en-GB" , 0x0809 },
{ L"en-US" , 0x0409 },
{ L"en-ZW" , 0x3009 },
{ L"et-EE" , 0x0425 },
{ L"fo-FO" , 0x0438 },
{ L"fa-IR" , 0x0429 },
{ L"fi-FI" , 0x040B },
{ L"fr-BE" , 0x080C },
{ L"fr-CA" , 0x0C0C },
{ L"fr-FR" , 0x040C },
{ L"fr-LU" , 0x140C },
{ L"fr-MC" , 0x180C },
{ L"fr-CH" , 0x100C },
{ L"gl-ES" , 0x0456 },
{ L"ka-GE" , 0x0437 },
{ L"de-AT" , 0x0C07 },
{ L"de-DE" , 0x0407 },
{ L"de-LI" , 0x1407 },
{ L"de-LU" , 0x1007 },
{ L"de-CH" , 0x0807 },
{ L"el-GR" , 0x0408 },
{ L"gu-IN" , 0x0447 },
{ L"he-IL" , 0x040D },
{ L"hi-IN" , 0x0439 },
{ L"hu-HU" , 0x040E },
{ L"is-IS" , 0x040F },
{ L"id-ID" , 0x0421 },
{ L"it-IT" , 0x0410 },
{ L"it-CH" , 0x0810 },
{ L"ja-JP" , 0x0411 },
{ L"kn-IN" , 0x044B },
{ L"kk-KZ" , 0x043F },
{ L"kok-IN" , 0x0457 },
{ L"ko-KR" , 0x0412 },
{ L"ky-KZ" , 0x0440 },
{ L"lv-LV" , 0x0426 },
{ L"lt-LT" , 0x0427 },
{ L"mk-MK" , 0x042F },
{ L"ms-BN" , 0x083E },
{ L"ms-MY" , 0x043E },
{ L"mr-IN" , 0x044E },
{ L"mn-MN" , 0x0450 },
{ L"nb-NO" , 0x0414 },
{ L"nn-NO" , 0x0814 },
{ L"pl-PL" , 0x0415 },
{ L"pt-BR" , 0x0416 },
{ L"pt-PT" , 0x0816 },
{ L"pa-IN" , 0x0446 },
{ L"ro-RO" , 0x0418 },
{ L"ru-RU" , 0x0419 },
{ L"sa-IN" , 0x044F },
{ L"Cy-sr-SP" , 0x0C1A },
{ L"Lt-sr-SP" , 0x081A },
{ L"sk-SK" , 0x041B },
{ L"sl-SI" , 0x0424 },
{ L"es-AR" , 0x2C0A },
{ L"es-BO" , 0x400A },
{ L"es-CL" , 0x340A },
{ L"es-CO" , 0x240A },
{ L"es-CR" , 0x140A },
{ L"es-DO" , 0x1C0A },
{ L"es-EC" , 0x300A },
{ L"es-SV" , 0x440A },
{ L"es-GT" , 0x100A },
{ L"es-HN" , 0x480A },
{ L"es-MX" , 0x080A },
{ L"es-NI" , 0x4C0A },
{ L"es-PA" , 0x180A },
{ L"es-PY" , 0x3C0A },
{ L"es-PE" , 0x280A },
{ L"es-PR" , 0x500A },
{ L"es-ES" , 0x0C0A },
{ L"es-UY" , 0x380A },
{ L"es-VE" , 0x200A },
{ L"sw-KE" , 0x0441 },
{ L"sv-FI" , 0x081D },
{ L"sv-SE" , 0x041D },
{ L"syr-SY" , 0x045A },
{ L"ta-IN" , 0x0449 },
{ L"tt-RU" , 0x0444 },
{ L"te-IN" , 0x044A },
{ L"th-TH" , 0x041E },
{ L"tr-TR" , 0x041F },
{ L"uk-UA" , 0x0422 },
{ L"ur-PK" , 0x0420 },
{ L"Cy-uz-UZ" , 0x0843 },
{ L"Lt-uz-UZ" , 0x0443 },
{ L"vi-VN" , 0x042A }
};
class RtfUtility
{
public:
//--------------------------------------------------------------------------------------------
static std::wstring convertDateTime (int dt)
{
if ( dt == PROP_DEF) return L"";
short Min = GETBITS(dt, 0 , 5);
short Hour = GETBITS(dt, 6 , 10);
short Day = GETBITS(dt, 11, 15);
short Month = GETBITS(dt, 16, 19);
int Year = GETBITS(dt, 20, 28) + 1900;
//to 1899-12-31T05:37:46.66569 - iso_extended_string
std::wstring date_str = std::to_wstring(Year)
+ L"-"
+ (Month < 10 ? L"0": L"") + std::to_wstring(Month)
+ L"-"
+ (Day < 10 ? L"0": L"") + std::to_wstring(Day)
+ L"T"
+ (Hour < 10 ? L"0": L"") + std::to_wstring(Hour)
+ L":"
+ (Min < 10 ? L"0": L"") + std::to_wstring(Min)
+ L":00Z";
return date_str;
}
static int convertDateTime (std::wstring & dt_)
{
if ( dt_.empty() ) return PROP_DEF;
std::string dt(dt_.begin(), dt_.end());
boost::posix_time::ptime date_time_;
boost::posix_time::time_input_facet *tif = new boost::posix_time::time_input_facet;
tif->set_iso_extended_format();
std::istringstream strm(dt);
strm.imbue(std::locale(std::locale::classic(), tif));
strm >> date_time_;
short Min = date_time_.time_of_day().minutes();
short Hour = date_time_.time_of_day().hours();
short Day = date_time_.date().day();
short Month = date_time_.date().month().as_number();
int Year = date_time_.date().year() - 1900;
int result = 0;
SETBITS(result, 0 , 5, Min);
SETBITS(result, 6 , 10, Hour);
SETBITS(result, 11, 15, Day);
SETBITS(result, 16, 19, Month);
SETBITS(result, 20, 28, Year);
return result;
}
//------------------------------------------------------------------------------------------------------
class RtfInternalEncoder
{
public:
static std::wstring Encode( std::wstring sFilename )
{
return L"{\\*filename " + sFilename + L"\\*end}";
}
static void Decode( std::wstring& sText, NFileWriter::CBufferedFileWriter& oFileWriter ) //сразу записывает в файл
{
#if defined(_WIN32) || defined(_WIN64)
std::string sAnsiText(sText.begin(), sText.end());
int nLenth = sAnsiText.length();
BYTE* BufferString = (BYTE*)sAnsiText.c_str() ;
#else
std::string sAnsiText(sText.begin(),sText.end());
int nLenth = sAnsiText.length();
BYTE* BufferString = (BYTE*)sAnsiText.c_str() ;
#endif
int nStart = 0;
int nFindRes = -1;
std::wstring sFindString = L"{\\*filename ";
int nFindStringLen = sFindString.length();
std::wstring sFindEnd = L"\\*end}";
int nFindEndLen = sFindEnd.length();
while( -1 != (nFindRes = sText.find( sFindString, nStart )) )
{
oFileWriter.Write( BufferString + nStart, nFindRes - nStart );
int nRightBound = 0;
nRightBound = sText.find( sFindEnd, nStart + nFindStringLen );
std::wstring sTargetFilename = sText.substr( nFindRes + nFindStringLen, nRightBound - nFindRes - nFindStringLen );
DecodeFromFile( sTargetFilename, oFileWriter );
nStart = nRightBound + nFindEndLen;
}
oFileWriter.Write( BufferString + nStart, nLenth - nStart );
}
private:
static void DecodeFromFile( std::wstring& sFilename, NFileWriter::CBufferedFileWriter& oFileWriter )
{
CFile file;
if (file.OpenFile(sFilename) != S_OK) return;
DWORD dwBytesRead = 0;
BYTE byteBuffer[ BUF_SIZE ];
char aLookup[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
file.ReadFile(byteBuffer ,BUF_SIZE);
dwBytesRead = (DWORD)file.GetPosition();
while( 0 != dwBytesRead )
{
for( int i = 0; i < (int)dwBytesRead; i++ )
{
BYTE byteData = byteBuffer[ i ];
BYTE byteFirst = aLookup[ byteData / 0x10 ];
BYTE byteSecond = aLookup[ byteData % 0x10 ];
oFileWriter.Write( &byteFirst, 1 );
oFileWriter.Write( &byteSecond, 1 );
}
dwBytesRead = (DWORD)file.GetPosition();
file.ReadFile(byteBuffer ,BUF_SIZE);
dwBytesRead = (DWORD)file.GetPosition() - dwBytesRead;
}
file.CloseFile();
}
};
static float String2Percent( std::wstring sValue )
{
int nPosition;
if( (nPosition = sValue.find( L"f" )) != -1 )
{
sValue = sValue.substr(0, nPosition );
int dResult = Strings::ToInteger( sValue );
return (float)(1.0 * dResult / 65536);
}
else if( (nPosition = sValue.find( L"%" )) != -1 )
{
sValue = sValue.substr(0, nPosition );
return (float)Strings::ToDouble( sValue ) / 100;
}
else
return 0;
}
static int String2Twips( std::wstring sValue )
{
int nPosition;
if( (nPosition = sValue.find( L"pt" )) != -1 )
{
sValue = sValue.substr(0, nPosition );
float dResult = (float)Strings::ToDouble( sValue );
return pt2Twip( dResult );
}
else if( (nPosition = sValue.find( L"in" )) != -1 )
{
sValue = sValue.substr(0, nPosition );
float dResult = (float)Strings::ToDouble( sValue );
return in2Twip(dResult);
}
else if( (nPosition = sValue.find( L"cm" )) != -1 )
{
sValue = sValue.substr(0, nPosition );
float dResult = (float)Strings::ToDouble( sValue );
return cm2Twip(dResult);
}
else if( (nPosition = sValue.find( L"mm" )) != -1 )
{
sValue = sValue.substr(0, nPosition );
float dResult = (float)Strings::ToDouble( sValue );
return mm2Twip(dResult);
}
else if( (nPosition = sValue.find( L"pc" )) != -1 )
{
sValue = sValue.substr(0, nPosition );
float dResult = (float)Strings::ToDouble( sValue );
return pc2Twip(dResult);
}
else if( (nPosition = sValue.find( L"pi" )) != -1 )
{
sValue = sValue.substr(0, nPosition );
float dResult = (float)Strings::ToDouble( sValue );
return pc2Twip(dResult);
}
else
return Strings::ToInteger( sValue );
}
static int px2Twip(int px)
{
return 15 * px; //из наблюдений за word
}
static int pc2Twip(double pc)
{
return (int)( 12 * pc / 20 );
}
static int mm2Twip(double mm)
{
return cm2Twip( mm / 10 );
}
static int cm2Twip(double cm)
{
return in2Twip( cm / ONE_INCH );
}
static int in2Twip(double in)
{
return (int)( 20 * 72 * in );
}
static int pt2Twip(double pt)
{
return (int)(pt * 20);
}
static float Twip2pt(int pt)
{
return (float)(pt / 20.0);
}
static int pt2HalfPt(float pt)
{
return (int)(pt * 2);
}
static int Twips2Emu(int pt)
{
return (int)(pt * 635);
}
static int Emu2Twips(int pt)
{
return (int)(pt / 635);
}
static float Emu2Pt(int emu)
{
return (float)(1.0 * emu / (635 * 20.0));
}
static void WriteDataToFileBinary(std::wstring& sFilename, BYTE* pbData, int nLength)
{
if( NULL == pbData )
return;
CFile file;
if (file.CreateFile(sFilename) != S_OK) return;
file.WriteFile(pbData ,nLength);
file.CloseFile();
}
static void WriteDataToFile(std::wstring& sFilename, std::wstring& sData)
{
CFile file;
if (file.CreateFile(sFilename) != S_OK) return;
wchar_t * buf = (wchar_t *)sData.c_str();
int nLengthText = sData.length();
int nLengthData = nLengthText/2;
BYTE * buf2 = new BYTE[ nLengthData];
BYTE nByte=0;
for( int i=0; i < nLengthData ; i++ )
{
nByte = ToByte( buf[2 * i] ) << 4;
nByte |= ToByte( buf[2 * i + 1] );
buf2[i] = nByte;
}
file.WriteFile(buf2 ,nLengthData);
delete[] buf2;
file.CloseFile();
}
static void WriteDataToBinary( std::wstring sData, BYTE** ppData, long& nSize)
{
wchar_t * buf = (wchar_t *)sData.c_str();
int nLengthText = sData.length();
nSize = nLengthText/2;
BYTE * buf2 = new BYTE[ nSize];
(*ppData) = buf2;
BYTE nByte=0;
for( int i=0; i < nSize ; i++ )
{
nByte = ToByte(buf[ 2*i])<<4;
nByte |= ToByte(buf[ 2*i+1]);
buf2[i] = nByte;
}
}
static std::wstring DecodeHex( std::wstring sText )
{
std::wstring sHexText;
for( int i = 0; i < sText.length(); i++ )
{
BYTE byteChar = sText[i];
sHexText += XmlUtils::IntToString(byteChar, L"%x");
}
return sHexText;
}
static std::wstring EncodeHex( std::wstring sHexText )
{
std::wstring sText;
for( int i = 0; i < sHexText.length() -1 ; i+=2 )
{
int byte1 = ToByte( sHexText[i] );
int byte2 = ToByte(sHexText[i + 1] );
int cChar = (byte1 << 4) + byte2;
sText += XmlUtils::IntToString(cChar, L"%c" );
}
return sText;
}
static BYTE ToByte( wchar_t cChar )
{
return (BYTE)(cChar > 'F' ? cChar - 0x57 : cChar > '9' ? cChar - 0x37 : cChar - 0x30);
}
static bool IsAlpha( int nChar )
{
return ( nChar >= 'a' && nChar <= 'z' || nChar >= 'A' && nChar <= 'Z' );
}
static bool IsDigit( int nChar )
{
return nChar >= '0' && nChar <= '9';
}
static std::wstring Preserve( std::wstring sText )
{
std::wstring sResult = sText;
//обрезавем лишние пробелы
//sResult.Trim();
//удаляем дублирующие пробелы
boost::algorithm::replace_all(sResult, L" ", L" ");
// while( sResult.Replace( L" ", L" " ) > 0 )
// ;
return sResult;
}
static int CharsetToCodepage( int nCharset )
{
#if defined (_WIN32) || defined(_WIN64)
CHARSETINFO Info;
DWORD* dwAcp = (DWORD*)nCharset;
if( TRUE == TranslateCharsetInfo(dwAcp, &Info, TCI_SRCCHARSET) )
return Info.ciACP;
#endif
int nCodePagesLength = sizeof( aCodePages ) / ( sizeof( int ) );
for( int i = 0; i < nCodePagesLength; i++ )
if( aCodePages[i][0] == nCharset )
return aCodePages[i][1];
return 1252;//ANSI
}
#ifdef _ASC_USE_UNICODE_CONVERTER_
static std::wstring convert_string(std::string::const_iterator start, std::string::const_iterator end, int nCodepage = 0)
{
std::string sCodePage;
for (int i = 0; i < UNICODE_CONVERTER_ENCODINGS_COUNT; ++i)
{
if (nCodepage == NSUnicodeConverter::Encodings[i].WindowsCodePage)
{
sCodePage = NSUnicodeConverter::Encodings[i].Name;
break;
}
}
if (sCodePage.empty())
sCodePage = "CP" + std::to_string(nCodepage);
unsigned int insize = (unsigned int)(end - start);
const char* inptr = (const char*)start.operator ->();
NSUnicodeConverter::CUnicodeConverter oConverter;
return oConverter.toUnicode(inptr, insize, sCodePage.c_str());
}
static std::string convert_string(std::wstring::const_iterator start, std::wstring::const_iterator end, int nCodepage = 0)
{
std::string sCodePage;
for (int i = 0; i < UNICODE_CONVERTER_ENCODINGS_COUNT; ++i)
{
if (nCodepage == NSUnicodeConverter::Encodings[i].WindowsCodePage)
{
sCodePage = NSUnicodeConverter::Encodings[i].Name;
break;
}
}
if (sCodePage.empty())
sCodePage = "CP" + std::to_string(nCodepage);
unsigned int insize = (unsigned int)(end - start);
const wchar_t* inptr = (const wchar_t*)start.operator ->();
NSUnicodeConverter::CUnicodeConverter oConverter;
return oConverter.fromUnicode(inptr, insize, sCodePage.c_str());
}
#else
static std::wstring convert_string(std::string::const_iterator start, std::string::const_iterator end, int nCodepage = 0)
{
std::wstring w_out;
bool ansi = true;
size_t insize = end - start;
char *inptr = (char*)start.operator ->();
if (nCodepage > 0)
{
#if defined (_WIN32) || defined (_WIN64)
int insize = MultiByteToWideChar(nCodepage, 0, inptr, -1, NULL, NULL);
wchar_t *out = new wchar_t[insize];
if (out && MultiByteToWideChar(nCodepage, 0, inptr, -1, out, insize) > 0)
{
w_out = std::wstring(out);
ansi = false;
}
if (out) delete []out;
#else
std::string sCodepage = "CP" + std::to_string(nCodepage);
iconv_t ic= iconv_open("WCHAR_T", sCodepage.c_str());
if (ic != (iconv_t) -1)
{
size_t nconv = 0, avail = (insize) * sizeof(wchar_t);
wchar_t *out = new wchar_t[insize];
nconv = iconv (ic, &inptr, &insize, (char**)&out, &avail);
if (nconv == 0)
{
w_out = std::wstring(out);
ansi = false;
}
if (out) delete []out;
iconv_close(ic);
}
#endif
}
if (ansi)
w_out = std::wstring(start, end);
return w_out;
}
static std::string convert_string(std::wstring::const_iterator start, std::wstring::const_iterator end, int nCodepage = 0)
{
std::string out;
bool ansi = true;
size_t insize = end - start;
char *inptr = (char*)start.operator ->();
char* outptr = (char*)out.c_str();
if (nCodepage > 0)
{
#if defined (_WIN32) || defined (_WIN64)
insize = WideCharToMultiByte(nCodepage, 0, (LPCWSTR)inptr, -1, NULL, 0, NULL, NULL);
out.reserve(insize);
if (WideCharToMultiByte(nCodepage, 0, (LPCWSTR)inptr, -1, outptr, insize, NULL, NULL) > 0)
{
out.resize(insize);
ansi = false;
}
#else
out.reserve(insize);
std::string sCodepage = "CP" + std::to_string(nCodepage);
iconv_t ic= iconv_open(sCodepage.c_str(), "WCHAR_T");
if (ic != (iconv_t) -1)
{
size_t nconv = 0, avail = insize * sizeof(wchar_t);
nconv = iconv (ic, &inptr, &insize, &outptr, &avail);
if (nconv == 0)
{
out.resize(insize);
ansi = false;
}
iconv_close(ic);
}
#endif
}
if (ansi)
out = std::string(start, end);
return out;
}
#endif
static int CodepageToCharset( int nCodepage )
{
#if defined (_WIN32) || defined(_WIN64)
CHARSETINFO Info;
DWORD* dwAcp = (DWORD*)nCodepage;
if( TRUE == TranslateCharsetInfo(dwAcp, &Info, TCI_SRCCODEPAGE) )
return Info.ciCharset;
#endif
int nCodePagesLength = sizeof( aCodePages ) / ( sizeof( int ) );
for( int i = 0; i < nCodePagesLength; i++ )
if( aCodePages[i][1] == nCodepage )
return aCodePages[i][0];
return 0;//ANSI
}
static bool IsMacCharset( int nCharset )
{
return nCharset == 77 || nCharset == 78 || nCharset == 79 || nCharset == 80 ||
nCharset == 81 || nCharset == 83 || nCharset == 84 || nCharset == 85 ||
nCharset == 86 || nCharset == 87 || nCharset == 88 || nCharset == 89;
}
static bool IsMacCodepage( int nCodepage )
{
return nCodepage == 10000 || nCodepage == 10001 || nCodepage == 10003 || nCodepage == 10008 ||
nCodepage == 10002 || nCodepage == 10005 || nCodepage == 10004 || nCodepage == 10006 ||
nCodepage == 10081 || nCodepage == 10021 || nCodepage == 10029 || nCodepage == 10007;
}
};