LSL:日本語文字列をバイト数で長さ制限

jinko

2009年04月29日 12:06


LOSTのSIM(過去記事は→こちら)に行くのに
ドラマの中でみんながもってるようなリュックを作ってます。



まだスカルプ作っておおまかな形作っただけやけどねー
こういう私物は主に自分で作って自分で使うみたいな遊び方なんですが、
たまにお友達にあげることもあるので、色ぐらいはダイアログで変更できるようにしています。

で、いつもあんまり日本語のこと考えずに作ってたのですが、
この間発見したこちらのページで感激しました。

Second Life 見たこと・聞いたこと [LSL] 文字列のバイト数を調べたい - llDialog

目からうろこです!!

ぼろっって大きなうろこが落ちてきました。

ってことで、日本語を含む文字列のバイト数を調べたり、バイト数で長さを制限したりに挑戦してみました。

* * *


処理の基本的なアイディアに関しては、 参照元の記事をご覧下さい。

あえてポイントをまとめるとすばらしい点が2点もあります。

(1)UTF-8の文字のコードを取得する方法
(2)UTF-8の文字によってバイト長が変化するのをカウントする方法

この記事では以下のように解決しておられました。

(1)UTF-8の文字のコードを取得する方法

LSLの中には、charCodeAt()みたいな文字のコードを取得する関数とかないんですよね。
コードがわからないと日本語処理できないと思い込んでたのですが、

「URLエンコードを使えばいいやん」


というアイディアです。
まったく気がつきませんでした。
英数字のコードは取得できませんが、
目的は日本語部分のコードを取得することですから実用上問題ありません。
すばらしいです!!


(2)UTF-8の文字によってバイト長が変化するのをカウントする方法

元記事にも詳しく説明がありますが、UTF-8は文字によって1バイトから4バイトまで変化します。
普通なら、1文字ずつ長さを調べて足し算していくことを考えると思うのですが、
ここで、またすばらしい提案が!

「'%'をカウントすればいいのよ」

うう・・そんなことまったくきがつかへんかったー

URLエンコードすると、こんな感じになります


文字
URLエンコード結果説明
AA英数字はもとのまま
+%2B%が1つ
×%C3%97%が2つ
あ%E3%81%82%が3つ

%の数と、文字のバイト長が同じってことなんですー
コペルニクス的な発想ですよね!


これらすばらしいアイディアをいただいて、
無謀にもちょっとだけ改造してみました。


//----------------------------------------------------
//  文字のバイト数
//  参考:http://snumaw.blogspot.com/2009/01/lsl-lldialog.html
//----------------------------------------------------
integer strlenB(string str){
    string  esc = llEscapeURL(str);
    string  wk  = llDumpList2String(llParseString2List(esc,["%"],[]),"");
    integer cnt = llStringLength(esc) - llStringLength(wk);
    return llStringLength(esc) - cnt * 2;
}


if文をなくしてみたのですが、いまのところうまく動いてる気がします。



■バイト数で長さを制限

さらにこのアイディアを使ってバイト数で長さを制限に挑戦しようとしたのですが・・・
リストを使った処理が閃かなくて・・・
URLエンコードのアイディアだけいただいてごりごり書いてみました。
関数の名前が、適当なんですけど・・・(substrじゃない気もする)

//----------------------------------------------------
//  バイトで指定した長さ以下の文字列
//  参考:http://snumaw.blogspot.com/2009/01/lsl-lldialog.html
//----------------------------------------------------
string substrB(string str, integer lenB) {
    string  out = "";
    integer cnt = 0;
    integer i   = 0;
    integer n   = llStringLength(str);
    
    for (;i