RFC3492-compliant encoder
Parameters
$input
stringrequired- UTF-8 encoded string to encode
Source
public static function punycode_encode($input) {
$output = '';
// let n = initial_n
$n = self::BOOTSTRAP_INITIAL_N;
// let delta = 0
$delta = 0;
// let bias = initial_bias
$bias = self::BOOTSTRAP_INITIAL_BIAS;
// let h = b = the number of basic code points in the input
$h = 0;
$b = 0; // see loop
// copy them to the output in order
$codepoints = self::utf8_to_codepoints($input);
$extended = [];
foreach ($codepoints as $char) {
if ($char < 128) {
// Character is valid ASCII
// TODO: this should also check if it's valid for a URL
$output .= chr($char);
$h++;
// Check if the character is non-ASCII, but below initial n
// This never occurs for Punycode, so ignore in coverage
// @codeCoverageIgnoreStart
} elseif ($char < $n) {
throw new Exception('Invalid character', 'idna.character_outside_domain', $char);
// @codeCoverageIgnoreEnd
} else {
$extended[$char] = true;
}
}
$extended = array_keys($extended);
sort($extended);
$b = $h;
// [copy them] followed by a delimiter if b > 0
if (strlen($output) > 0) {
$output .= '-';
}
// {if the input contains a non-basic code point < n then fail}
// while h < length(input) do begin
$codepointcount = count($codepoints);
while ($h < $codepointcount) {
// let m = the minimum code point >= n in the input
$m = array_shift($extended);
//printf('next code point to insert is %s' . PHP_EOL, dechex($m));
// let delta = delta + (m - n) * (h + 1), fail on overflow
$delta += ($m - $n) * ($h + 1);
// let n = m
$n = $m;
// for each code point c in the input (in order) do begin
for ($num = 0; $num < $codepointcount; $num++) {
$c = $codepoints[$num];
// if c < n then increment delta, fail on overflow
if ($c < $n) {
$delta++;
} elseif ($c === $n) { // if c == n then begin
// let q = delta
$q = $delta;
// for k = base to infinity in steps of base do begin
for ($k = self::BOOTSTRAP_BASE; ; $k += self::BOOTSTRAP_BASE) {
// let t = tmin if k <= bias {+ tmin}, or
// tmax if k >= bias + tmax, or k - bias otherwise
if ($k <= ($bias + self::BOOTSTRAP_TMIN)) {
$t = self::BOOTSTRAP_TMIN;
} elseif ($k >= ($bias + self::BOOTSTRAP_TMAX)) {
$t = self::BOOTSTRAP_TMAX;
} else {
$t = $k - $bias;
}
// if q < t then break
if ($q < $t) {
break;
}
// output the code point for digit t + ((q - t) mod (base - t))
$digit = (int) ($t + (($q - $t) % (self::BOOTSTRAP_BASE - $t)));
$output .= self::digit_to_char($digit);
// let q = (q - t) div (base - t)
$q = (int) floor(($q - $t) / (self::BOOTSTRAP_BASE - $t));
} // end
// output the code point for digit q
$output .= self::digit_to_char($q);
// let bias = adapt(delta, h + 1, test h equals b?)
$bias = self::adapt($delta, $h + 1, $h === $b);
// let delta = 0
$delta = 0;
// increment h
$h++;
} // end
} // end
// increment delta and n
$delta++;
$n++;
} // end
return $output;
}
User Contributed Notes
You must log in before being able to contribute a note or feedback.