source/AccessorySDK/Support/utfconv.c
int
utf8_encodestr(const uint16_t * ucsp, size_t ucslen, uint8_t * utf8p,
               size_t * utf8len, size_t buflen, uint16_t altslash, int flags)
{
	uint8_t * bufstart;
	uint8_t * bufend;
	uint16_t ucs_ch;
	uint16_t * chp = NULL;
	uint16_t sequence[8];
	int extra = 0;
	int charcnt;
	int swapbytes = (flags & UTF_REVERSE_ENDIAN);
	int nullterm  = ((flags & UTF_NO_NULL_TERM) == 0);
	int decompose = (flags & UTF_DECOMPOSED);
	int sfmconv = (flags & UTF_SFM_CONVERSIONS);
	int result = 0;

	bufstart = utf8p;
	bufend = bufstart + buflen;
	if (nullterm)
		--bufend;
	charcnt = (int)(ucslen / 2);

	while (charcnt-- > 0) {
		if (extra > 0) {
			--extra;
			ucs_ch = *chp++; // Note: chp is from the local, aligned "sequence" array.
		} else {
			if (swapbytes)	ucs_ch = ReadSwap16(ucsp);
			else			ucs_ch = ReadHost16(ucsp);
			++ucsp;

			if (decompose && unicode_decomposeable(ucs_ch)) {
				extra = unicode_decompose(ucs_ch, sequence) - 1;
				charcnt += extra;
				ucs_ch = sequence[0];
				chp = &sequence[1];
			}
		}

		/* Slash and NULL are not permitted */
		if (ucs_ch == '/') {
			if (altslash)
				ucs_ch = altslash;
			else {
				ucs_ch = '_';
				result = EINVAL;
			}
		} else if (ucs_ch == '\0') {
			ucs_ch = UCS_ALT_NULL;
		}

		if (ucs_ch < 0x0080) {
			if (utf8p >= bufend) {
				result = ENAMETOOLONG;
				break;
			}			
			*utf8p++ = (uint8_t)ucs_ch;

		} else if (ucs_ch < 0x800) {
			if ((utf8p + 1) >= bufend) {
				result = ENAMETOOLONG;
				break;
			}
			*utf8p++ = (uint8_t)(0xc0 | (ucs_ch >> 6));
			*utf8p++ = (uint8_t)(0x80 | (0x3f & ucs_ch));

		} else {
			/* These chars never valid Unicode. */
			if (ucs_ch == 0xFFFE || ucs_ch == 0xFFFF) {
				result = EINVAL;
				break;
			}

			/* Combine valid surrogate pairs */
			if (ucs_ch >= SP_HIGH_FIRST && ucs_ch <= SP_HIGH_LAST
				&& charcnt > 0) {
				uint16_t ch2;
				uint32_t pair;

				if (swapbytes)	ch2 = ReadSwap16(ucsp);
				else			ch2 = ReadHost16(ucsp);
				if (ch2 >= SP_LOW_FIRST && ch2 <= SP_LOW_LAST) {
					pair = ((ucs_ch - SP_HIGH_FIRST) << SP_HALF_SHIFT)
						+ (ch2 - SP_LOW_FIRST) + SP_HALF_BASE;
					if ((utf8p + 3) >= bufend) {
						result = ENAMETOOLONG;
						break;
					}
					--charcnt;
					++ucsp;				
					*utf8p++ = (uint8_t)(0xf0 | (pair >> 18));
					*utf8p++ = (uint8_t)(0x80 | (0x3f & (pair >> 12)));
					*utf8p++ = (uint8_t)(0x80 | (0x3f & (pair >> 6)));
					*utf8p++ = (uint8_t)(0x80 | (0x3f & pair));
					continue;
				}
			} else if (sfmconv) {
				ucs_ch = sfm_to_ucs(ucs_ch);
				if (ucs_ch < 0x0080) {
					if (utf8p >= bufend) {
						result = ENAMETOOLONG;
						break;
					}			
					*utf8p++ = (uint8_t)ucs_ch;
					continue;
				}
			}
			if ((utf8p + 2) >= bufend) {
				result = ENAMETOOLONG;
				break;
			}
			*utf8p++ = (uint8_t)(0xe0 | (ucs_ch >> 12));
			*utf8p++ = (uint8_t)(0x80 | (0x3f & (ucs_ch >> 6)));
			*utf8p++ = (uint8_t)(0x80 | (0x3f & ucs_ch));
		}	
	}
	
	*utf8len = (size_t)(utf8p - bufstart);
	if (nullterm)
		*utf8p = '\0';

	return (result);
}
/*
 * utf8_encodestr - Encodes a Unicode string to UTF-8
 *
 * NOTES:
 *    The resulting UTF-8 string is NULL terminated.
 *
 *    If '/' chars are allowed on disk then an alternate
 *    (replacement) char must be provided in altslash.
 *
 * input flags:
 *    UTF_REVERSE_ENDIAN: Unicode byteorder is opposite current runtime
 *
 *    UTF_BIG_ENDIAN:  Unicode byte order is always big endian
 *
 *    UTF_LITTLE_ENDIAN:  Unicode byte order is always little endian
 *
 *    UTF_DECOMPOSED:  generate fully decomposed output
 *
 *    UTF_NO_NULL_TERM:  don't add NULL termination to UTF-8 output
 *
 * result:
 *    ENAMETOOLONG: Name didn't fit; only buflen bytes were encoded
 *
 *    EINVAL: Illegal char found; char was replaced by an '_'.
 */
Encodes a Unicode string to UTF-8
NOTES:
The resulting UTF-8 string is NULL terminated.

If '/' chars are allowed on disk then an alternate
(replacement) char must be provided in altslash.

input flags:
UTF_REVERSE_ENDIAN: Unicode byteorder is opposite current runtime

Unicode byte order is always big endian

Unicode byte order is always little endian

generate fully decomposed output

don't add NULL termination to UTF-8 output

Name didn't fit; only buflen bytes were encoded

Illegal char found; char was replaced by an '_'.
Encodes a Unicode string to UTF - 8 NOTES : The resulting UTF - 8 string is NULL terminated . If ' / ' chars are allowed on disk then an alternate ( replacement ) char must be provided in altslash . input flags : UTF_REVERSE_ENDIAN : Unicode byteorder is opposite current runtime Unicode byte order is always big endian Unicode byte order is always little endian generate fully decomposed output don ' t add NULL termination to UTF - 8 output Name didn ' t fit ; only buflen bytes were encoded Illegal char found ; char was replaced by an ' _ ' .
int
utf8_encodestr(const uint16_t * ucsp, size_t ucslen, uint8_t * utf8p,
               size_t * utf8len, size_t buflen, uint16_t altslash, int flags)
{
	uint8_t * bufstart;
	uint8_t * bufend;
	uint16_t ucs_ch;
	uint16_t * chp = NULL;
	uint16_t sequence[8];
	int extra = 0;
	int charcnt;
	int swapbytes = (flags & UTF_REVERSE_ENDIAN);
	int nullterm  = ((flags & UTF_NO_NULL_TERM) == 0);
	int decompose = (flags & UTF_DECOMPOSED);
	int sfmconv = (flags & UTF_SFM_CONVERSIONS);
	int result = 0;
	bufstart = utf8p;
	bufend = bufstart + buflen;
	if (nullterm)
		--bufend;
	charcnt = (int)(ucslen / 2);
	while (charcnt-- > 0) {
		if (extra > 0) {
			--extra;
			ucs_ch = *chp++; 
		} else {
			if (swapbytes)	ucs_ch = ReadSwap16(ucsp);
			else			ucs_ch = ReadHost16(ucsp);
			++ucsp;
			if (decompose && unicode_decomposeable(ucs_ch)) {
				extra = unicode_decompose(ucs_ch, sequence) - 1;
				charcnt += extra;
				ucs_ch = sequence[0];
				chp = &sequence[1];
			}
		}
		if (ucs_ch == '/') {
			if (altslash)
				ucs_ch = altslash;
			else {
				ucs_ch = '_';
				result = EINVAL;
			}
		} else if (ucs_ch == '\0') {
			ucs_ch = UCS_ALT_NULL;
		}
		if (ucs_ch < 0x0080) {
			if (utf8p >= bufend) {
				result = ENAMETOOLONG;
				break;
			}			
			*utf8p++ = (uint8_t)ucs_ch;
		} else if (ucs_ch < 0x800) {
			if ((utf8p + 1) >= bufend) {
				result = ENAMETOOLONG;
				break;
			}
			*utf8p++ = (uint8_t)(0xc0 | (ucs_ch >> 6));
			*utf8p++ = (uint8_t)(0x80 | (0x3f & ucs_ch));
		} else {
			if (ucs_ch == 0xFFFE || ucs_ch == 0xFFFF) {
				result = EINVAL;
				break;
			}
			if (ucs_ch >= SP_HIGH_FIRST && ucs_ch <= SP_HIGH_LAST
				&& charcnt > 0) {
				uint16_t ch2;
				uint32_t pair;
				if (swapbytes)	ch2 = ReadSwap16(ucsp);
				else			ch2 = ReadHost16(ucsp);
				if (ch2 >= SP_LOW_FIRST && ch2 <= SP_LOW_LAST) {
					pair = ((ucs_ch - SP_HIGH_FIRST) << SP_HALF_SHIFT)
						+ (ch2 - SP_LOW_FIRST) + SP_HALF_BASE;
					if ((utf8p + 3) >= bufend) {
						result = ENAMETOOLONG;
						break;
					}
					--charcnt;
					++ucsp;				
					*utf8p++ = (uint8_t)(0xf0 | (pair >> 18));
					*utf8p++ = (uint8_t)(0x80 | (0x3f & (pair >> 12)));
					*utf8p++ = (uint8_t)(0x80 | (0x3f & (pair >> 6)));
					*utf8p++ = (uint8_t)(0x80 | (0x3f & pair));
					continue;
				}
			} else if (sfmconv) {
				ucs_ch = sfm_to_ucs(ucs_ch);
				if (ucs_ch < 0x0080) {
					if (utf8p >= bufend) {
						result = ENAMETOOLONG;
						break;
					}			
					*utf8p++ = (uint8_t)ucs_ch;
					continue;
				}
			}
			if ((utf8p + 2) >= bufend) {
				result = ENAMETOOLONG;
				break;
			}
			*utf8p++ = (uint8_t)(0xe0 | (ucs_ch >> 12));
			*utf8p++ = (uint8_t)(0x80 | (0x3f & (ucs_ch >> 6)));
			*utf8p++ = (uint8_t)(0x80 | (0x3f & ucs_ch));
		}	
	}
	*utf8len = (size_t)(utf8p - bufstart);
	if (nullterm)
		*utf8p = '\0';
	return (result);
}
int utf8_encodestr ( const uint16_t * ucsp , size_t ucslen , uint8_t * utf8p , size_t * utf8len , size_t buflen , uint16_t altslash , int flags ) { uint8_t * bufstart ; uint8_t * bufend ; uint16_t ucs_ch ; uint16_t * chp = NULL ; uint16_t sequence [ 8 ] ; int extra = 0 ; int charcnt ; int swapbytes = ( flags & UTF_REVERSE_ENDIAN ) ; int nullterm = ( ( flags & UTF_NO_NULL_TERM ) == 0 ) ; int decompose = ( flags & UTF_DECOMPOSED ) ; int sfmconv = ( flags & UTF_SFM_CONVERSIONS ) ; int result = 0 ; bufstart = utf8p ; bufend = bufstart + buflen ; if ( nullterm ) -- bufend ; charcnt = ( int ) ( ucslen / 2 ) ; while ( charcnt -- > 0 ) { if ( extra > 0 ) { -- extra ; ucs_ch = * chp ++ ; } else { if ( swapbytes ) ucs_ch = ReadSwap16 ( ucsp ) ; else ucs_ch = ReadHost16 ( ucsp ) ; ++ ucsp ; if ( decompose && unicode_decomposeable ( ucs_ch ) ) { extra = unicode_decompose ( ucs_ch , sequence ) - 1 ; charcnt += extra ; ucs_ch = sequence [ 0 ] ; chp = & sequence [ 1 ] ; } } if ( ucs_ch == ' ' ) { if ( altslash ) ucs_ch = altslash ; else { ucs_ch = ' ' ; result = EINVAL ; } } else if ( ucs_ch == ' \0 ' ) { ucs_ch = UCS_ALT_NULL ; } if ( ucs_ch < 0x0080 ) { if ( utf8p >= bufend ) { result = ENAMETOOLONG ; break ; } * utf8p ++ = ( uint8_t ) ucs_ch ; } else if ( ucs_ch < 0x800 ) { if ( ( utf8p + 1 ) >= bufend ) { result = ENAMETOOLONG ; break ; } * utf8p ++ = ( uint8_t ) ( 0xc0 | ( ucs_ch >> 6 ) ) ; * utf8p ++ = ( uint8_t ) ( 0x80 | ( 0x3f & ucs_ch ) ) ; } else { if ( ucs_ch == 0xFFFE || ucs_ch == 0xFFFF ) { result = EINVAL ; break ; } if ( ucs_ch >= SP_HIGH_FIRST && ucs_ch <= SP_HIGH_LAST && charcnt > 0 ) { uint16_t ch2 ; uint32_t pair ; if ( swapbytes ) ch2 = ReadSwap16 ( ucsp ) ; else ch2 = ReadHost16 ( ucsp ) ; if ( ch2 >= SP_LOW_FIRST && ch2 <= SP_LOW_LAST ) { pair = ( ( ucs_ch - SP_HIGH_FIRST ) << SP_HALF_SHIFT ) + ( ch2 - SP_LOW_FIRST ) + SP_HALF_BASE ; if ( ( utf8p + 3 ) >= bufend ) { result = ENAMETOOLONG ; break ; } -- charcnt ; ++ ucsp ; * utf8p ++ = ( uint8_t ) ( 0xf0 | ( pair >> 18 ) ) ; * utf8p ++ = ( uint8_t ) ( 0x80 | ( 0x3f & ( pair >> 12 ) ) ) ; * utf8p ++ = ( uint8_t ) ( 0x80 | ( 0x3f & ( pair >> 6 ) ) ) ; * utf8p ++ = ( uint8_t ) ( 0x80 | ( 0x3f & pair ) ) ; continue ; } } else if ( sfmconv ) { ucs_ch = sfm_to_ucs ( ucs_ch ) ; if ( ucs_ch < 0x0080 ) { if ( utf8p >= bufend ) { result = ENAMETOOLONG ; break ; } * utf8p ++ = ( uint8_t ) ucs_ch ; continue ; } } if ( ( utf8p + 2 ) >= bufend ) { result = ENAMETOOLONG ; break ; } * utf8p ++ = ( uint8_t ) ( 0xe0 | ( ucs_ch >> 12 ) ) ; * utf8p ++ = ( uint8_t ) ( 0x80 | ( 0x3f & ( ucs_ch >> 6 ) ) ) ; * utf8p ++ = ( uint8_t ) ( 0x80 | ( 0x3f & ucs_ch ) ) ; } } * utf8len = ( size_t ) ( utf8p - bufstart ) ; if ( nullterm ) * utf8p = ' \0 ' ; return ( result ) ; }
utf8_encodestr - Encodes a Unicode string to UTF-8
 NOTES:
    The resulting UTF-8 string is NULL terminated.
utf8_encodestr - Encodes a Unicode string to UTF - 8 NOTES : The resulting UTF - 8 string is NULL terminated .
// Note: chp is from the local, aligned "sequence" array. /* Slash and NULL are not permitted */ /* These chars never valid Unicode. */ /* Combine valid surrogate pairs */