文字列の操作に関する、Forth標準ワードのいくつかについて説明する。文字列の操作というよりも、文字列バッファの操作という観点から集めた。文字列用ワード群はオプショナルであり、全ての環境で定義されているとは限らない。

文字列の扱いは環境毎に多様化しているようである。したがって、文字列用として標準となっているワードはごく僅かである。
Mopsでも、基本的クラスライブラリとして、ヒープベースの文字列を扱うStringクラスがあり、その拡張としてString+クラスがあるため、文字列操作は専らオブジェクトにメッセージを送ることで行う。

CMOVE CMOVE>


CMOVEは文字列をバッファにコピーするワードである。パラメターを3つ取り、入力バッファのアドレス、コピー先バッファのアドレス、バイト数の順となる。
CMOVE   ( addr1 addr2  u -- )  \ addr1から始まるバッファのデータを、addr2から始まるバッファにuバイトコピーする。下から上へ
左端(低いアドレス)から順に1バイトずつコピーする。
スタックコメントのuはunsigined(符号なし)数の意味で、正か0の数値ということだが、文字列の場合、これは文字列のバイト長(length)である。
古典的にはlenとも表記する。意味上はlenの方が分り易いと思うが、規格にしたがって、uと表記する。
1文字が1バイトであるという想定から、データをバイト系列として扱って移動するこのワードは文字列用拡張ワードとされているが、データは文字列である必要はない。要するにメモリー上のデータを移動するワードである。

CMOVE>は、内容はCMOVEと同じだが、データは右端(高いアドレス)から順にコピーされる。
CMOVE> ( addr1 addr2  u -- )  \ addr1から始まるバッファのデータを、addr2から始まるバッファにuバイトコピーする。上から下へ

移動順序が違うワードが準備されている理由は、addr1に当たるバッファとaddr2に当たるバッファの領域が重なっている場合について配慮してあるのである。addr2がadd1より低いアドレスにあるときは、CMOVEを用いれば、add2バッファの後ろの端がaddr1にかかるときも全て正しく移動できるし、逆にadd1がaddr2より低いアドレスのときは、CMOVE>を用いれば、add1バッファの後ろの端がaddr2にかかるときも正しく移動できる。もっとも、両バッファが分離されているときには、そのような配慮は不要である。普通はCMOVEを用いる。

MopsではCMOVEのみ定義されている。

MOVE


MOVEは一般のメモリー操作ワードであって、文字列拡張ワードには含まれていないが、文字列のコピーに使えなくはない。入力パラメターはCMOVE等と同じである。
MOVE  ( addr1 addr2 u -- ) \ addr1から始まるバッファのデータを、addr2から始まるバッファにuバイトコピーする。
大きいサイズのデータの場合、一般にはこちらの方が効率が良いようである。また、addr1バッファとaddr2バッファに重なり合う部分があっても、自動的に正しい内容がaddr2バッファにコピーされる(当然だが、重なっている部分のコピー元の文字列は、最後は上書きされてしまうが)。addr1、addr2の位置関係が予めわからず、バッフアが重なっている可能性も否定できない場合には、こちらを使えば良い。

/STRING -TRAILING


/STRINGは、文字列の頭を切除するワードである
/STRING  ( addr1 u1 n -- addr2 u2 ) \ addr1 u1 で指された文字列バッファの左端(addr1に当たる)をn移動し、長さも調整。
nは負でもよい。その場合には、初めの部分を伸ばす操作になる。しかし、もちろん、addr1よりも前の部分も文字列バッファに属していることが前提である。

-TRAILINGは、文字列の終わりに空白文字が続いている場合に、それを切り落とすワードである。
-TRAILING  ( addr1 u1 -- addr2 u2 )
すべて空白文字からなる文字列なら、もちろん、返される長さu2は0である。
このワードはMopsでは定義されていない。

FILL BLANK ERASE


FILLとERASEはコアおよびコアエクステンションワードで、オプショナルではない。

FILLは、メモリーアドレスと長さ、それに文字コードを入力として取り、アドレスと長さで表記されたバッファを同じ文字コードで埋める。
FILL  ( addr u c -- ) \ addrからuバイトをcで満たす
したがって、例えば、
( -- addr len ) CHAR a FILL
とすれば、addrからlenバイト分、小文字のaを(len個:lenバイト分)詰める。

BLANKは、バッファアドレスと長さ(バイト)を入力として取り、そこに半角空白文字を詰める。
BLANK  ( addr u -- )
つまり、BLANKは
32 FILL
と同値である。なお、Mopsでは、BLANKSとして定義されている。

ERASEは、BLANKと同じように、バッファのアドレスとバイト長を取るが、こちらは0を詰める。文字列バッファというよりも、一般にメモリー領域をクリアーするためのワードである。
ERASE ( addr u -- )
0を番兵とする文字列を格納するバッファーなどは、これで消去しておけばよい。文字列だけでなくメモリー領域一般について内容を消去することにも利用できるが、1バイトずつ消すので、領域サイズが大きい場合は、あまり効率は良くない。機能としては、
0 FILL
と同値である。

SEARCH


SEARCHは、2つのaddr len文字列を取り、前の文字列の中に、後の文字列が含まれているかどうかを探すワードである。ヒットした場合、その含まれている部分のaddr lenと、TRUEフラグを返し、ヒットしなかった場合、前の文字列(内部検索された文字列)のaddr lenとFALSEフラグを返す。
SEARCH  ( addr1 u1 addr2 u2 -- addr3 u3 b ) \ addr1 u1文字列の中にaddr2 u2文字列を探す。

Forth環境によって文字列関連の機構は極めて多様である。上のようなforth規格に取り入れられたワードは、比較的多くのforthに共通するものという観点で取られている。
Mopsでは、前にも述べたように、Stringクラスのインスタンスを利用するのが標準であり、通常のワードとしてのSEARCHなどは定義されていない。Mopsの文字列オブジェクトでは、検索には該当部分のアドレスとバイト長を返すのではなく、アクティブパートという機構を用いる。String+クラスのインスタンスを用いれば、大文字小文字を区別する/しないを切り替えて検索できる。

PAD


なお、文字列固有のものではないが、データのバッファーメモリーとして、PADが準備されている。
PAD ( -- addr ) \ データバッファーの先頭アドレスをスタックに置く。
文字列を加工する際に、一時的なストレージとしても利用出来る。PADメモリーの大きさは、規格では最小で84文字分(84バイトか)とされているが、通常はもっと大きく確保されている。iMopsでは512バイトである。なお、PADメモリーはシステムが利用する場合があるので、格納したものは直ちに利用するべきこととされている。プログラムが使用していないからといって、いつまでも同じ内容が保存されていることは保証されない。




最終更新:2019年06月10日 20:14