出力文字がやたらと多いescape()
、encodeURI()
、encodeURIComponent()
とかいう組み込み関数があります。出力量を抑えるべく考案された模倣関数を本記事で紹介します。
そもそもなぜ本家3つの関数の排泄文字が多過ぎるのか? それは特定の文字を16進数化する上に、接頭辞%
が付加されるからです。例えばencodeURI("ぁあ")
→%E3%81%81%E3%81%82
といった具合。
該当文字が連続する場合、%
を省略しろと突っ込みたくなります。つまり%E38181E38182
と言う具合にです(区切り文字も必要ですが)。更に言えば、UTF8の16進数列は長過ぎます。
実装編
また下らぬ前置きが短くなってしまったので、とっとと本題のprogramに話題をすり替えます。
%直後の文字 | 意味 |
---|---|
_ 0 - 9 A - F(0-16) | [_0-9A-F][\w][\w]の3つの文字列でUnicode 0 ~ 65535を表現 |
G - W(17-33) | 上記escape終了 |
X(34) | Tab |
Y(35) | 改行 |
Z(36) | 空白 |
a,b,c(37-39) | 上記3つのescape終了 |
d(40) | Unicode 0 - 62 |
e(41) | Unicode 63 - 125 |
f(42) | Unicode 126 - 188 |
g,h,i(43-45) | 上記3つのescape終了 |
/*
EUCe(S,b): 符号化関数
@S :文字列
@b :偽ならescape,2未満ならencodeURI,他はencodeURIComponent風になる
戻り値 :文字列
EUCd(S): 復号関数
@S :文字列
戻り値 :文字列
*/
function EUCe(S,b){
var a=62,c,i=189,j="!#$&'()*+,-./:;=?@~".split(""),A=["_"],B=String.fromCharCode,
E={"*":1,"+":1,"-":1,".":1,"/":1,"@":1},U=[],C={"!":1,"'":1,"(":1,")":1,"*":1,"-":1,".":1,"~":1},W={" ":36,"\n":35," ":34};
for(S=S.split("");a;)E[c=A[a--]=B(a+(a<10?48:a<36?55:61))]=U[c]=C[c]=1;
for(c of j)U[c]=1;
for(j=!1;i>126;)W[B(--i)]=42;
for(;i>63;)W[B(--i)]=41;
for(;i;)W[c=B(--i)]||(W[c]=40);
for(B=!b?E:b<2?U:C,B._=1;c=S[a];j=i)S[a++]=(i=!B[c])?(i==j?"":"%")+(W[c]<37?A[W[c]+(B[S[a]]?3:0)]:W[c]<43?A[W[c]+(B[S[a]]?3:0)]+A[c.charCodeAt(0)%63]:A[(c=c.charCodeAt(0))/3969+(B[S[a]]?17:0)|0]+A[(c/63|0)%63]+A[c%63]):c;
return S.join("")
}
function EUCd(S){
var a=62,b=0,c,e,n,A={_:0},W={X:" ",Y:"\n",Z:" ",a:" ",b:"\n",c:" "},C=String.fromCharCode;
for(S=S.split("");a;)A[C(a+(a<11?47:a<37?54:60))]=a--;
for(;c=S[a++];){
if(c==="%"){e=1;continue}
if(e){
if((n=A[c])<34)c=C(((e=n<17)?n:n-17)*3969+A[S[a++]]*63+A[S[a++]]);
else if(n<40)e=n<37,c=W[c];
else c=C((n-=(e=n<43)?40:43)*63+A[S[a++]])
}S[b++]=c
}S.length=b;
return S.join("")
}
使用例
var a=EUCe("aぁあa"), b=EUCd(a)
console.log(a,b)
実験もどき
See the Pen Improved encode URI by xezz (@xezz) on CodePen.
性能
非常に高速。特に[\x80-\uffff]
の比率が多い程、本家より高速っぽい気がします