0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

hspcmp(exe版)のコードを読む 2-2 ~membuf.cpp/.h編~

Last updated at Posted at 2023-06-23

概要

このシリーズは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
    • idxbufInitIndexBufメソッドでメモリを確保されているかどうか。確保されていたら1、確保されていなければ0が代入されます。
  • int *idxbuf
    • 配列的に使われています。
  • int idxmax
    • idxbufが何Byte分確保されているか。
  • int curidx
    • idxbufの最終インデックス番号。いまどれだけidxbufが使われているのかをも示します。

AddIndexBufferメソッド

2種類のコンストラクタがありますが、idxbufを256Byteか指定バイト分で初期化するように引数を取っているだけで、初期化の処理はInitIndexBufメソッドに丸投げしています。

引数(一つ目の方)

なし(void)

コードを見てみる(一つ目の方)

membuf.cpp(328~331行目)
void CMemBuf::AddIndexBuffer( void )
{
	InitIndexBuf( 256 );
}

idxbufを256Byteで初期化することになります。

引数(二つ目の方)

  • int sz
    • idxbufを何Byte確保するか。コンストラクタの時とは違って、指定した分だけそのまま確保されます。

コードを見てみる

membuf.cpp(334~337行目)
void CMemBuf::AddIndexBuffer( int sz )
{
	InitIndexBuf( sz );
}

idxbufszByteで初期化することになります。

InitIndexBufメソッド

引数

  • int sz
    • idxbufを何byte分確保するか。

コードを見てみる

membuf.cpp(41~48行目)
void CMemBuf::InitIndexBuf( int sz )
{
	//	Indexバッファ初期化
	idxflag = 1;
	idxmax = sz;
	curidx = 0;
	idxbuf = (int *)malloc( sizeof(int)*sz );
}

ここでフィールドを初期化しています。それぞれがどの値に初期化されるかはコードを見てください。

デストラクタ

mem_bufidxbufとをfreeを使って解放しています。
(前回のやつで一部紹介しています。)

コードを見てみる

membuf.cpp(315~325行目)
CMemBuf::~CMemBuf( void )
{
	if ( mem_buf != NULL ) {
		free( mem_buf );
		mem_buf = NULL;
	}
	if ( idxbuf != NULL ) {
		free( idxbuf );
		idxbuf = NULL;
	}
}

membufInitMemBufメソッドで、idxbufInitIndexBufメソッドmallocを用いてメモリを確保しておりfreeでメモリを解放する必要があるので、ここでそれをやっていますね。

GetSizeメソッド

curの値を返します。

GetBufferメソッド

mem_bufの値を返します。

GetBufferSizeメソッド

sizeの値を返します。

GetIndexBufferメソッド

idxbufの値を返します。

GetFileNameメソッド

nameの値を返します。

GetIndexメソッド

指定したインデックスの値を返します。指定したインデックスがなければ0が返されます。

引数

  • int idx
    • 指定するインデックス番号

コードを見てみる

membuf.cpp(365~370行目)
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)

コードを見てみる

membuf.cpp(373~377行目)
int CMemBuf::GetIndexBufferSize( void )
{
	if ( idxflag==0 ) return -1;
	return curidx;
}

idxflag0かどうかでidxbufが確保されているかを判断して、確保されていればcuridxの値を返します。
なぜここで返す値がcuridxでよいのかというと、curidxidxflagのポインタの代わりのようなものであり、その値を調べることで現在idxflagが何Byte使われているのかがわかるからです。

SearchIndexValueメソッド

指定した値が登録されているかどうかを調べ、登録されていればidxbufの何番目に登録されているかが、そうでなければ-1が返されます。

引数

  • int val
    • 調べる値

使われている変数

  • int i
    • forの添字。この値が返されます。

コードを見てみる

membuf.cpp(380~388行目)
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の文字数(ヌル文字含む)

コードを見てみる

membuf.cpp(391~398行目)
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の設定をしています。

membuf.cpp(400~406行目)
	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
    • 登録したい値。

コードを見てみる

membuf.cpp(358~362行目)
void CMemBuf::SetIndex( int idx, int val )
{
	if ( idxflag==0 ) return;
	idxbuf[idx] = val;
}

初めにそもそもidxbufが初期化(メモリの確保)がされているかを確認して値(val)をidxbuf[idx]に登録しています。

RegistIndexメソッド

引数で指定した値をidxbufの末尾に追加します。

引数

  • int val

使われている変数

  • int *p
    • これを操作して値を代入する。

コードを見てみる

membuf.cpp(78~91行目)
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++]に登録しています。
そのあと、次に書き込むときにcuridxidxbufのメモリ確保分を超えてしまうかどうかチェックして、超えていたら256Byte追加でidxbufを確保します。

Indexメソッド

引数がcurRegistIndexメソッドを呼び出します。
つまり、curの値を追加します。

IndexExclusiveメソッド

現在のcurの値が登録されているかどうかを確認して、登録されていなければその値をidxbufの末尾に追加します。

引数

なし(void)

コードを見てみる

membuf.cpp(100~105行目)
void CMemBuf::IndexExclusive(void)
{
	if (SearchIndexValue(cur) < 0) {
		RegistIndex(cur);
	}
}

SearchIndexValueメソッドcurの値が登録されているかどうかを確認して、登録されていなければその値をRegistIndexメソッドで登録してます。

ReduceSizeメソッド

新しいcurの値を指定します。

引数

  • int new_cur
    • 新しいcurの値

コードを見てみる

membuf.cpp(288~292行目)
void CMemBuf::ReduceSize( int new_cur )
{
	assert( new_cur >= 0 && new_cur <= cur );
	cur = new_cur;
}

単にcurnew_curを代入するだけです。

PutStrDQメソッド

ダブルクオート内のデータをmem_bufに書き込みます。
執筆時点ではこのメソッドはhspcmp.exe内で使用されていません。

引数
  • char *data
    • mem_bufに書き込むダブルクオート内の文字列。

SaveFileメソッド

mem_bufの内容を指定したファイルに書き出します。
書き出しに成功すればファイルサイズが、失敗すれば-1が返されます。

引数

  • char *fname
    • セーブするときのファイル名

使われている変数

  • FILE *fp
    • ファイルを操作するときに必要な奴。(C#でいうところのStreamに近い)
  • int flen
    • 書き込んだファイルのファイルサイズ。

コードを見てみる

membuf.cpp(409~417行目)
int CMemBuf::SaveFile( char *fname )
{
	FILE *fp;
	int flen;
	fp=fopen(fname,"wb");
	if (fp==NULL) return -1;

ここまででファイルを開いてfpを設定しています。
もしファイルが見つからなかったときは-1を返すようになっています。

membuf.cpp(418~422行目)
	flen = fwrite( mem_buf, 1, cur, fp );
	fclose(fp);
	strcpy( name,fname );
	return flen;
}

ここでファイルfpmem_bufを書き込んで、ファイル操作を終了しています。
そのあとnamefnameをコピーして書き込んだファイルの(実質的に)ファイルサイズを返しています。

次は

次回は、tagstack.cpp/.hを解説します。
hspcmp(exe版)のコードを読む 3 ~tagstack.cpp/.h編~

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?