libintelprov/gpt/lib/cgpt_common.c
/* Convert possibly unterminated UTF16 string to UTF8.
 * Caller must prepare enough space for UTF8, which could be up to
 * twice the byte length of UTF16 string plus the terminating '\0'.
 * See the following table for encoding lengths.
 *
 *     Code point       UTF16       UTF8
 *   0x0000-0x007F     2 bytes     1 byte
 *   0x0080-0x07FF     2 bytes     2 bytes
 *   0x0800-0xFFFF     2 bytes     3 bytes
 *  0x10000-0x10FFFF   4 bytes     4 bytes
 *
 * This function uses a simple state meachine to convert UTF-16 char(s) to
 * a code point. Once a code point is parsed out, the state machine throws
 * out sequencial UTF-8 chars in one time.
 *
 * Return: CGPT_OK --- all character are converted successfully.
 *         CGPT_FAILED --- convert error, i.e. output buffer is too short.
 */
Convert possibly unterminated UTF16 string to UTF8.
Caller must prepare enough space for UTF8, which could be up to
twice the byte length of UTF16 string plus the terminating '\0'.
See the following table for encoding lengths.



This function uses a simple state meachine to convert UTF-16 char(s) to
a code point. Once a code point is parsed out, the state machine throws
out sequencial UTF-8 chars in one time.

all character are converted successfully.
CGPT_FAILED --- convert error, i.e. output buffer is too short.
Convert possibly unterminated UTF16 string to UTF8 . Caller must prepare enough space for UTF8 which could be up to twice the byte length of UTF16 string plus the terminating ' \ 0 ' . See the following table for encoding lengths . This function uses a simple state meachine to convert UTF - 16 char ( s ) to a code point . Once a code point is parsed out the state machine throws out sequencial UTF - 8 chars in one time . all character are converted successfully . CGPT_FAILED --- convert error i . e . output buffer is too short .
int UTF16ToUTF8(const uint16_t *utf16, unsigned int maxinput,
                uint8_t *utf8, unsigned int maxoutput)
{
  size_t s16idx, s8idx;
  uint32_t code_point = 0;
  int code_point_ready = 1;  
  int retval = CGPT_OK;
  if (!utf16 || !maxinput || !utf8 || !maxoutput)
    return CGPT_FAILED;
  maxoutput--;                             
  for (s16idx = s8idx = 0;
       s16idx < maxinput && utf16[s16idx] && maxoutput;
       s16idx++) {
    uint16_t codeunit = le16toh(utf16[s16idx]);
    if (code_point_ready) {
      if (codeunit >= 0xD800 && codeunit <= 0xDBFF) {
        code_point_ready = 0;
        code_point = (codeunit & 0x03FF) + 0x0040;
      } else {
        code_point = codeunit;
      }
    } else {
      if (codeunit >= 0xDC00 && codeunit <= 0xDFFF) {
        code_point = (code_point << 10) | (codeunit & 0x03FF);
        code_point_ready = 1;
      } else {
        code_point_ready = 0;
        retval = CGPT_FAILED;
        break;
      }
    }
    if (code_point_ready) {
      require(code_point <= 0x10FFFF);
      if (code_point <= 0x7F && maxoutput >= 1) {
        maxoutput -= 1;
        utf8[s8idx++] = code_point & 0x7F;
      } else if (code_point <= 0x7FF && maxoutput >= 2) {
        maxoutput -= 2;
        utf8[s8idx++] = 0xC0 | (code_point >> 6);
        utf8[s8idx++] = 0x80 | (code_point & 0x3F);
      } else if (code_point <= 0xFFFF && maxoutput >= 3) {
        maxoutput -= 3;
        utf8[s8idx++] = 0xE0 | (code_point >> 12);
        utf8[s8idx++] = 0x80 | ((code_point >> 6) & 0x3F);
        utf8[s8idx++] = 0x80 | (code_point & 0x3F);
      } else if (code_point <= 0x10FFFF && maxoutput >= 4) {
        maxoutput -= 4;
        utf8[s8idx++] = 0xF0 | (code_point >> 18);
        utf8[s8idx++] = 0x80 | ((code_point >> 12) & 0x3F);
        utf8[s8idx++] = 0x80 | ((code_point >> 6) & 0x3F);
        utf8[s8idx++] = 0x80 | (code_point & 0x3F);
      } else {
        retval = CGPT_FAILED;
        break;
      }
    }
  }
  utf8[s8idx++] = 0;
  return retval;
}
int UTF16ToUTF8 ( const uint16_t * utf16 , unsigned int maxinput , uint8_t * utf8 , unsigned int maxoutput ) { size_t s16idx , s8idx ; uint32_t code_point = 0 ; int code_point_ready = 1 ; int retval = CGPT_OK ; if ( ! utf16 || ! maxinput || ! utf8 || ! maxoutput ) return CGPT_FAILED ; maxoutput -- ; for ( s16idx = s8idx = 0 ; s16idx < maxinput && utf16 [ s16idx ] && maxoutput ; s16idx ++ ) { uint16_t codeunit = le16toh ( utf16 [ s16idx ] ) ; if ( code_point_ready ) { if ( codeunit >= 0xD800 && codeunit <= 0xDBFF ) { code_point_ready = 0 ; code_point = ( codeunit & 0x03FF ) + 0x0040 ; } else { code_point = codeunit ; } } else { if ( codeunit >= 0xDC00 && codeunit <= 0xDFFF ) { code_point = ( code_point << 10 ) | ( codeunit & 0x03FF ) ; code_point_ready = 1 ; } else { code_point_ready = 0 ; retval = CGPT_FAILED ; break ; } } if ( code_point_ready ) { require ( code_point <= 0x10FFFF ) ; if ( code_point <= 0x7F && maxoutput >= 1 ) { maxoutput -= 1 ; utf8 [ s8idx ++ ] = code_point & 0x7F ; } else if ( code_point <= 0x7FF && maxoutput >= 2 ) { maxoutput -= 2 ; utf8 [ s8idx ++ ] = 0xC0 | ( code_point >> 6 ) ; utf8 [ s8idx ++ ] = 0x80 | ( code_point & 0x3F ) ; } else if ( code_point <= 0xFFFF && maxoutput >= 3 ) { maxoutput -= 3 ; utf8 [ s8idx ++ ] = 0xE0 | ( code_point >> 12 ) ; utf8 [ s8idx ++ ] = 0x80 | ( ( code_point >> 6 ) & 0x3F ) ; utf8 [ s8idx ++ ] = 0x80 | ( code_point & 0x3F ) ; } else if ( code_point <= 0x10FFFF && maxoutput >= 4 ) { maxoutput -= 4 ; utf8 [ s8idx ++ ] = 0xF0 | ( code_point >> 18 ) ; utf8 [ s8idx ++ ] = 0x80 | ( ( code_point >> 12 ) & 0x3F ) ; utf8 [ s8idx ++ ] = 0x80 | ( ( code_point >> 6 ) & 0x3F ) ; utf8 [ s8idx ++ ] = 0x80 | ( code_point & 0x3F ) ; } else { retval = CGPT_FAILED ; break ; } } } utf8 [ s8idx ++ ] = 0 ; return retval ; }
Convert possibly unterminated UTF16 string to UTF8.
Convert possibly unterminated UTF16 string to UTF8 .
// code point is ready to output. /* plan for termination now */ /* high surrogate, need the low surrogate. */ /* BMP char, output it. */ /* expect the low surrogate */ /* the second code unit is NOT the low surrogate. Unexpected. */ /* If UTF code point is ready, output it. */ /* buffer underrun */