cgpt/cgpt_common.c
/* Convert UTF8 string to UTF16. The UTF8 string must be null-terminated.
 * Caller must prepare enough space for UTF16, including a terminating 0x0000.
 * See the following table for encoding lengths. In any case, the caller
 * just needs to prepare the byte length of UTF8 plus the terminating 0x0000.
 *
 *     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 converts UTF8 chars to a code point first. Then, convrts it
 * to UTF16 code unit(s).
 *
 * Return: CGPT_OK --- all character are converted successfully.
 *         CGPT_FAILED --- convert error, i.e. output buffer is too short.
 */
Convert UTF8 string to UTF16. The UTF8 string must be null-terminated.
Caller must prepare enough space for UTF16, including a terminating 0x0000.
See the following table for encoding lengths. In any case, the caller
just needs to prepare the byte length of UTF8 plus the terminating 0x0000.



This function converts UTF8 chars to a code point first. Then, convrts it
to UTF16 code unit(s).

all character are converted successfully.
CGPT_FAILED --- convert error, i.e. output buffer is too short.
Convert UTF8 string to UTF16 . The UTF8 string must be null - terminated . Caller must prepare enough space for UTF16 including a terminating 0x0000 . See the following table for encoding lengths . In any case the caller just needs to prepare the byte length of UTF8 plus the terminating 0x0000 . This function converts UTF8 chars to a code point first . Then convrts it to UTF16 code unit ( s ) . all character are converted successfully . CGPT_FAILED --- convert error i . e . output buffer is too short .
int UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16, unsigned int maxoutput)
{
  size_t s16idx, s8idx;
  uint32_t code_point = 0;
  unsigned int expected_units = 1;
  unsigned int decoded_units = 1;
  int retval = CGPT_OK;
  if (!utf8 || !utf16 || !maxoutput)
    return CGPT_FAILED;
  maxoutput--;                             
  for (s8idx = s16idx = 0;
       utf8[s8idx] && maxoutput;
       s8idx++) {
    uint8_t code_unit;
    code_unit = utf8[s8idx];
    if (expected_units != decoded_units) {
      if ((code_unit & 0xC0) == 0x80) {
        code_point = (code_point << 6) | (code_unit & 0x3F);
        ++decoded_units;
      } else {
        retval = CGPT_FAILED;
        break;
      }
    } else {
      decoded_units = 1;
      if (code_unit <= 0x7F) {
        code_point = code_unit;
        expected_units = 1;
      } else if (code_unit <= 0xBF) {
        retval = CGPT_FAILED;
        break;
      } else if (code_unit >= 0xC2 && code_unit <= 0xDF) {
        code_point = code_unit & 0x1F;
        expected_units = 2;
      } else if (code_unit >= 0xE0 && code_unit <= 0xEF) {
        code_point = code_unit & 0x0F;
        expected_units = 3;
      } else if (code_unit >= 0xF0 && code_unit <= 0xF4) {
        code_point = code_unit & 0x07;
        expected_units = 4;
      } else {
        retval = CGPT_FAILED;
        break;
      }
    }
    if ((retval == CGPT_OK) &&
        (expected_units == decoded_units)) {
      switch (expected_units) {
        case 2:
          if (code_point <= 0x7F) retval = CGPT_FAILED;
          break;
        case 3:
          if (code_point <= 0x7FF) retval = CGPT_FAILED;
          break;
        case 4:
          if (code_point <= 0xFFFF) retval = CGPT_FAILED;
          break;
      }
      if (retval == CGPT_FAILED) break;  
      if ((code_point <= 0xD7FF) ||
          (code_point >= 0xE000 && code_point <= 0xFFFF)) {
        utf16[s16idx++] = code_point;
        maxoutput -= 1;
      } else if (code_point >= 0x10000 && code_point <= 0x10FFFF &&
                 maxoutput >= 2) {
        utf16[s16idx++] = 0xD800 | ((code_point >> 10) - 0x0040);
        utf16[s16idx++] = 0xDC00 | (code_point & 0x03FF);
        maxoutput -= 2;
      } else {
        retval = CGPT_FAILED;
        break;
      }
    }
  }
  if (expected_units != decoded_units) {
    retval = CGPT_FAILED;
  }
  utf16[s16idx++] = 0;
  return retval;
}
int UTF8ToUTF16 ( const uint8_t * utf8 , uint16_t * utf16 , unsigned int maxoutput ) { size_t s16idx , s8idx ; uint32_t code_point = 0 ; unsigned int expected_units = 1 ; unsigned int decoded_units = 1 ; int retval = CGPT_OK ; if ( ! utf8 || ! utf16 || ! maxoutput ) return CGPT_FAILED ; maxoutput -- ; for ( s8idx = s16idx = 0 ; utf8 [ s8idx ] && maxoutput ; s8idx ++ ) { uint8_t code_unit ; code_unit = utf8 [ s8idx ] ; if ( expected_units != decoded_units ) { if ( ( code_unit & 0xC0 ) == 0x80 ) { code_point = ( code_point << 6 ) | ( code_unit & 0x3F ) ; ++ decoded_units ; } else { retval = CGPT_FAILED ; break ; } } else { decoded_units = 1 ; if ( code_unit <= 0x7F ) { code_point = code_unit ; expected_units = 1 ; } else if ( code_unit <= 0xBF ) { retval = CGPT_FAILED ; break ; } else if ( code_unit >= 0xC2 && code_unit <= 0xDF ) { code_point = code_unit & 0x1F ; expected_units = 2 ; } else if ( code_unit >= 0xE0 && code_unit <= 0xEF ) { code_point = code_unit & 0x0F ; expected_units = 3 ; } else if ( code_unit >= 0xF0 && code_unit <= 0xF4 ) { code_point = code_unit & 0x07 ; expected_units = 4 ; } else { retval = CGPT_FAILED ; break ; } } if ( ( retval == CGPT_OK ) && ( expected_units == decoded_units ) ) { switch ( expected_units ) { case 2 : if ( code_point <= 0x7F ) retval = CGPT_FAILED ; break ; case 3 : if ( code_point <= 0x7FF ) retval = CGPT_FAILED ; break ; case 4 : if ( code_point <= 0xFFFF ) retval = CGPT_FAILED ; break ; } if ( retval == CGPT_FAILED ) break ; if ( ( code_point <= 0xD7FF ) || ( code_point >= 0xE000 && code_point <= 0xFFFF ) ) { utf16 [ s16idx ++ ] = code_point ; maxoutput -= 1 ; } else if ( code_point >= 0x10000 && code_point <= 0x10FFFF && maxoutput >= 2 ) { utf16 [ s16idx ++ ] = 0xD800 | ( ( code_point >> 10 ) - 0x0040 ) ; utf16 [ s16idx ++ ] = 0xDC00 | ( code_point & 0x03FF ) ; maxoutput -= 2 ; } else { retval = CGPT_FAILED ; break ; } } } if ( expected_units != decoded_units ) { retval = CGPT_FAILED ; } utf16 [ s16idx ++ ] = 0 ; return retval ; }
Convert UTF8 string to UTF16.
Convert UTF8 string to UTF16 .
/* plan for termination */ /* Trailing bytes of multi-byte character */ /* Unexpected code unit. */ /* parsing a new code point. */ /* 0x80-0xBF must NOT be the heading byte unit of a new code point. */ /* illegal code unit: 0xC0-0xC1, 0xF5-0xFF */ /* If no more unit is needed, output the UTF16 unit(s). */ /* Check if the encoding is the shortest possible UTF-8 sequence. */ /* leave immediately */ /* Three possibilities fall into here. Both are failure cases.
         *   a. surrogate pair (non-BMP characters; 0xD800~0xDFFF)
         *   b. invalid code point > 0x10FFFF
         *   c. buffer underrun
         */ /* A null-terminator shows up before the UTF8 sequence ends. */