ActionScriptでPunycode変換

これを移植した。
 
Punycode変換のコードを書いてみました - Operaの備忘録のぺえじ - チーム俺等
http://orera.g.hatena.ne.jp/misttrap/20080518/p1
 

jp/eth0/Punycode.as

package jp.eth0
{
	public class Punycode
	{
		protected static const BASE:int = 36;
		protected static const TMIN:int = 1;
		protected static const TMAX:int = 26;
		protected static const DAMP:int = 700;
		protected static const INITIAL_BIAS:int = 72;
		protected static const INITIAL_N:int = 0x80;
		protected static const DELIMITER:String = '-';

		protected static const ENCODE_TABLE:Array = [
			'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
			'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
			'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
			'4', '5', '6', '7', '8', '9'
		];

		protected static const DECODE_TABLE:Object = {
			'a' :  0, 'A' :  0, 'b' :  1, 'B' :  1, 'c' :  2, 'C' :  2, 'd' :  3, 'D' :  3,
			'e' :  4, 'E' :  4, 'f' :  5, 'F' :  5, 'g' :  6, 'G' :  6, 'h' :  7, 'H' :  7,
			'i' :  8, 'I' :  8, 'j' :  9, 'J' :  9, 'k' : 10, 'K' : 10, 'l' : 11, 'L' : 11,
			'm' : 12, 'M' : 12, 'n' : 13, 'N' : 13, 'o' : 14, 'O' : 14, 'p' : 15, 'P' : 15,
			'q' : 16, 'Q' : 16, 'r' : 17, 'R' : 17, 's' : 18, 'S' : 18, 't' : 19, 'T' : 19,
			'u' : 20, 'U' : 20, 'v' : 21, 'V' : 21, 'w' : 22, 'W' : 22, 'x' : 23, 'X' : 23,
			'y' : 24, 'Y' : 24, 'z' : 25, 'Z' : 25, '0' : 26, '1' : 27, '2' : 28, '3' : 29,
			'4' : 30, '5' : 31, '6' : 32, '7' : 33, '8' : 34, '9' : 35
		};

		/* bias offset */

		protected static const ADAPT_DIV:int   = BASE - TMIN;           // 35
		protected static const ADAPT_LIMIT:int = ADAPT_DIV * TMAX >> 1; // 455

		protected static const ADAPT_TABLE:Array = [ // Math.floor((BASE - TMIN + 1) * delta / (delta + SKEW))
			 0,  0,  1,  2,  3,  4,  4,  5,  6,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12,
			12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 17, 18, 18,
			18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21,
			22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24,
			24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26,
			26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27,
			27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28,
			28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29,
			29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
			29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
			30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
			30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31,
			31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
			31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
			31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
			31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
			32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
			32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
			32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
			32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
			32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33,
			33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
			33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33
		];

		protected static function adapt(delta:int, firstTime:Boolean, numPoints:int):int
		{
			var k:int;
			delta = firstTime ? (delta -  delta % DAMP) / DAMP
							  : (delta - (delta & 1)  ) / 2;
			delta += (delta - delta % numPoints) / numPoints;
			for (k = 0; delta > ADAPT_LIMIT; k += BASE)
				delta = (delta - delta % ADAPT_DIV) / ADAPT_DIV;
			return k + ADAPT_TABLE[delta];
		}

		/* decode */

		public static function decode(input:String):String
		{
			var n:int    = INITIAL_N;
			var i:int    = 0;
			var bias:int = INITIAL_BIAS;

			var b:int = input.lastIndexOf(DELIMITER);
			var output:String = b > 0 ? input.substring(0, b) : '';
			b++;

			var len:int = input.length, h:int = output.length, f:Function = String.fromCharCode;
			while (b < len) {
				var old_i:int = i, w:int = 1, k:int = BASE, kmax:int = bias + TMAX, digit:int, t:int;
				while ((i += (digit = DECODE_TABLE[input.charAt(b++)]) * w) && (
					t = k <= bias ? TMIN : k >= kmax ? TMAX : k - bias
				) <= digit) {
					w *= BASE - t;
					k += BASE;
				}
				bias = adapt(i - old_i, old_i == 0, ++h);
				n += (i - (i %= h)) / h;
				output = output.substring(0, i) + f(n) + output.substring(i++);
			}

			return output;
		}

		/* encode */

		protected static function descend(a:int, b:int):int
		{
			return b - a;
		};

		public static function encode(input:String):String
		{
			var n:int        = INITIAL_N;
			var delta:int    = 0;
			var bias:int     = INITIAL_BIAS;
			var output:Array = [];

			var j:int = 0, len:int = input.length, b:int = 0, f:Function = String.fromCharCode, buf:Array = [], chk:Object = {}, ext:Array = [], c:int = 0;
			while (j < len) {
				var code:int = input.charCodeAt(j);
				code < n ? (
					output[b++] = f(code),
					buf[j++] = 0
				) : chk.hasOwnProperty(code) ? (
					buf[j++] = code
				) : (
					chk[buf[j++] = ext[c++] = code] = null
				);
			}

			var h:int = b;
			if (b) output[b] = DELIMITER;

			for (ext.sort(descend); c; delta++, n++) {
				delta -= (n - (n = ext[--c])) * (h + 1);
				j = 0;
				do switch (buf[j]) {
					case 0 :
						delta++; break;
					case n :
						for (var q:int = delta, k:int = BASE, kmax:int = bias + TMAX, t:int; (
							t = k <= bias ? TMIN : k >= kmax ? TMAX : k - bias
						) <= q; k += BASE) {
							var div:int = BASE - t, mod:int = (q -= t) % div;
							output[output.length] = ENCODE_TABLE[t + mod];
							q = (q - mod) / div;
						}
						output[output.length] = ENCODE_TABLE[q];
						bias = adapt(delta, h == b, ++h);
						buf[j] = delta = 0;
				} while (++j < len);
			}

			return output.join('');
		};
	}
}

 

punycode_test.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%" height="100%"
	xmlns:eth0="jp.eth0.*"
	backgroundGradientColors="[#ffffff, #cccccc]"
	>
	<mx:Script>
		<![CDATA[
			import mx.utils.ObjectUtil;
			import jp.eth0.Punycode;

			public function decode():void
			{
				result.text = Punycode.decode(txt.text);
			}

			public function encode():void
			{
				result.text = Punycode.encode(txt.text);
			}
		]]>
	</mx:Script>

	<mx:VBox>
		<mx:TextInput id="txt" />
		<mx:Button label="Decode" click="{decode()}"/>
		<mx:Button label="Encode" click="{encode()}"/>
		<mx:TextInput id="result" />
	</mx:VBox>
</mx:Application>