note 99422 deleted from function.utf8-encode by danbrown
| From: | danbrown@php.net | Date: | Tue, 17 Aug 2010 16:32:54 +0000 |
| Subject: | note 99422 deleted from function.utf8-encode by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-171773@lists.php.net to get a copy of this message | ||
Note Submitter: petepostma at gmail
----
squeegee, good idea!
I fixed up the code, used output buffering over repeated string concatenation, combined them to a
single function, changed the initial preg to match multiple of any valid characters (instead of just
ascii), and a few more speed ups.
Little quicker through out and and easier on memory on the second part.
function fix_encoding($instr){
if(mb_check_encoding($instr,'UTF-8'))return $instr; // no need for the rest if it's
all valid UTF-8 already
global $NIBBLE_GOOD_CHARS,$ENCODE_BYTE_MAP;
if(empty($ENCODE_BYTE_MAP)) {
$ENCODE_BYTE_MAP=array(); //byte-map-array, empty
$cp1252_map=array( //windows-1252 char re-map information
"\x80"=>"\xE2\x82\xAC", // EURO SIGN
"\x82" => "\xE2\x80\x9A", // SINGLE LOW-9 QUOTATION MARK
"\x83" => "\xC6\x92", // LATIN SMALL LETTER F WITH HOOK
"\x84" => "\xE2\x80\x9E", // DOUBLE LOW-9 QUOTATION MARK
"\x85" => "\xE2\x80\xA6", // HORIZONTAL ELLIPSIS
"\x86" => "\xE2\x80\xA0", // DAGGER
"\x87" => "\xE2\x80\xA1", // DOUBLE DAGGER
"\x88" => "\xCB\x86", // MODIFIER LETTER CIRCUMFLEX ACCENT
"\x89" => "\xE2\x80\xB0", // PER MILLE SIGN
"\x8A" => "\xC5\xA0", // LATIN CAPITAL LETTER S WITH CARON
"\x8B" => "\xE2\x80\xB9", // SINGLE LEFT-POINTING ANGLE QUOTATION
MARK
"\x8C" => "\xC5\x92", // LATIN CAPITAL LIGATURE OE
"\x8E" => "\xC5\xBD", // LATIN CAPITAL LETTER Z WITH CARON
"\x91" => "\xE2\x80\x98", // LEFT SINGLE QUOTATION MARK
"\x92" => "\xE2\x80\x99", // RIGHT SINGLE QUOTATION MARK
"\x93" => "\xE2\x80\x9C", // LEFT DOUBLE QUOTATION MARK
"\x94" => "\xE2\x80\x9D", // RIGHT DOUBLE QUOTATION MARK
"\x95" => "\xE2\x80\xA2", // BULLET
"\x96" => "\xE2\x80\x93", // EN DASH
"\x97" => "\xE2\x80\x94", // EM DASH
"\x98" => "\xCB\x9C", // SMALL TILDE
"\x99" => "\xE2\x84\xA2", // TRADE MARK SIGN
"\x9A" => "\xC5\xA1", // LATIN SMALL LETTER S WITH CARON
"\x9B" => "\xE2\x80\xBA", // SINGLE RIGHT-POINTING ANGLE QUOTATION
MARK
"\x9C" => "\xC5\x93", // LATIN SMALL LIGATURE OE
"\x9E" => "\xC5\xBE", // LATIN SMALL LETTER Z WITH CARON
"\x9F" => "\xC5\xB8" // LATIN CAPITAL LETTER Y WITH DIAERESIS
);
//build the encode_byte_map array keeping the index in incrementing order
for($x=128;$x<256;++$x){
$ch = chr($x); //get the character
if(isset($cp1252_map[$ch])) //look up if its Windows-1252
$ENCODE_BYTE_MAP[$ch] = $cp1252_map[$ch];
else
$ENCODE_BYTE_MAP[$ch]=utf8_encode($ch); //simple conversion
}
}
if(empty($NIBBLE_GOOD_CHARS)) {
$ascii_char='[\x00-\x7F]';
$cont_byte='[\x80-\xBF]';
$utf8_2='[\xC0-\xDF]'.$cont_byte;
$utf8_3='[\xE0-\xEF]'.$cont_byte.'{2}';
$utf8_4='[\xF0-\xF7]'.$cont_byte.'{3}';
$utf8_5='[\xF8-\xFB]'.$cont_byte.'{4}';
//set it took look for any good character combinations repeatedly
$NIBBLE_GOOD_CHARS = "@^(($ascii_char|$utf8_2|$utf8_3|$utf8_4|$utf8_5)+)(.*)$@s";
}
ob_start();
$char='';
$rest='';
while((strlen($instr))>0){
//match all good characters
if(1==preg_match($NIBBLE_GOOD_CHARS,$instr,$match)){
$char=$match[1];
$instr=$match[3];
echo $char;
unset($match);
}
//we can continue with the operations if the string is not empty
if(!empty($instr)) {
//'byting' the string is 30% more efficient than preg('/(.)(.*)/s'
$char=$instr[0];
if(strlen($instr)>1)
$instr=substr($instr,1); //set to remainder of string
else
$instr=''; //set to empty if its done and let the loop terminate
echo $ENCODE_BYTE_MAP[$char];
}
}
$outstr = ob_get_clean();
return $outstr;
}