source/AccessorySDK/Support/utfconv.c
int
utf8_normalizestr(const uint8_t* instr, size_t inlen, uint8_t* outstr,
                  size_t *outlen, size_t buflen, int flags)
{
	uint16_t unicodebuf[32];
	uint16_t* unistr = NULL;
	size_t unicode_bytes;
	size_t uft8_bytes;
	size_t inbuflen;
	uint8_t *outbufstart, *outbufend;
	const uint8_t *inbufstart;
	unsigned int byte;
	int decompose, precompose;
	int result = 0;

	if (flags & ~(UTF_DECOMPOSED | UTF_PRECOMPOSED | UTF_NO_NULL_TERM | UTF_ESCAPE_ILLEGAL)) {
		return (EINVAL);
	}
	decompose = (flags & UTF_DECOMPOSED);
	precompose = (flags & UTF_PRECOMPOSED);
	if ((decompose && precompose) || (!decompose && !precompose)) {
		return (EINVAL);
	}
	outbufstart = outstr;
	outbufend = outbufstart + buflen;
	inbufstart = instr;
	inbuflen = inlen;

	while (inlen-- > 0 && (byte = *instr++) != '\0') {
		if (outstr >= outbufend) {
			result = ENAMETOOLONG;
			goto exit;
		}
		if (byte >= 0x80) {
			goto nonASCII;
		}
		/* ASCII is already normalized. */
		*outstr++ = (uint8_t)byte;
	}
exit:
	*outlen = (size_t)(outstr - outbufstart);
	if (((flags & UTF_NO_NULL_TERM) == 0)) {
		if (outstr < outbufend)
			*outstr = '\0';
		else
			result = ENAMETOOLONG;
	}
	return (result);


	/* 
	 * Non-ASCII uses the existing utf8_encodestr/utf8_decodestr
	 * functions to perform the normalization.  Since this will
	 * presumably be used to normalize filenames in the back-end
	 * (on disk or over-the-wire), it should be fast enough.
	 */
nonASCII:

	/* Make sure the input size is reasonable. */
	if (inbuflen > PATH_MAX) {
		result = ENAMETOOLONG;
		goto exit;
	}
	/*
	 * Compute worst case Unicode buffer size.
	 *
	 * For pre-composed output, every UTF-8 input byte will be at
	 * most 2 Unicode bytes.  For decomposed output, 2 UTF-8 bytes
	 * (smallest composite char sequence) may yield 6 Unicode bytes
	 * (1 base char + 2 combining chars).
	 */
	unicode_bytes = precompose ? (inbuflen * 2) : (inbuflen * 3);

	if (unicode_bytes <= sizeof(unicodebuf))
		unistr = &unicodebuf[0];
	else {
		unistr = (uint16_t*)utfmalloc(unicode_bytes);
		if (!unistr) {
			result = ENOMEM;
			goto exit;
		}
	}

	/* Normalize the string. */
	result = utf8_decodestr(inbufstart, inbuflen, unistr, &unicode_bytes,
	                        unicode_bytes, 0, flags & ~UTF_NO_NULL_TERM);
	if (result == 0) {
		/* Put results back into UTF-8. */
		result = utf8_encodestr(unistr, unicode_bytes, outbufstart,
		                        &uft8_bytes, buflen, 0, UTF_NO_NULL_TERM);
		outstr = outbufstart + uft8_bytes;
	}
	if (unistr && unistr != &unicodebuf[0]) {
		utffree(unistr);
	}
	goto exit;
}
/*
 * utf8_normalizestr - Normalize a UTF-8 string (NFC or NFD)
 *
 * This function takes an UTF-8 input string, instr, of inlen bytes
 * and produces normalized UTF-8 output into a buffer of buflen bytes
 * pointed to by outstr. The size of the output in bytes (not including
 * a NULL termination byte) is returned in outlen. In-place conversions
 * are not supported (i.e. instr != outstr).]
 
 * FLAGS
 *    UTF_DECOMPOSED:  output string will be fully decomposed (NFD)
 *
 *    UTF_PRECOMPOSED:  output string will be precomposed (NFC)
 *
 *    UTF_NO_NULL_TERM:  do not add null termination to output string
 *
 *    UTF_ESCAPE_ILLEGAL:  percent escape any illegal UTF-8 input
 *
 * ERRORS
 *    ENAMETOOLONG:  output did not fit or input exceeded MAXPATHLEN bytes
 *
 *    EINVAL:  illegal UTF-8 sequence encountered or invalid flags
 */
Normalize a UTF-8 string (NFC or NFD)
This function takes an UTF-8 input string, instr, of inlen bytes
and produces normalized UTF-8 output into a buffer of buflen bytes
pointed to by outstr. The size of the output in bytes (not including
a NULL termination byte) is returned in outlen. In-place conversions
are not supported .]

FLAGS
UTF_DECOMPOSED:  output string will be fully decomposed (NFD)

output string will be precomposed (NFC)

do not add null termination to output string

percent escape any illegal UTF-8 input

ERRORS
ENAMETOOLONG:  output did not fit or input exceeded MAXPATHLEN bytes

illegal UTF-8 sequence encountered or invalid flags
Normalize a UTF - 8 string ( NFC or NFD ) This function takes an UTF - 8 input string instr of inlen bytes and produces normalized UTF - 8 output into a buffer of buflen bytes pointed to by outstr . The size of the output in bytes ( not including a NULL termination byte ) is returned in outlen . In - place conversions are not supported . ] FLAGS UTF_DECOMPOSED : output string will be fully decomposed ( NFD ) output string will be precomposed ( NFC ) do not add null termination to output string percent escape any illegal UTF - 8 input ERRORS ENAMETOOLONG : output did not fit or input exceeded MAXPATHLEN bytes illegal UTF - 8 sequence encountered or invalid flags
int
utf8_normalizestr(const uint8_t* instr, size_t inlen, uint8_t* outstr,
                  size_t *outlen, size_t buflen, int flags)
{
	uint16_t unicodebuf[32];
	uint16_t* unistr = NULL;
	size_t unicode_bytes;
	size_t uft8_bytes;
	size_t inbuflen;
	uint8_t *outbufstart, *outbufend;
	const uint8_t *inbufstart;
	unsigned int byte;
	int decompose, precompose;
	int result = 0;
	if (flags & ~(UTF_DECOMPOSED | UTF_PRECOMPOSED | UTF_NO_NULL_TERM | UTF_ESCAPE_ILLEGAL)) {
		return (EINVAL);
	}
	decompose = (flags & UTF_DECOMPOSED);
	precompose = (flags & UTF_PRECOMPOSED);
	if ((decompose && precompose) || (!decompose && !precompose)) {
		return (EINVAL);
	}
	outbufstart = outstr;
	outbufend = outbufstart + buflen;
	inbufstart = instr;
	inbuflen = inlen;
	while (inlen-- > 0 && (byte = *instr++) != '\0') {
		if (outstr >= outbufend) {
			result = ENAMETOOLONG;
			goto exit;
		}
		if (byte >= 0x80) {
			goto nonASCII;
		}
		*outstr++ = (uint8_t)byte;
	}
exit:
	*outlen = (size_t)(outstr - outbufstart);
	if (((flags & UTF_NO_NULL_TERM) == 0)) {
		if (outstr < outbufend)
			*outstr = '\0';
		else
			result = ENAMETOOLONG;
	}
	return (result);
nonASCII:
	if (inbuflen > PATH_MAX) {
		result = ENAMETOOLONG;
		goto exit;
	}
	unicode_bytes = precompose ? (inbuflen * 2) : (inbuflen * 3);
	if (unicode_bytes <= sizeof(unicodebuf))
		unistr = &unicodebuf[0];
	else {
		unistr = (uint16_t*)utfmalloc(unicode_bytes);
		if (!unistr) {
			result = ENOMEM;
			goto exit;
		}
	}
	result = utf8_decodestr(inbufstart, inbuflen, unistr, &unicode_bytes,
	                        unicode_bytes, 0, flags & ~UTF_NO_NULL_TERM);
	if (result == 0) {
		result = utf8_encodestr(unistr, unicode_bytes, outbufstart,
		                        &uft8_bytes, buflen, 0, UTF_NO_NULL_TERM);
		outstr = outbufstart + uft8_bytes;
	}
	if (unistr && unistr != &unicodebuf[0]) {
		utffree(unistr);
	}
	goto exit;
}
int utf8_normalizestr ( const uint8_t * instr , size_t inlen , uint8_t * outstr , size_t * outlen , size_t buflen , int flags ) { uint16_t unicodebuf [ 32 ] ; uint16_t * unistr = NULL ; size_t unicode_bytes ; size_t uft8_bytes ; size_t inbuflen ; uint8_t * outbufstart , * outbufend ; const uint8_t * inbufstart ; unsigned int byte ; int decompose , precompose ; int result = 0 ; if ( flags & ~ ( UTF_DECOMPOSED | UTF_PRECOMPOSED | UTF_NO_NULL_TERM | UTF_ESCAPE_ILLEGAL ) ) { return ( EINVAL ) ; } decompose = ( flags & UTF_DECOMPOSED ) ; precompose = ( flags & UTF_PRECOMPOSED ) ; if ( ( decompose && precompose ) || ( ! decompose && ! precompose ) ) { return ( EINVAL ) ; } outbufstart = outstr ; outbufend = outbufstart + buflen ; inbufstart = instr ; inbuflen = inlen ; while ( inlen -- > 0 && ( byte = * instr ++ ) != ' \0 ' ) { if ( outstr >= outbufend ) { result = ENAMETOOLONG ; goto exit ; } if ( byte >= 0x80 ) { goto nonASCII ; } * outstr ++ = ( uint8_t ) byte ; } exit : * outlen = ( size_t ) ( outstr - outbufstart ) ; if ( ( ( flags & UTF_NO_NULL_TERM ) == 0 ) ) { if ( outstr < outbufend ) * outstr = ' \0 ' ; else result = ENAMETOOLONG ; } return ( result ) ; nonASCII : if ( inbuflen > PATH_MAX ) { result = ENAMETOOLONG ; goto exit ; } unicode_bytes = precompose ? ( inbuflen * 2 ) : ( inbuflen * 3 ) ; if ( unicode_bytes <= sizeof ( unicodebuf ) ) unistr = & unicodebuf [ 0 ] ; else { unistr = ( uint16_t * ) utfmalloc ( unicode_bytes ) ; if ( ! unistr ) { result = ENOMEM ; goto exit ; } } result = utf8_decodestr ( inbufstart , inbuflen , unistr , & unicode_bytes , unicode_bytes , 0 , flags & ~ UTF_NO_NULL_TERM ) ; if ( result == 0 ) { result = utf8_encodestr ( unistr , unicode_bytes , outbufstart , & uft8_bytes , buflen , 0 , UTF_NO_NULL_TERM ) ; outstr = outbufstart + uft8_bytes ; } if ( unistr && unistr != & unicodebuf [ 0 ] ) { utffree ( unistr ) ; } goto exit ; }
utf8_normalizestr - Normalize a UTF-8 string (NFC or NFD)
 This function takes an UTF-8 input string, instr, of inlen bytes
 and produces normalized UTF-8 output into a buffer of buflen bytes
 pointed to by outstr.
utf8_normalizestr - Normalize a UTF - 8 string ( NFC or NFD ) This function takes an UTF - 8 input string instr of inlen bytes and produces normalized UTF - 8 output into a buffer of buflen bytes pointed to by outstr .
/* ASCII is already normalized. */ /* 
	 * Non-ASCII uses the existing utf8_encodestr/utf8_decodestr
	 * functions to perform the normalization.  Since this will
	 * presumably be used to normalize filenames in the back-end
	 * (on disk or over-the-wire), it should be fast enough.
	 */ /* Make sure the input size is reasonable. */ /*
	 * Compute worst case Unicode buffer size.
	 *
	 * For pre-composed output, every UTF-8 input byte will be at
	 * most 2 Unicode bytes.  For decomposed output, 2 UTF-8 bytes
	 * (smallest composite char sequence) may yield 6 Unicode bytes
	 * (1 base char + 2 combining chars).
	 */ /* Normalize the string. */ /* Put results back into UTF-8. */