Home -> HSP講座 -> HPI編 No.06

どんな型でも受け取ってみせる!

今回は code_getprm() を使ってみます。
これは非常に便利な関数なので、僕はマスターしますt(ry


code_getprmについて復習

第二回でも言いましたが、おさらいです。
code_getprm() 関数は、どんな型の引数でも取得することが出来ます。
取得したデータは、PVal* 型のグローバル変数 mpval に格納されます。
また、この関数の返値から引数の取得状況を取り出すことができ、その値は PARAM_* の定数になります。

#define PARAM_OK       0
#define PARAM_SPLIT    (-1)
#define PARAM_END      (-2)
#define PARAM_DEFAULT  (-3)
#define PARAM_ENDSPLIT (-4)

※引用元は hsp3struct.h。

code_getprm() の戻り値
定数 成敗 備考
PARAM_OK 成功 ---
PARAM_SPLIT 成功 次は PARAM_ENDSPLIT です。
PARAM_END 失敗 引数はもうありません。
PARAM_DEFAULT 失敗 引数が省略されています。
PARAM_ENDSPLIT 失敗 関数で、引数が残っていません。

簡潔にまとめました。

実際に使ってみましょう。


exstrf

C言語でおなじみ、printf()の、書式文字列を返すバージョン exstrf()関数です。
というか、劣化 strf です。
機能は、任意の値 %v 、アドレス %p と、文字コード %c の3つだけです。桁揃えなどは冗長なのでありません。
もちろん可変長引数です。

例によって今回のソースコードを公開しています:「exstrf」リポジトリ


コーディング

いつも流れが同じになってきていますが……。
今回も、exstrf() を処理する関数だけコーディングします。
※実用性は捨てたので、メモリ周りのチェックがありません。

フォーマット指定子(%...)の解析は、長くなったので別の関数に分けました。
ParseFormat は、psResult に次の引数の書式文字列を書き込み、その長さを返す関数です。

exstrf 関数の内容ですが、これはまだ簡単だと思います。
stt_psResult は、refstr と同じサイズの文字列を格納しています。
逆に言うと、これ以上の長さの文字列は連結できませんので、あしからず。( メモリ違反起こしますよ……とほほ )
ループでは、一文字ずつ調べて行き、 % 以外はそのままコピーします。
書式を表す % が見つかった場合は ParseFormat() を呼び出します。

基本的にやっていることは、引数から値を取り出し、それを文字列として psResult に書き込む、という処理です。
%v と他の書式が異なるのは、%p の場合は変数のアドレスを、%c の場合はその値に対応する文字を、代わりに書き込むという点です。
ただし、%% の形式の場合は、単に % を書き込みます。これはいわゆる「エスケープ・シーケンス」の一種ですね。
※書き込み処理の前にバッファサイズの確認をすべきですが、今回は省略しました。

また、ConvertToStr 関数で値を文字列型に型変換をしています。
型変換処理は、組み込み型(label 〜 comobj)とプラグイン拡張型(userdef)で扱いが異なることに注意が必要です。
組み込み型の場合は、HspVarProc::Cnv で他の型の値を HspVarProc の型に変換し、プラグイン拡張型の場合は、HspVarProc::CnvCustom でその型の値を他の型に変換します。
……実際のところ、文字列型に型変換可能なプラグイン拡張型なんて滅多に使わないでしょうけれど、一応。

さて、ざっくりと説明しました。
上記の3つの関数を cmd.cpp として、そのほかは今まで通りです。


ヘッダファイル

いつも通りヘッダファイルを書きます。
今回も手抜き……^^。

// exstrf.hpi - public header

#ifndef IG_EXSTRF_HPI_AS
#define IG_EXSTRF_HPI_AS

#regcmd "_hsp3hpi_init@4", "exstrf.hpi"
#cmd exstrf 0x000

// サンプル・スクリプト
#if 1
	
// %v : 値
// %p : 変数アドレス
// %c : 文字
	
	x = 1 + 2
	mes exstrf( "%v + %v = %v", 1, 2, x )
	mes exstrf( "%vの%vなんて%vで%vさ!", "文字列", "連結", "exstrf", "楽勝" )
	mes exstrf( "%c%c%c%c%c, world%c", 'H', 'e', 'l', 'l', 'o', '!' )
	mes exstrf( "&x = %p = %v", x, varptr(x) )
	
#endif

#endif

大抵の機能を使ってみました。( 命令形式は役に立たない orz )
見ての通り、可変長の引数になっていますね。
引数が足りない場合は、「パラメータの省略は出来ません」、多すぎる場合は、「関数のパラメータ記述が無効です」のエラーになります。


おわりに

今回は code_getprm() を使ってみました。
mpval の扱いさえ分かれば、問題ないでしょう。

では、また次回。


by 上大

第五章へ   第七章へ