TAD Class は、ファイルやストリームから TAD を 読み書きするのを助ける C++ クラスライブラリです。 生の TAD を解析して、セグメント単位で読み込んだり 書き込んだりできます。
現在は C++ の iostream を対象にしていて、 iostream の使える環境(UNIX,Windows,その他)なら どこでも使えるはずです。
将来的には BTRON1,BTRON3 の 実身(BRealObjTADInputStream,BRealObjTADOutputStream)と トレー(BTrayTADInputStream,BTrayTADOutputStream)を 作成する予定です。
できるかぎりプラットホームに依存しないようにしたつもりです。 私は Linux 上で gcc(egcs-2.90.27) でコンパイルしています。 他の環境でも使えるはずですが、 内部で STL を使用しているため、 STL の使えるコンパイラが必要になります。
ちなみに、Visual C++ 4.0 ではコンパイルできませんでした。 最新バージョンは持っていないので、 コンパイルできるかどうか分からないです。
コンパイルできないコンパイラが多いようでしたら、 ソースのほうで対応するかもしれません。
TAD Class を利用する場合、使用するクラスは
の2種類です。
それ以外には、プログラムで使用するセグメントを 登録するための、BSegMakerRegister,BSubIDSegMakerRegister を 使用しますが、これの使い方は毎回同じなので 決まり文句として使えば良いです。
その他のクラスは直接使うことはまずないでしょう。
BSegment は TAD のセグメントに対応するものです。 全てのセグメントは BSegment を継承しています。
BSegment の主な機能は、
の3種類です。
セグメントはあくまでデータであり、 ストリームとの入出力以外の機能は持たせません。
セグメントにはサブID を持つものもありますが、
サブID が違うと、ほとんど別物と言って良いほど内容が異なるので、
サブID ごとに別クラスとしています。
また、サブID のための機能が BSegment に
入っているので、サブID を持たないセグメントでは
無駄になってしまいますが、まあこのくらいなら良いのでは、と
思っています。
セグメントのデータメンバの多くは public になっています。 これは"セグメントはデータである"という考えに基づくものです。 ただ、複雑なデータ構造の場合は非公開にして get,set 関数を 準備します。
特殊なセグメントとして、BUnknownSeg と BStringSeg があります。
BUnknownSeg はまだ作成されていないセグメントを 処理するためのクラスです。 データ部分を Byte列として扱います。
BStringSeg は、一続きに連続した文字(固定長セグメント)を ひとまとめにしたものです。 本来の TAD には文字列セグメントは存在しませんが、 他のセグメントと同列に扱うために、BStringSeg があります。
BTADInputStream, BTADOutputStream は抽象クラスで、 セグメント(BSegment)単位で読み書きできるストリームです。
定義は次のようになっています。
class BTADInputStream { public: virtual BSegment* getSegment()=0; }; class BTADOutputStream { public: virtual bool putSegment(const BSegment* asegment)=0; };
つまり、BSegment を取り出し、書き込む機能だけです。
BTADInputStream,BTADOutputStream はセグメントの並びですが、 生の TAD である Byte列(Byte ストリーム)を表したものが BByteInputStream,BByteOutputStream です。
BByteInputStream では、データの読み込みだけではなく、 機能も付いています。 BByteInputStream,BByteOutputStream でマシンの エンディアンの違いを吸収しています。
BByteInputStream,BByteOutputStream を継承して
新しい Byte ストリームを作る場合、
BByteInputStream : read_inner(),skip_inner()
BByteOutputStream : write_inner()
をオーバーロードしてください。
他のメソッドはオーバーロードする必要はないです。
BTADInputStream を実装するには Byte ストリーム(BByteInputStream)を解析する必要があります。 iostream、実身、トレーごと別々に 解析プログラムを書くのは無駄ですので、 Byte ストリームの解析をしてくれる補助クラス BTADInputHelper を準備しました。
TAD 解析のほとんどを BTADInputHelper がやってくれるので、 BTADInputStream を継承したクラスでは、 それぞれの特有の機能のプログラムだけに専念できます。
実際、IstreamInputStream では istream 特有の機能は なにもないので、IstreamInputStream では ほとんどなにもやってません。 BRealObjTADInputStream やBTrayTADInputStream では 仮身の扱いを自分でする必要があります。
同様に、BTADOutputStream の実装を助けるために BTADOutputHelper があります。
BTADInputStream では、BByteInputStream から セグメントID,サブID を読み出したところで、 ID に対応する BSegment のサブクラスを インスタンス化する必要があります。
ID を指定するとそれに合うセグメントを生成するクラスは BSegmentMaker と言います。
TAD Class では、グローバル変数 defaultSegMaker が 準備してあり、普通は defaultSegMaker に 使用するセグメントを登録します。
登録作業を楽するために、 BSegMakerRegister,BSubIDSegMakerRegister があります。
例えば、BInfoSeg (ID: TS_INFO, サブID: なし)を登録する場合、
BSegMakerRegister
とします。
独自の BSegmentMaker を作っても良いです。
例えば、myMaker に登録したい場合、
BSegMakerRegister
とします。
実際には、セグメントを生成する作業は BTADInputStream ではなく BTADInputHelper で行なわれています。
現在作成されているセグメントは
だけです。 作成されていないセグメントは BUnknownSeg で処理されます。
画像セグメントや仮身セグメントのような やっかいそうなセグメントは、とりあえず後回しにしてます。
その他のセグメントは必要になったら作ります。 ですから、欲しいセグメントは自分で作成してください。 もしよろしければ、作ったセグメントを私まで送っていただけると ありがたいです。
C++ の iostream を利用する IstreamTADInputStream と OstreamTADInputStream が 作成されています。
将来的には BTRON1,BTRON3 の 実身(BRealObjTADInputStream,BRealObjTADOutputStream)と トレー(BTrayTADInputStream,BTrayTADOutputStream)を 作成する予定です。
TAD Class は次のように使います。
IstreamTADInputStream in(cin); // 標準入力を利用する TADInputStream BSegment* seg=in.getSegment(); // セグメントを1つ読み込みます。 OstreamTADOutputStream out(cout); //標準出力を利用する TADOutputStream out.putSegment(seg); // セグメントをストリームに書き込みます。
文書作成: 落合秀俊 1998年5月3日