概要
このシリーズはHSPの.axファイルの作成をするhspcmpを読んでいくものです。
間違いに気づいた方や、加筆すべきポイントを見つけた人はコメントで指摘してください。
今回はhspcmp(exe版)の最新のコードを読む 2-1 ~membuf.cpp/.h編~の続きになります。
あとここに掲載されたコードは
Hot Soup Processor (HSP) / OpenHSP Copyright (c) 1997-2020, onion software/onitama in collaboration with Sencha, Yume-Yume Yuuka, Y-JINN, chobin, Usuaji, Kenji Yuukoku, puma, tom, sakura, fujidig, zakki, naznyark, Lonely Wolf, Shark++, HyperPageProject, Chokuto, S.Programs, Yuki, K-K, USK, NGND001, yoshis, naka, JET, eller, arue, mjhd_otsuka, tds12 All rights reserved.
から一部改変したものです。
必要に応じて元のコードからインデントを調整したり、空行を省いています。
あと、これは2023/06/23時点のコードになります。
以前別名義で投稿していたものをほぼそのまま再投稿したものです。
またこれらのコードはOpenHSP 3.6のコードに基づいているため、3.6正式版や最新(3.7β)のものと異なる可能性があることに注意してください。
membuf.cpp(membuf.h)
hspcmp.exe内で文字列を扱うためのバッファとして使われています。
また、使い方には大きく分けて以下の3つがあります。
- プリプロセスするファイルの格納
- プリプロセスとコンパイル時のメッセージの格納
- 生成する
.axファイルの格納
今回はこの3つの使い方のうち、主に最後の一つに関係するメソッドを紹介します。
CMemBufクラス
これがmembuf.cpp/hの本体です。
フィールド(一部)
- int idxflag
-
idxbufがInitIndexBufメソッドでメモリを確保されているかどうか。確保されていたら1、確保されていなければ0が代入されます。
-
- int *idxbuf
- 配列的に使われています。
- int idxmax
-
idxbufが何Byte分確保されているか。
-
- int curidx
-
idxbufの最終インデックス番号。いまどれだけidxbufが使われているのかをも示します。
-
AddIndexBufferメソッド
2種類のコンストラクタがありますが、idxbufを256Byteか指定バイト分で初期化するように引数を取っているだけで、初期化の処理はInitIndexBufメソッドに丸投げしています。
引数(一つ目の方)
なし(void)
コードを見てみる(一つ目の方)
void CMemBuf::AddIndexBuffer( void )
{
InitIndexBuf( 256 );
}
idxbufを256Byteで初期化することになります。
引数(二つ目の方)
コードを見てみる
void CMemBuf::AddIndexBuffer( int sz )
{
InitIndexBuf( sz );
}
idxbufをszByteで初期化することになります。
InitIndexBufメソッド
引数
- int sz
-
idxbufを何byte分確保するか。
-
コードを見てみる
void CMemBuf::InitIndexBuf( int sz )
{
// Indexバッファ初期化
idxflag = 1;
idxmax = sz;
curidx = 0;
idxbuf = (int *)malloc( sizeof(int)*sz );
}
ここでフィールドを初期化しています。それぞれがどの値に初期化されるかはコードを見てください。
デストラクタ
mem_bufとidxbufとをfreeを使って解放しています。
(前回のやつで一部紹介しています。)
コードを見てみる
CMemBuf::~CMemBuf( void )
{
if ( mem_buf != NULL ) {
free( mem_buf );
mem_buf = NULL;
}
if ( idxbuf != NULL ) {
free( idxbuf );
idxbuf = NULL;
}
}
membufはInitMemBufメソッドで、idxbufはInitIndexBufメソッドでmallocを用いてメモリを確保しておりfreeでメモリを解放する必要があるので、ここでそれをやっていますね。
GetSizeメソッド
curの値を返します。
GetBufferメソッド
mem_bufの値を返します。
GetBufferSizeメソッド
sizeの値を返します。
GetIndexBufferメソッド
idxbufの値を返します。
GetFileNameメソッド
nameの値を返します。
GetIndexメソッド
指定したインデックスの値を返します。指定したインデックスがなければ0が返されます。
引数
- int idx
- 指定するインデックス番号
コードを見てみる
int CMemBuf::GetIndex( int idx )
{
if ( idxflag==0 ) return 0;
if ((idx < 0) || ( idx>=curidx)) return 0;
return idxbuf[idx];
}
ここでは、idxbufが初期化されているかどうかを判断して指定するインデックスが本当に存在するのかを調べて、なければ0が返され、あればそのインデックスの値(idxbuf[idx])が返されます。
GetIndexBufferSizeメソッド
今idxbufが何Byte使われているかを示します。そもそもidxbufがメモリ確保されていなければ-1が返されます。
引数
なし(void)
コードを見てみる
int CMemBuf::GetIndexBufferSize( void )
{
if ( idxflag==0 ) return -1;
return curidx;
}
idxflagが0かどうかでidxbufが確保されているかを判断して、確保されていればcuridxの値を返します。
なぜここで返す値がcuridxでよいのかというと、curidxはidxflagのポインタの代わりのようなものであり、その値を調べることで現在idxflagが何Byte使われているのかがわかるからです。
SearchIndexValueメソッド
指定した値が登録されているかどうかを調べ、登録されていればidxbufの何番目に登録されているかが、そうでなければ-1が返されます。
引数
- int val
- 調べる値
使われている変数
- int i
-
forの添字。この値が返されます。
-
コードを見てみる
int CMemBuf::SearchIndexValue( int val )
{
int i;
if ( idxflag==0 ) return -1;
for(i=0;i< curidx;i++) {
if ( idxbuf[i] == val ) return i;
}
return -1;
}
初めにそもそもidxbufが初期化(メモリの確保)がされているかを確認し、確保されていなければ-1が返されます。
次にforで全探索して値がヒットすればその時のiの値が、ヒットしなければ-1が返されます。
SearchIndexedDataメソッド
mem_bufの末尾とidexbufの一つを合わせたものと指定した文字が指定したByte分が一致するかどうかを調べます。
一致しなければ-1が、一致すればその時合わせたidexbufの値が返されます。
引数
- char* data
- 調べる文字列
- int size
- 指定するByte数
使われている変数
- int i
-
forで使う添字
-
- int j
- この値が返される。
- int sz
-
sizeか、dataの文字数(ヌル文字含む)
-
コードを見てみる
int CMemBuf::SearchIndexedData(char* data, int size)
{
int i; int j;
int sz = size;
if (idxflag == 0) return -1;
if (sz < 0) sz = (int)strlen(data)+1;
if (sz == 0) return -1;
ここまでで、idxbufの初期化(メモリの確保)がされているかを確認して、変数の定義やszの設定をしています。
j = -1;
for (i = 0; i < curidx; i++) {
char* p = mem_buf + idxbuf[i];
if (memcmp( p, data, sz )==0) j = idxbuf[i];
}
return j;
}
ここでmem_bufのポインタとidexbuf[i]とを合わせたものとdataが、初めからszByte分一致するかどうかを調べます。
一致すればidexbuf[i]を、一致しなければ-1を返します。
SetIndexメソッド
指定したインデックスに指定した値を代入します。
idxbufの最後に登録したいときは、RegistIndexメソッドを使います。
引数
- int idx
- 値を登録したい
idxbufの番号。
- 値を登録したい
- int val
- 登録したい値。
コードを見てみる
void CMemBuf::SetIndex( int idx, int val )
{
if ( idxflag==0 ) return;
idxbuf[idx] = val;
}
初めにそもそもidxbufが初期化(メモリの確保)がされているかを確認して値(val)をidxbuf[idx]に登録しています。
RegistIndexメソッド
引数で指定した値をidxbufの末尾に追加します。
引数
- int val
-
idxbufに追加する値。
-
使われている変数
- int *p
- これを操作して値を代入する。
コードを見てみる
void CMemBuf::RegistIndex( int val )
{
int *p;
if ( idxflag==0 ) return;
idxbuf[ curidx++ ]= val;
if ( curidx >= idxmax ) {
idxmax+=256;
p = (int *)malloc( sizeof(int)*idxmax );
memcpy( p, idxbuf, sizeof(int)*curidx );
free( idxbuf );
idxbuf = p;
}
}
初めにそもそもidxbufが初期化(メモリの確保)がされているかを確認して値(val)をidxbuf[curidx++]に登録しています。
そのあと、次に書き込むときにcuridxがidxbufのメモリ確保分を超えてしまうかどうかチェックして、超えていたら256Byte追加でidxbufを確保します。
Indexメソッド
引数がcurのRegistIndexメソッドを呼び出します。
つまり、curの値を追加します。
IndexExclusiveメソッド
現在のcurの値が登録されているかどうかを確認して、登録されていなければその値をidxbufの末尾に追加します。
引数
なし(void)
コードを見てみる
void CMemBuf::IndexExclusive(void)
{
if (SearchIndexValue(cur) < 0) {
RegistIndex(cur);
}
}
SearchIndexValueメソッドでcurの値が登録されているかどうかを確認して、登録されていなければその値をRegistIndexメソッドで登録してます。
ReduceSizeメソッド
新しいcurの値を指定します。
引数
- int new_cur
- 新しい
curの値
- 新しい
コードを見てみる
void CMemBuf::ReduceSize( int new_cur )
{
assert( new_cur >= 0 && new_cur <= cur );
cur = new_cur;
}
単にcurにnew_curを代入するだけです。
PutStrDQメソッド
ダブルクオート内のデータをmem_bufに書き込みます。
執筆時点ではこのメソッドはhspcmp.exe内で使用されていません。
引数
- char *data
-
mem_bufに書き込むダブルクオート内の文字列。
-
SaveFileメソッド
mem_bufの内容を指定したファイルに書き出します。
書き出しに成功すればファイルサイズが、失敗すれば-1が返されます。
引数
- char *fname
- セーブするときのファイル名
使われている変数
- FILE *fp
- ファイルを操作するときに必要な奴。(C#でいうところの
Streamに近い)
- ファイルを操作するときに必要な奴。(C#でいうところの
- int flen
- 書き込んだファイルのファイルサイズ。
コードを見てみる
int CMemBuf::SaveFile( char *fname )
{
FILE *fp;
int flen;
fp=fopen(fname,"wb");
if (fp==NULL) return -1;
ここまででファイルを開いてfpを設定しています。
もしファイルが見つからなかったときは-1を返すようになっています。
flen = fwrite( mem_buf, 1, cur, fp );
fclose(fp);
strcpy( name,fname );
return flen;
}
ここでファイルfpにmem_bufを書き込んで、ファイル操作を終了しています。
そのあとnameにfnameをコピーして書き込んだファイルの(実質的に)ファイルサイズを返しています。
次は
次回は、tagstack.cpp/.hを解説します。
hspcmp(exe版)のコードを読む 3 ~tagstack.cpp/.h編~