diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /external/vpc/vstdlib/vstrtools.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'external/vpc/vstdlib/vstrtools.cpp')
| -rw-r--r-- | external/vpc/vstdlib/vstrtools.cpp | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/external/vpc/vstdlib/vstrtools.cpp b/external/vpc/vstdlib/vstrtools.cpp new file mode 100644 index 0000000..7c4a5e9 --- /dev/null +++ b/external/vpc/vstdlib/vstrtools.cpp @@ -0,0 +1,316 @@ +#include "tier0/dbg.h" +#include "vstdlib/vstrtools.h" + +#if defined( _WIN32 ) && !defined( _X360 ) +#include <windows.h> +#endif +#if defined(POSIX) && !defined(_PS3) +#include <iconv.h> +#endif + +#ifdef _PS3 +#include <cell/sysmodule.h> +#include <cell/l10n.h> + +class DummyInitL10N +{ +public: + DummyInitL10N() + { + int ret = cellSysmoduleLoadModule( CELL_SYSMODULE_L10N ); + if( ret != CELL_OK ) + { + Warning( "Cannot initialize l10n, unicode services will not work. Error %d\n", ret ); + } + } + + ~DummyInitL10N() + { + cellSysmoduleUnloadModule( CELL_SYSMODULE_L10N ); + } +}s_dummyInitL10N; +#endif + +//----------------------------------------------------------------------------- +// Purpose: Converts a UTF8 string into a unicode string +//----------------------------------------------------------------------------- +int V_UTF8ToUnicode( const char *pUTF8, wchar_t *pwchDest, int cubDestSizeInBytes ) +{ + if ( !pUTF8 ) + return 0; + + AssertValidStringPtr(pUTF8); + AssertValidWritePtr(pwchDest); + + pwchDest[0] = 0; +#ifdef _WIN32 + int cchResult = MultiByteToWideChar( CP_UTF8, 0, pUTF8, -1, pwchDest, cubDestSizeInBytes / sizeof(wchar_t) ); +#elif defined( _PS3 ) + size_t cchResult = cubDestSizeInBytes / sizeof( uint16 ), cchSrc = V_strlen( pUTF8 ) + 1; + L10nResult result = UTF8stoUCS2s( ( const uint8 *) pUTF8, &cchSrc, ( uint16 * ) pwchDest, &cchResult ); + Assert( result == ConversionOK ); + cchResult *= sizeof( uint16 ); +#elif POSIX + iconv_t conv_t = iconv_open( "UTF-32LE", "UTF-8" ); + int cchResult = -1; + size_t nLenUnicde = cubDestSizeInBytes; + size_t nMaxUTF8 = strlen(pUTF8) + 1; + char *pIn = (char *)pUTF8; + char *pOut = (char *)pwchDest; + if ( conv_t > 0 ) + { + cchResult = 0; + cchResult = iconv( conv_t, &pIn, &nMaxUTF8, &pOut, &nLenUnicde ); + iconv_close( conv_t ); + if ( (int)cchResult < 0 ) + cchResult = 0; + else + cchResult = nMaxUTF8; + } +#endif + pwchDest[(cubDestSizeInBytes / sizeof(wchar_t)) - 1] = 0; + return cchResult; +} + +//----------------------------------------------------------------------------- +// Purpose: Converts a unicode string into a UTF8 (standard) string +//----------------------------------------------------------------------------- +int V_UnicodeToUTF8( const wchar_t *pUnicode, char *pUTF8, int cubDestSizeInBytes ) +{ + AssertValidStringPtr(pUTF8, cubDestSizeInBytes); + AssertValidReadPtr(pUnicode); + + if ( cubDestSizeInBytes > 0 ) + { + pUTF8[0] = 0; + } + +#ifdef _WIN32 + int cchResult = WideCharToMultiByte( CP_UTF8, 0, pUnicode, -1, pUTF8, cubDestSizeInBytes, NULL, NULL ); +#elif defined( _PS3 ) + size_t cchResult = cubDestSizeInBytes, cchSrc = V_wcslen( pUnicode ) + 1; + L10nResult result = UCS2stoUTF8s( ( const uint16 *) pUnicode, &cchSrc, ( uint8 * ) pUTF8, &cchResult ); + Assert( result == ConversionOK ); +#elif POSIX + int cchResult = 0; + if ( pUnicode && pUTF8 ) + { + iconv_t conv_t = iconv_open( "UTF-8", "UTF-32LE" ); + int cchResult = -1; + size_t nLenUnicde = ( wcslen(pUnicode) + 1 ) * sizeof(wchar_t); // 4 bytes per wchar vs. 1 byte for utf8 for simple english + size_t nMaxUTF8 = cubDestSizeInBytes; + char *pIn = (char *)pUnicode; + char *pOut = (char *)pUTF8; + if ( conv_t > 0 ) + { + cchResult = 0; + cchResult = iconv( conv_t, &pIn, &nLenUnicde, &pOut, &nMaxUTF8 ); + iconv_close( conv_t ); + if ( (int)cchResult < 0 ) + cchResult = 0; + else + cchResult = nMaxUTF8; + } + } +#endif + + if ( cubDestSizeInBytes > 0 ) + { + pUTF8[cubDestSizeInBytes - 1] = 0; + } + + return cchResult; +} + + +//----------------------------------------------------------------------------- +// Purpose: Converts a ucs2 string to a unicode (wchar_t) one, no-op on win32 +//----------------------------------------------------------------------------- +int V_UCS2ToUnicode( const ucs2 *pUCS2, wchar_t *pUnicode, int cubDestSizeInBytes ) +{ + AssertValidWritePtr(pUnicode); + AssertValidReadPtr(pUCS2); + + pUnicode[0] = 0; +#if defined( _WIN32 ) || defined( _PS3 ) + int lenUCS2 = V_wcslen( pUCS2 ); + int cchResult = MIN( (lenUCS2+1)*( int )sizeof(ucs2), cubDestSizeInBytes ); + V_wcsncpy( (wchar_t*)pUCS2, pUnicode, cchResult ); +#else + iconv_t conv_t = iconv_open( "UCS-4LE", "UCS-2LE" ); + int cchResult = -1; + size_t nLenUnicde = cubDestSizeInBytes; + size_t nMaxUTF8 = cubDestSizeInBytes; + char *pIn = (char *)pUCS2; + char *pOut = (char *)pUnicode; + if ( conv_t > 0 ) + { + cchResult = 0; + cchResult = iconv( conv_t, &pIn, &nLenUnicde, &pOut, &nMaxUTF8 ); + iconv_close( conv_t ); + if ( (int)cchResult < 0 ) + cchResult = 0; + else + cchResult = nMaxUTF8; + } +#endif + pUnicode[(cubDestSizeInBytes / sizeof(wchar_t)) - 1] = 0; + return cchResult; + +} + + +//----------------------------------------------------------------------------- +// Purpose: Converts a wchar_t string into a UCS2 string -noop on windows +//----------------------------------------------------------------------------- +int V_UnicodeToUCS2( const wchar_t *pUnicode, int cubSrcInBytes, char *pUCS2, int cubDestSizeInBytes ) +{ + // TODO: MACMERGE: Figure out how to convert from 2-byte Win32 wchars to platform wchar_t type that can be 4 bytes +#if defined( _WIN32 ) || defined( _PS3 ) + int cchResult = MIN( cubSrcInBytes, cubDestSizeInBytes ); + V_wcsncpy( (wchar_t*)pUCS2, pUnicode, cchResult ); +#elif defined (POSIX) + iconv_t conv_t = iconv_open( "UCS-2LE", "UTF-32LE" ); + size_t cchResult = -1; + size_t nLenUnicde = cubSrcInBytes; + size_t nMaxUCS2 = cubDestSizeInBytes; + char *pIn = (char*)pUnicode; + char *pOut = pUCS2; + if ( conv_t > 0 ) + { + cchResult = 0; + cchResult = iconv( conv_t, &pIn, &nLenUnicde, &pOut, &nMaxUCS2 ); + iconv_close( conv_t ); + if ( (int)cchResult < 0 ) + cchResult = 0; + else + cchResult = cubSrcInBytes / sizeof( wchar_t ); + } +#endif + return cchResult; +} + +// UTF-8 encodes each character (code point) in 1 to 4 octets (8-bit bytes). +// The first 128 characters of the Unicode character set (which correspond directly to the ASCII) use a single octet with the same binary value as in ASCII. +// url:http://en.wikipedia.org/wiki/UTF-8 +#define MAX_UTF8_CHARACTER_BYTES 4 + + +//----------------------------------------------------------------------------- +// Purpose: Converts a ucs-2 (windows wchar_t) string into a UTF8 (standard) string +//----------------------------------------------------------------------------- +VSTRTOOLS_INTERFACE int V_UCS2ToUTF8( const ucs2 *pUCS2, char *pUTF8, int cubDestSizeInBytes ) +{ + AssertValidStringPtr(pUTF8, cubDestSizeInBytes); + AssertValidReadPtr(pUCS2); + Assert( cubDestSizeInBytes >= 1 ); // must have at least 1 byte to write the terminator character + + pUTF8[0] = '\0'; +#ifdef _WIN32 + // under win32 wchar_t == ucs2, sigh + int cchResult = WideCharToMultiByte( CP_UTF8, 0, pUCS2, -1, pUTF8, cubDestSizeInBytes, NULL, NULL ); +#elif defined( _PS3 ) + size_t cchResult = cubDestSizeInBytes, cchSrc = V_wcslen( pUCS2 ) + 1; + L10nResult result = UCS2stoUTF8s( ( const uint16 *) pUCS2, &cchSrc, ( uint8 * ) pUTF8, &cchResult ); + Assert( result == ConversionOK ); +#elif defined(POSIX) + iconv_t conv_t = iconv_open( "UTF-8", "UCS-2LE" ); + size_t cchResult = -1; + size_t nLenUnicde = cubDestSizeInBytes; + size_t nMaxUTF8 = cubDestSizeInBytes; + char *pIn = (char *)pUCS2; + char *pOut = (char *)pUTF8; + if ( conv_t > 0 ) + { + cchResult = 0; + cchResult = iconv( conv_t, &pIn, &nLenUnicde, &pOut, &nMaxUTF8 ); + iconv_close( conv_t ); + if ( (int)cchResult < 0 ) + cchResult = 0; + else + cchResult = nMaxUTF8; + } +#endif + pUTF8[cubDestSizeInBytes - 1] = '\0'; + return cchResult; +} + + +//----------------------------------------------------------------------------- +// Purpose: Converts a UTF8 to ucs-2 (windows wchar_t) +//----------------------------------------------------------------------------- +VSTRTOOLS_INTERFACE int V_UTF8ToUCS2( const char *pUTF8, int cubSrcInBytes, ucs2 *pUCS2, int cubDestSizeInBytes ) +{ + AssertValidStringPtr(pUTF8, cubDestSizeInBytes); + AssertValidReadPtr(pUCS2); + + pUCS2[0] = 0; +#ifdef _WIN32 + // under win32 wchar_t == ucs2, sigh + int cchResult = MultiByteToWideChar( CP_UTF8, 0, pUTF8, -1, pUCS2, cubDestSizeInBytes / sizeof(wchar_t) ); +#elif defined( _PS3 ) + size_t cchResult = cubDestSizeInBytes / sizeof( uint16 ), cchSrc = cubSrcInBytes; + L10nResult result = UTF8stoUCS2s( ( const uint8 *) pUTF8, &cchSrc, ( uint16 * ) pUCS2, &cchResult ); + Assert( result == ConversionOK ); + cchResult *= sizeof( uint16 ); +#elif defined(POSIX) + iconv_t conv_t = iconv_open( "UCS-2LE", "UTF-8" ); + size_t cchResult = -1; + size_t nLenUnicde = cubSrcInBytes; + size_t nMaxUTF8 = cubDestSizeInBytes; + char *pIn = (char *)pUTF8; + char *pOut = (char *)pUCS2; + if ( conv_t > 0 ) + { + cchResult = 0; + cchResult = iconv( conv_t, &pIn, &nLenUnicde, &pOut, &nMaxUTF8 ); + iconv_close( conv_t ); + if ( (int)cchResult < 0 ) + cchResult = 0; + else + cchResult = cubSrcInBytes; + + } +#endif + pUCS2[ (cubDestSizeInBytes/sizeof(ucs2)) - 1] = 0; + return cchResult; +} + +//----------------------------------------------------------------------------- +// Purpose: copies at most nMaxBytes of the UTF-8 input data into the destination, +// ensuring that a trailing multi-byte sequence isn't truncated. +//----------------------------------------------------------------------------- +VSTRTOOLS_INTERFACE void * V_UTF8_strncpy( char *pDest, const char *pSrc, size_t nMaxBytes ) +{ + strncpy( pDest, pSrc, nMaxBytes ); + + // http://en.wikipedia.org/wiki/UTF-8 + int end = nMaxBytes-1; + pDest[end] = 0; + + int nBytesSeen = 0, nBytesExpected = 0; + // walk backwards, ignoring nulls + while ( pDest[end] == 0 ) + --end; + + // found a non-null - see if it's part of a multi-byte sequence + while ( ( pDest[end] & 0x80 ) && !( pDest[end] & 0x40 ) ) + { + nBytesSeen++; + --end; + } + + if ( ( pDest[end] & 0xC0 ) == 0xC0 ) + { + for ( int i = 6; i > 1; --i ) + { + if ( (char)( pDest[end] >> i ) & 0x1 ) + ++nBytesExpected; + } + } + + if ( nBytesExpected != nBytesSeen ) + pDest[end] = 0; + + return pDest; +}
\ No newline at end of file |