function utf8_char_mapping($str, $mode, $opt = '') {
		if (!$this->initUnicodeData($mode)) {
			return $str;
		} // do nothing

		$out = '';
		switch ($mode) {
			case 'case':
				$map =& $this->caseFolding['utf-8'][$opt];
				break;

			case 'ascii':
				$map =& $this->toASCII['utf-8'];
				break;

			default:
				return $str;
		}

		for ($i = 0; strlen($str{$i}); $i++) {
			$c = ord($str{$i});
			if (!($c & 0x80)) // single-byte (0xxxxxx)
			{
				$mbc = $str{$i};
			}
			elseif (($c & 0xC0) == 0xC0) { // multi-byte starting byte (11xxxxxx)
				for ($bc = 0; $c & 0x80; $c = $c << 1) {
					$bc++;
				} // calculate number of bytes
				$mbc = substr($str, $i, $bc);
				$i += $bc - 1;
			}

			if (isset($map[$mbc])) {
				$out .= $map[$mbc];
			} else {
				$out .= $mbc;
			}
		}

		return $out;
	}