いきなりなんだと思った人も多いでしょう。
これはC言語の話ですね。Cでは、文字列を char[] 型 (文字配列型) で扱います。
( C++なら CString があるので楽ですが )
……というわけで、ちょっと懐古主義になって、
strのサポートされているHSPでcharを使えるようにします!!
ん、ややこしいからイラナイ?
まぁそう言わずに (^-^;
今回のソースコード:「char」リポジトリ
以前、変数の操作には HspVarProc 構造体を使うと言いましたね。
この構造体に関数ポインタをセットしてHSPに渡せば、新たな変数型が作れます。
手順はこうです。
サクッと行きましょう、サクッと。
まず、宣言を書きます。
全部列挙すると、こんな感じ。
うぅ、いっぱいありますが……。
大丈夫です。後半はほぼ全部同じですし、いくつかは実装しませんから。
※これらとSet以降の関数以外は、今回は不必要。
ふぅ、1つ1つは難しくなさそうですね。
早速始めましょう!
まず、Alloc()とFree()です。
これらが一番重要なので、最初に書きましょう。
今回の char 型の仕様では、PVal構造体の pt メンバ(char*)をそのまま、char型の配列として使います。
こうすれば、管理もアクセスも簡単ですし、わかりやすいです。
そのため、Alloc()の方では、pt に hspmalloc() で確保したメモリへのポインタを格納しています。
CalcVarSize_Char()は、次のように実装します。
まぁ、見た感じの通りです。
配列の全要素数を計算し、全体に必要なバイト数を返します。
さて、続いて Cnv() と CnvCustom() 関数です。
これがなければ新しい型を使う意味がないですね。
基本的には、double、str、int の3つだけに対応すればいいでしょう。
それ以外の型には変換のしようがないので。
変換後はポインタを返すので、static な変数が型ごとに必要です。
また、char → charの変換も出来るように、一応サポートした方がいい気がします。
HSPVAR_FLAG_CHAR は、HSPVAR_FLAG_INT と同じようなものですが、これは変数です。
そのため、case に指定できません。( case には定数式しか書けないため )
続いて、GetPtr()です。実体は pt が指す領域なので、それへのポインタを返すようにします。
以前言いましたが、pval->offset は APTR 値です。
残りはほぼサンプルのままでいいので、一気に全部いきます。
次に、演算のための関数です。( Set() 以降 )
char 同士の演算は C++ でできるので、基本的にその機能を使います。
※テンプレート関数を使ってまとめたほうがいいですが、難しくなるのでやめておきました。
pdat が左辺、val や in が右辺です。
どれも pdat に計算後の値を格納していますね。
なお、両辺の型は常に一致しています。
g_pHvpChar は、char型のHspVarProc構造体へのポインタです。詳しくは後述。
g_pHvpChar->aftertype は、演算後の値の型です。
例えば、== や > などの比較では、必ず int 型の値を返すので、aftertype メンバに HSPVAR_FLAG_INT をセットしています。
型が変わらず、char型のままの場合、HSPVAR_FLAG_CHAR の代入を省略できるかどうかは分かりません。(おい)
…… だってドキュメントに書いてないんだもーん。
最後に、これらの関数を HspVarProc 構造体にセットする関数が必要です。
ここでは、HspVarChar_Init()とします。これは HspVarProc* を引数に取る関数です。
※ここで代入していない関数を呼び出そうとすると、「サポートされない機能を選択しました」というエラーが起きます。ぬるぽの心配はいりません。
を、それぞれ設定します。version は 0x001 で OK な模様。
support は、HSPVAR_SUPPORT_* という定数を、演算子 | で結合して複数指定します。
#define HSPVAR_SUPPORT_STORAGE 0x0001 // 固定長ストレージサポート #define HSPVAR_SUPPORT_FLEXSTORAGE 0x0002 // 可変長ストレージサポート #define HSPVAR_SUPPORT_FIXEDARRAY 0x0004 // 配列サポート #define HSPVAR_SUPPORT_FLEXARRAY 0x0008 // 可変長配列サポート #define HSPVAR_SUPPORT_ARRAYOBJ 0x0010 // 連想配列サポート #define HSPVAR_SUPPORT_FLEXSIZE 0x0020 // 要素ごとのデータが可変長 #define HSPVAR_SUPPORT_NOCONVERT 0x0040 // 代入時の型変換を無効にする #define HSPVAR_SUPPORT_VARUSE 0x0080 // varuse関数のチェックを有効にする #define HSPVAR_SUPPORT_TEMPVAR 0x0100 // テンポラリ変数として使用する #define HSPVAR_SUPPORT_USER1 0x4000 // ユーザーフラグ1 #define HSPVAR_SUPPORT_USER2 0x8000 // ユーザーフラグ2
※引用元は「hspvar_core.h」。
ここまでの関数を vp_char.cpp に納めて、それのヘッダを書いておきます。
必要なのは HspVarChar_Init() だけなので、それを宣言するだけです。
今回は命令も関数も使わないので、メインのファイルは以下の通りです。
char型を登録する必要があるので、hsp3hpi_init()関数が若干違います。
registvar()関数で、変数型を新たに登録します。
ちなみに、第一引数を -1 ではなく既存の HSPVAR_FLAG_* にすると、HspVarProc を上書きできます。
ふう、ひとまず完成です。長かったですねー……。
さて、いつも通りヘッダファイルを書きますか。
// char - public header #ifndef IG_CHAR_HPI_AS #define IG_CHAR_HPI_AS #regcmd "_hsp3hpi_init@4", "char.hpi", 1 // サンプル・スクリプト #if 1 dimtype c, vartype("char"), 3 // 配列にしてみる c = 'A' // 1 の文字コード mes c // char->str stop #endif #endif
…………。
………………。あれ?
char → strはうまくいっているはずなのに、画面には「64」が……?
と、デバッグウィンドウを見たら、変数 c は int 型になってますね!
そうか、'A' は int なのか。
だから、代入した時点でintに変換されて……。
……というわけで、今の時点では char 型は全くもって無意味です。
ふぅ、どうなるのやら、乞うご期待。
この話は複数回に分けてお送りします。
次回でしっかり char が使えるようになります。大変だ……。
では、また次回。
by 上大