2008年11月21日
文字コードを取得する方法。
LSLでは、文字コードを得る関数は用意されていないのですが、llStringToBase64()でBase64にエンコードし、llBase64ToInteger()で数値に変換することができます。ところが、llBase64ToInteger()には問題があって、4Byteの数値になる長さ(エンコード状態で6Byte)のBase64文字列以外では正しい結果を返しません。ひらがなの"あ"をエンコードすると"44GC"となり、日本語文字列はうまく6Byteにすることはできません。実際にどういう結果になるか見てみると。
"あ"→"E3818200"
"a"→"6100F612"
といった感じの結果になります。他の文字についても調べてみると、どうやら左詰めで正しい変換結果が入り、余ったバイトには無意味な数値が入っているようです。ということは、余ったバイトは無視して左から必要なバイト数だけ取り出せば問題ないはずです。
SLでの文字コードはUTF-8で、左から順に検査すれば文字コードの長さは求まりますのでこの方法でUTF-8をUCS-2に変換して返す関数を作りました。この関数は一度に一文字しか受け付けませんので、呼び出し元で文字列を一文字ずつ取り出して使用する必要があります。
UTF-8では一文字4byteまで使う可能性があるのですが、この場合3byteまでの変換のみを行っています。4byteUTF-8に対応する場合、もう一行増やす必要があります。現在はUTF-8 3byteを越えるものは32(空白)を返すようになっています。UTF-8 3byteの範囲で、基本的な文字(16bitであらわせる範囲)は含まれていますので、実用上はこれでなんとかなるはずです。JIS第三、第四水準の文字をすべて扱いたいという場合は4byte UTF-8に対応する必要があります。
"あ"→"E3818200"
"a"→"6100F612"
といった感じの結果になります。他の文字についても調べてみると、どうやら左詰めで正しい変換結果が入り、余ったバイトには無意味な数値が入っているようです。ということは、余ったバイトは無視して左から必要なバイト数だけ取り出せば問題ないはずです。
SLでの文字コードはUTF-8で、左から順に検査すれば文字コードの長さは求まりますのでこの方法でUTF-8をUCS-2に変換して返す関数を作りました。この関数は一度に一文字しか受け付けませんので、呼び出し元で文字列を一文字ずつ取り出して使用する必要があります。
integer toUnicode(string c) //Accept one unicode character only.
{
string s= llStringToBase64(c);
integer n= llBase64ToInteger(s);
//
// n contains UTF-8 character code with 'Left to Right order'.
// We accept only 2 byte unicode m so it was only 1 to 3 byte UTF-8.
//
if ((n & 0x80000000) == 0) return ((n & 0x7f000000) >>24);
if ((n & 0xe0000000) == 0xc0000000) return ((n & 0x1f000000) >>18) | ((n & 0x003f0000)>>16);
if ((n & 0xf0000000) == 0xe0000000) return ((n & 0x0f000000) >>12) | ((n & 0x003f0000) >>10) | ((n & 0x00003f00) >>8);
return 32; // else return space code.
}
UTF-8では一文字4byteまで使う可能性があるのですが、この場合3byteまでの変換のみを行っています。4byteUTF-8に対応する場合、もう一行増やす必要があります。現在はUTF-8 3byteを越えるものは32(空白)を返すようになっています。UTF-8 3byteの範囲で、基本的な文字(16bitであらわせる範囲)は含まれていますので、実用上はこれでなんとかなるはずです。JIS第三、第四水準の文字をすべて扱いたいという場合は4byte UTF-8に対応する必要があります。