Packages
fit_decoder
0.1.0
A high-performance Elixir library for decoding Garmin .fit files using a C++ NIF.
Current section
Files
Jump to
Current section
Files
c_src/fit_sdk/cpp/fit_unicode.cpp
/////////////////////////////////////////////////////////////////////////////////////////////
// Copyright 2025 Garmin International, Inc.
// Licensed under the Flexible and Interoperable Data Transfer (FIT) Protocol License; you
// may not use this file except in compliance with the Flexible and Interoperable Data
// Transfer (FIT) Protocol License.
/////////////////////////////////////////////////////////////////////////////////////////////
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
// Profile Version = 21.171.0Release
// Tag = production/release/21.171.0-0-g57fed75
/////////////////////////////////////////////////////////////////////////////////////////////
#include "fit_config.hpp"
#include "fit_runtime_exception.hpp"
#include "fit_unicode.hpp"
///////////////////////////////////////////////////////////////////////
// Private Definitions
///////////////////////////////////////////////////////////////////////
// Encoding types.
typedef FIT_ENUM FIT_UNICODE_ENCODING;
#define FIT_UNICODE_ENCODING_UTF8 ((FIT_UNICODE_ENCODING)0)
#define FIT_UNICODE_ENCODING_UTF16 ((FIT_UNICODE_ENCODING)1)
#define FIT_UNICODE_ENCODING_UTF32 ((FIT_UNICODE_ENCODING)2)
#define FIT_UNICODE_ENCODING_INVALID FIT_ENUM_INVALID
#define FIT_UNICODE_ENCODING_COUNT 3
#if (FIT_WIDE_CHAR_SIZE == 1)
#define INTERNAL_UNICODE_ENCODING FIT_UNICODE_ENCODING_UTF8
#elif (FIT_WIDE_CHAR_SIZE == 2)
#define INTERNAL_UNICODE_ENCODING FIT_UNICODE_ENCODING_UTF16
#elif (FIT_WIDE_CHAR_SIZE == 4)
#define INTERNAL_UNICODE_ENCODING FIT_UNICODE_ENCODING_UTF32
#else
#error "Wide character size not specified as 1, 2 or 4 bytes."
#endif
// Conversion error codes.
typedef FIT_ENUM FIT_STRING_CONVERSION_ERROR;
#define FIT_STRING_CONVERSION_ERROR_UNICODE_INVALID_POINT ((FIT_STRING_CONVERSION_ERROR)0)
#define FIT_STRING_CONVERSION_ERROR_UNICODE_UNDEFINED_SOURCE_ENCODING ((FIT_STRING_CONVERSION_ERROR)1)
#define FIT_STRING_CONVERSION_ERROR_UNICODE_UNDEFINED_DESTINATION_ENCODING ((FIT_STRING_CONVERSION_ERROR)2)
#define FIT_STRING_CONVERSION_ERROR_UTF8_INVALID_UNIT ((FIT_STRING_CONVERSION_ERROR)3)
#define FIT_STRING_CONVERSION_ERROR_UTF8_INVALID_LEAD_UNIT ((FIT_STRING_CONVERSION_ERROR)4)
#define FIT_STRING_CONVERSION_ERROR_UTF8_INVALID_CONTINUATION_UNIT ((FIT_STRING_CONVERSION_ERROR)5)
#define FIT_STRING_CONVERSION_ERROR_UTF8_NON_CONTINUATION_UNIT ((FIT_STRING_CONVERSION_ERROR)6)
#define FIT_STRING_CONVERSION_ERROR_UTF8_OVERENCODED_POINT_1 ((FIT_STRING_CONVERSION_ERROR)7)
#define FIT_STRING_CONVERSION_ERROR_UTF8_OVERENCODED_POINT_2 ((FIT_STRING_CONVERSION_ERROR)8)
#define FIT_STRING_CONVERSION_ERROR_UTF8_OVERENCODED_POINT_3 ((FIT_STRING_CONVERSION_ERROR)9)
#define FIT_STRING_CONVERSION_ERROR_UTF8_OVERENCODED_POINT_4 ((FIT_STRING_CONVERSION_ERROR)10)
#define FIT_STRING_CONVERSION_ERROR_UTF8_INVALID_NUM_UNITS ((FIT_STRING_CONVERSION_ERROR)11)
#define FIT_STRING_CONVERSION_ERROR_UTF8_END_OF_STRING ((FIT_STRING_CONVERSION_ERROR)12)
#define FIT_STRING_CONVERSION_ERROR_UTF16_INVALID_UNIT ((FIT_STRING_CONVERSION_ERROR)13)
#define FIT_STRING_CONVERSION_ERROR_UTF16_INVALID_LEAD_UNIT ((FIT_STRING_CONVERSION_ERROR)14)
#define FIT_STRING_CONVERSION_ERROR_UTF16_INVALID_TAIL_UNIT ((FIT_STRING_CONVERSION_ERROR)15)
#define FIT_STRING_CONVERSION_ERROR_UTF16_NON_TAIL_UNIT ((FIT_STRING_CONVERSION_ERROR)16)
#define FIT_STRING_CONVERSION_ERROR_UTF16_OVERENCODED_POINT_1 ((FIT_STRING_CONVERSION_ERROR)17)
#define FIT_STRING_CONVERSION_ERROR_UTF16_OVERENCODED_POINT_2 ((FIT_STRING_CONVERSION_ERROR)18)
#define FIT_STRING_CONVERSION_ERROR_UTF16_INVALID_NUM_UNITS ((FIT_STRING_CONVERSION_ERROR)19)
#define FIT_STRING_CONVERSION_ERROR_UTF16_END_OF_STRING ((FIT_STRING_CONVERSION_ERROR)20)
#define FIT_STRING_CONVERSION_ERROR_UTF32_INVALID_UNIT ((FIT_STRING_CONVERSION_ERROR)21)
#define FIT_STRING_CONVERSION_ERROR_INVALID FIT_ENUM_INVALID
#define FIT_STRING_CONVERSION_ERROR_COUNT 22
// General Unicode.
typedef unsigned long int FIT_LARGE_TYPE;
#define UNICODE_IS_POINT_VALID(POINT) ((((((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) <= (FIT_LARGE_TYPE)0x00D7FF) || (((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) >= (FIT_LARGE_TYPE)0x00E000)) && (((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) <= (FIT_LARGE_TYPE)0x10FFFF)) ? (FIT_TRUE) : (FIT_FALSE))
// UTF-8 encoding.
#define UTF8_IS_UNIT_VALID(UNIT) (((((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xFF) != (FIT_LARGE_TYPE)0xC0) && (((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xFF) != (FIT_LARGE_TYPE)0xC1) && (((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xFF) <= (FIT_LARGE_TYPE)0xF4)) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF8_IS_UNIT_1UNIT(UNIT) ((((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0x80) == (FIT_LARGE_TYPE)0x00) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF8_IS_UNIT_2UNIT_LEAD(UNIT) ((((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xE0) == (FIT_LARGE_TYPE)0xC0) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF8_IS_UNIT_3UNIT_LEAD(UNIT) ((((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xF0) == (FIT_LARGE_TYPE)0xE0) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF8_IS_UNIT_4UNIT_LEAD(UNIT) ((((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xF8) == (FIT_LARGE_TYPE)0xF0) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF8_IS_UNIT_MULTI_CONT(UNIT) ((((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xC0) == (FIT_LARGE_TYPE)0x80) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF8_IS_POINT_1UNIT(POINT) (((((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) <= (FIT_LARGE_TYPE)0x00007F)) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF8_IS_POINT_2UNIT(POINT) (((((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) >= (FIT_LARGE_TYPE)0x000080) && (((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) <= (FIT_LARGE_TYPE)0x0007FF)) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF8_IS_POINT_3UNIT(POINT) (((((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) >= (FIT_LARGE_TYPE)0x000800) && (((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) <= (FIT_LARGE_TYPE)0x00FFFF)) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF8_IS_POINT_4UNIT(POINT) (((((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) >= (FIT_LARGE_TYPE)0x010000) && (((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) <= (FIT_LARGE_TYPE)0x10FFFF)) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF8_1UNIT_TO_POINT(UNIT) ((((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0x7F) << 0))
#define UTF8_2UNIT_TO_POINT(LEAD,C1) ((((FIT_LARGE_TYPE)(LEAD) & (FIT_LARGE_TYPE)0x1F) << 6) | (((FIT_LARGE_TYPE)(C1) & (FIT_LARGE_TYPE)0x3F) << 0))
#define UTF8_3UNIT_TO_POINT(LEAD,C1,C2) ((((FIT_LARGE_TYPE)(LEAD) & (FIT_LARGE_TYPE)0x0F) << 12) | (((FIT_LARGE_TYPE)(C1) & (FIT_LARGE_TYPE)0x3F) << 6) | (((FIT_LARGE_TYPE)(C2) & (FIT_LARGE_TYPE)0x3F) << 0))
#define UTF8_4UNIT_TO_POINT(LEAD,C1,C2,C3) ((((FIT_LARGE_TYPE)(LEAD) & (FIT_LARGE_TYPE)0x07) << 18) | (((FIT_LARGE_TYPE)(C1) & (FIT_LARGE_TYPE)0x3F) << 12) | (((FIT_LARGE_TYPE)(C2) & (FIT_LARGE_TYPE)0x3F) << 6) | (((FIT_LARGE_TYPE)(C3) & (FIT_LARGE_TYPE)0x3F) << 0))
#define UTF8_POINT_TO_1UNIT(POINT) ((((FIT_LARGE_TYPE)(POINT) >> 0) & (FIT_LARGE_TYPE)0x7F) | (FIT_LARGE_TYPE)0x00)
#define UTF8_POINT_TO_2UNIT_LEAD(POINT) ((((FIT_LARGE_TYPE)(POINT) >> 6) & (FIT_LARGE_TYPE)0x1F) | (FIT_LARGE_TYPE)0xC0)
#define UTF8_POINT_TO_2UNIT_CONT1(POINT) ((((FIT_LARGE_TYPE)(POINT) >> 0) & (FIT_LARGE_TYPE)0x3F) | (FIT_LARGE_TYPE)0x80)
#define UTF8_POINT_TO_3UNIT_LEAD(POINT) ((((FIT_LARGE_TYPE)(POINT) >> 12) & (FIT_LARGE_TYPE)0x0F) | (FIT_LARGE_TYPE)0xE0)
#define UTF8_POINT_TO_3UNIT_CONT1(POINT) ((((FIT_LARGE_TYPE)(POINT) >> 6) & (FIT_LARGE_TYPE)0x3F) | (FIT_LARGE_TYPE)0x80)
#define UTF8_POINT_TO_3UNIT_CONT2(POINT) ((((FIT_LARGE_TYPE)(POINT) >> 0) & (FIT_LARGE_TYPE)0x3F) | (FIT_LARGE_TYPE)0x80)
#define UTF8_POINT_TO_4UNIT_LEAD(POINT) ((((FIT_LARGE_TYPE)(POINT) >> 18) & (FIT_LARGE_TYPE)0x07) | (FIT_LARGE_TYPE)0xF0)
#define UTF8_POINT_TO_4UNIT_CONT1(POINT) ((((FIT_LARGE_TYPE)(POINT) >> 12) & (FIT_LARGE_TYPE)0x3F) | (FIT_LARGE_TYPE)0x80)
#define UTF8_POINT_TO_4UNIT_CONT2(POINT) ((((FIT_LARGE_TYPE)(POINT) >> 6) & (FIT_LARGE_TYPE)0x3F) | (FIT_LARGE_TYPE)0x80)
#define UTF8_POINT_TO_4UNIT_CONT3(POINT) ((((FIT_LARGE_TYPE)(POINT) >> 0) & (FIT_LARGE_TYPE)0x3F) | (FIT_LARGE_TYPE)0x80)
// UTF-16 encoding.
// Using unicode version 8.0 D91, http://www.unicode.org/versions/Unicode8.0.0/ch03.pdf
// Isolated code units in the range D800..DFFF are ill formed.
// Any UTF 32 code unit > 10FFFF is ill formed.
// This check is already performed by UNICODE_IS_POINT_VALID macro
#define UTF16_IS_UNIT_VALID(UNIT) (UNICODE_IS_POINT_VALID(UNIT))
#define UTF16_IS_UNIT_1UNIT(UNIT) (((((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xFFFF)<= (FIT_LARGE_TYPE)0xD7FF) || (((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xFFFF)>= (FIT_LARGE_TYPE)0xE000)) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF16_IS_UNIT_2UNIT_LEAD(UNIT) (((((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xFFFF)>= (FIT_LARGE_TYPE)0xD800) && (((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xFFFF)<= (FIT_LARGE_TYPE)0xDBFF)) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF16_IS_UNIT_2UNIT_TAIL(UNIT) (((((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xFFFF)>= (FIT_LARGE_TYPE)0xDC00) && (((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xFFFF)<= (FIT_LARGE_TYPE)0xDFFF)) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF16_IS_POINT_1UNIT(POINT) (((((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) <= (FIT_LARGE_TYPE)0x00FFFF)) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF16_IS_POINT_2UNIT(POINT) (((((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) >= (FIT_LARGE_TYPE)0x010000) && (((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) <= (FIT_LARGE_TYPE)0x10FFFF)) ? (FIT_TRUE) : (FIT_FALSE))
#define UTF16_1UNIT_TO_POINT(UNIT) ((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0xFFFF)
#define UTF16_2UNIT_TO_POINT(LEAD,TAIL) (((((FIT_LARGE_TYPE)(LEAD) & (FIT_LARGE_TYPE)0xFFFF) - (FIT_LARGE_TYPE)0xD800) << 10) + ((((FIT_LARGE_TYPE)(TAIL) & (FIT_LARGE_TYPE)0xFFFF) - (FIT_LARGE_TYPE)0xDC00) << 0) + (FIT_LARGE_TYPE)0x10000)
#define UTF16_POINT_TO_1UNIT(POINT) ((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0xFFFF)
#define UTF16_POINT_TO_2UNIT_LEAD(POINT) ((((((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) - (FIT_LARGE_TYPE)0x10000) >> 10) & (FIT_LARGE_TYPE)0x3FF) + (FIT_LARGE_TYPE)0xD800)
#define UTF16_POINT_TO_2UNIT_TAIL(POINT) ((((((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x1FFFFF) - (FIT_LARGE_TYPE)0x10000) >> 0) & (FIT_LARGE_TYPE)0x3FF) + (FIT_LARGE_TYPE)0xDC00)
// UTF 32 encoding
// Using unicode version 8.0 D90, http://www.unicode.org/versions/Unicode8.0.0/ch03.pdf
// UTF 32 code units in the range 0000D800..0000DFFF are ill formed.
// Any UTF 32 code unit > 0010FFFF is ill formed.
// This check is already performed by UNICODE_IS_POINT_VALID macro
#define UTF32_IS_UNIT_VALID(UNIT) (UNICODE_IS_POINT_VALID(UNIT))
#define UTF32_UNIT_TO_POINT(UNIT) ((FIT_LARGE_TYPE)(UNIT) & (FIT_LARGE_TYPE)0x0010FFFF)
#define UTF32_POINT_TO_UNIT(POINT) ((FIT_LARGE_TYPE)(POINT) & (FIT_LARGE_TYPE)0x0010FFFF)
namespace fit
{
///////////////////////////////////////////////////////////////////////
// Private Classes
///////////////////////////////////////////////////////////////////////
class StringConversionException : public RuntimeException
{
public:
StringConversionException(const FIT_STRING_CONVERSION_ERROR newErrorCode = FIT_STRING_CONVERSION_ERROR_INVALID)
: RuntimeException(std::string("")),
errorCode(newErrorCode)
{
}
private:
FIT_STRING_CONVERSION_ERROR errorCode;
};
///////////////////////////////////////////////////////////////////////
// Private Functions
///////////////////////////////////////////////////////////////////////
template <typename STRING_TYPE_DST, typename CHAR_TYPE_DST, typename STRING_TYPE_SRC, typename CHAR_TYPE_SRC>
FIT_BOOL ConvertStringEncoding(STRING_TYPE_DST& strDst, const FIT_UNICODE_ENCODING dstEncoding, const STRING_TYPE_SRC& strSrc, const FIT_UNICODE_ENCODING srcEncoding)
{
STRING_TYPE_DST convertedStr;
for (unsigned long int i = 0; i < strSrc.size(); ++i)
{
try
{
FIT_LARGE_TYPE codePoint = 0;
// Decode the source.
switch (srcEncoding)
{
case FIT_UNICODE_ENCODING_UTF8:
{
if (!UTF8_IS_UNIT_VALID(strSrc[i]))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF8_INVALID_UNIT);
unsigned long int numUnits = 0;
if (UTF8_IS_UNIT_1UNIT(strSrc[i]))
numUnits = 1;
else if (UTF8_IS_UNIT_2UNIT_LEAD(strSrc[i]))
numUnits = 2;
else if (UTF8_IS_UNIT_3UNIT_LEAD(strSrc[i]))
numUnits = 3;
else if (UTF8_IS_UNIT_4UNIT_LEAD(strSrc[i]))
numUnits = 4;
else
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF8_INVALID_LEAD_UNIT);
unsigned long int numContUnits = numUnits - 1;
while (numContUnits--)
{
if ((++i) >= strSrc.size())
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF8_END_OF_STRING);
if (!UTF8_IS_UNIT_MULTI_CONT(strSrc[i]))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF8_NON_CONTINUATION_UNIT);
if (!UTF8_IS_UNIT_VALID(strSrc[i]))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF8_INVALID_CONTINUATION_UNIT);
}
switch (numUnits)
{
case 1:
codePoint = UTF8_1UNIT_TO_POINT(strSrc[i]);
if (!UTF8_IS_POINT_1UNIT(codePoint))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF8_OVERENCODED_POINT_1);
break;
case 2:
codePoint = UTF8_2UNIT_TO_POINT(strSrc[i-1], strSrc[i]);
if (!UTF8_IS_POINT_2UNIT(codePoint))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF8_OVERENCODED_POINT_2);
break;
case 3:
codePoint = UTF8_3UNIT_TO_POINT(strSrc[i-2], strSrc[i-1], strSrc[i]);
if (!UTF8_IS_POINT_3UNIT(codePoint))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF8_OVERENCODED_POINT_3);
break;
case 4:
codePoint = UTF8_4UNIT_TO_POINT(strSrc[i-3], strSrc[i-2], strSrc[i-1], strSrc[i]);
if (!UTF8_IS_POINT_4UNIT(codePoint))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF8_OVERENCODED_POINT_4);
break;
}
}
break;
case FIT_UNICODE_ENCODING_UTF16:
{
if (!UTF16_IS_UNIT_VALID(strSrc[i]))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF16_INVALID_UNIT);
if (UTF16_IS_UNIT_1UNIT(strSrc[i]))
{
codePoint = static_cast<FIT_LARGE_TYPE>(UTF16_1UNIT_TO_POINT(strSrc[i]));
if (!UTF16_IS_POINT_1UNIT(codePoint))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF16_OVERENCODED_POINT_1);
}
else if (UTF16_IS_UNIT_2UNIT_LEAD(strSrc[i]))
{
if ((++i) >= strSrc.size())
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF16_END_OF_STRING);
if (!UTF16_IS_UNIT_2UNIT_TAIL(strSrc[i]))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF16_NON_TAIL_UNIT);
if (!UTF16_IS_UNIT_VALID(strSrc[i]))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF16_INVALID_TAIL_UNIT);
codePoint = static_cast<FIT_LARGE_TYPE>(UTF16_2UNIT_TO_POINT(strSrc[i-1], strSrc[i]));
if (!UTF16_IS_POINT_2UNIT(codePoint))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF16_OVERENCODED_POINT_2);
}
else
{
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF16_INVALID_LEAD_UNIT);
}
}
break;
case FIT_UNICODE_ENCODING_UTF32:
{
if (!UTF32_IS_UNIT_VALID(strSrc[i]))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF32_INVALID_UNIT);
codePoint = static_cast<FIT_LARGE_TYPE>(UTF32_UNIT_TO_POINT(strSrc[i]));
}
break;
default:
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UNICODE_UNDEFINED_SOURCE_ENCODING);
}
// Check that the code point is valid.
if (!UNICODE_IS_POINT_VALID(codePoint))
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UNICODE_INVALID_POINT);
// Encode the destination.
switch (dstEncoding)
{
case FIT_UNICODE_ENCODING_UTF8:
if (UTF8_IS_POINT_1UNIT(codePoint))
{
convertedStr.push_back((CHAR_TYPE_DST) UTF8_POINT_TO_1UNIT(codePoint));
}
else if (UTF8_IS_POINT_2UNIT(codePoint))
{
convertedStr.push_back((CHAR_TYPE_DST) UTF8_POINT_TO_2UNIT_LEAD(codePoint));
convertedStr.push_back((CHAR_TYPE_DST) UTF8_POINT_TO_2UNIT_CONT1(codePoint));
}
else if (UTF8_IS_POINT_3UNIT(codePoint))
{
convertedStr.push_back((CHAR_TYPE_DST) UTF8_POINT_TO_3UNIT_LEAD(codePoint));
convertedStr.push_back((CHAR_TYPE_DST) UTF8_POINT_TO_3UNIT_CONT1(codePoint));
convertedStr.push_back((CHAR_TYPE_DST) UTF8_POINT_TO_3UNIT_CONT2(codePoint));
}
else if (UTF8_IS_POINT_4UNIT(codePoint))
{
convertedStr.push_back((CHAR_TYPE_DST) UTF8_POINT_TO_4UNIT_LEAD(codePoint));
convertedStr.push_back((CHAR_TYPE_DST) UTF8_POINT_TO_4UNIT_CONT1(codePoint));
convertedStr.push_back((CHAR_TYPE_DST) UTF8_POINT_TO_4UNIT_CONT2(codePoint));
convertedStr.push_back((CHAR_TYPE_DST) UTF8_POINT_TO_4UNIT_CONT3(codePoint));
}
else
{
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF8_INVALID_NUM_UNITS);
}
break;
case FIT_UNICODE_ENCODING_UTF16:
if (UTF16_IS_POINT_1UNIT(codePoint))
{
convertedStr.push_back((CHAR_TYPE_DST) UTF16_POINT_TO_1UNIT(codePoint));
}
else if (UTF16_IS_POINT_2UNIT(codePoint))
{
convertedStr.push_back((CHAR_TYPE_DST) UTF16_POINT_TO_2UNIT_LEAD(codePoint));
convertedStr.push_back((CHAR_TYPE_DST) UTF16_POINT_TO_2UNIT_TAIL(codePoint));
}
else
{
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UTF16_INVALID_NUM_UNITS);
}
break;
case FIT_UNICODE_ENCODING_UTF32:
convertedStr.push_back((CHAR_TYPE_DST) UTF32_POINT_TO_UNIT(codePoint));
break;
default:
throw StringConversionException(FIT_STRING_CONVERSION_ERROR_UNICODE_UNDEFINED_DESTINATION_ENCODING);
}
} // end try
catch (const StringConversionException&)
{
continue; // Go to the next character.
}
}
strDst = convertedStr;
return FIT_TRUE;
}
///////////////////////////////////////////////////////////////////////
// Public Functions
///////////////////////////////////////////////////////////////////////
Unicode::UTF8_STRING Unicode::Encode_BaseToUTF8(const FIT_WSTRING& strSrc)
{
Unicode::UTF8_STRING strDst;
if (ConvertStringEncoding<Unicode::UTF8_STRING, Unicode::UTF8_STRING::value_type, FIT_WSTRING, FIT_WSTRING::value_type>(strDst, FIT_UNICODE_ENCODING_UTF8, strSrc, INTERNAL_UNICODE_ENCODING))
return strDst;
else
return Unicode::UTF8_STRING();
}
FIT_WSTRING Unicode::Encode_UTF8ToBase(const Unicode::UTF8_STRING& strSrc)
{
FIT_WSTRING strDst;
if (ConvertStringEncoding<FIT_WSTRING, FIT_WSTRING::value_type, Unicode::UTF8_STRING, Unicode::UTF8_STRING::value_type>(strDst, INTERNAL_UNICODE_ENCODING, strSrc, FIT_UNICODE_ENCODING_UTF8))
return strDst;
else
return FIT_WSTRING_INVALID;
}
Unicode::UTF8_STRING Unicode::Copy_StdToUTF8(const std::string& strSrc)
{
#if 0
Unicode::UTF8_STRING strDst(static_cast<Unicode::UTF8_STRING::size_type>(strSrc.size()), 0);
for (Unicode::UTF8_STRING::size_type i = 0; i < strDst.size(); i++)
strDst[i] = static_cast<Unicode::UTF8_STRING::value_type>(strSrc[i]);
return strDst;
#endif
return strSrc; // Input type is typedef'd to be the same as output - this shortcut is valid.
}
std::string Unicode::Copy_UTF8ToStd(const Unicode::UTF8_STRING& strSrc)
{
#if 0
string strDst(static_cast<string::size_type>(strSrc.size()), 0);
for (std::string::size_type i = 0; i < strDst.size(); i++)
strDst[i] = static_cast<string::value_type>(strSrc[i]);
return strDst;
#endif
return strSrc; // Input type is typedef'd to be the same as output - this shortcut is valid.
}
} // namespace fit