IronHSP UTF-16 ワイド文字列型 (wstr) - 設計書

最終更新: 2026-04-11

1. 概要

HSP の変数型に UTF-16 LE ワイド文字列型 wstr (HSPVAR_FLAG_WSTR = 10) を追加する。 既存の文字列関数は第1引数の変数型を見て str/wstr を自動判定し、戻り値も同じ型で返す。

使用例

wsdim ws, 256
ws = L"Unicode文字列"        ; L"..." リテラルで UTF-16 直接代入
ws = "Shift-JIS文字列"       ; str → wstr 自動変換

n = strlen(ws)               ; wstr なので wcslen 動作 → 文字数
s = strmid(ws, 0, 4)         ; wstr → wstr 部分文字列
mes ws                        ; wstr → str 自動変換して表示

#func MessageBoxW "MessageBoxW" int, wstr, wstr, int
MessageBoxW 0, L"本文", L"題名", 0

2. 変数型の定義

ID定数名内部格納basesize
2HSPVAR_FLAG_STRchar* (SJIS or UTF-8)sizeof(char*)
10HSPVAR_FLAG_WSTRwchar_t* (UTF-16 LE)sizeof(wchar_t*)

自動変換ルール

変換方法
str → wstrMultiByteToWideChar(CP_ACP or CP_UTF8)
wstr → strWideCharToMultiByte(CP_ACP or CP_UTF8)
wstr → intwcstol()
wstr → doublewcstod()
int → wstrswprintf(L"%d")
double → wstrswprintf(L"%f")

L"..." リテラル

コンパイラのトークナイザで L" を検出し、ソース文字列を UTF-16 に変換してデータセグメント (DS) に格納。 バイトコードでは新しい即値型 TYPE_WSTR として扱う。

ws = L"Hello"     ; DS に 48 00 65 00 6C 00 6C 00 6F 00 00 00 (UTF-16 LE) を格納
ws = "Hello"      ; DS に "Hello\0" (SJIS/UTF-8) を格納 → ランタイムで wstr に自動変換

3. 命令・関数の対応一覧

以下の全ての命令・関数を wstr 対応にする。第1引数(対象文字列変数)の型が wstr の場合、内部的に wchar_t ベースの処理に切り替える。

3.1 文字列関数 (戻り値あり)

関数対応str 時の動作wstr 時の動作戻り値の型
strlen(s) 型判定 strlen() バイト数 wcslen() 文字数 int
strmid(s, p, n) 型判定 char ベース部分文字列 wchar_t ベース部分文字列 str / wstr (入力と同じ)
instr(s, p, target) 型判定 strstr() wcsstr() int
strtrim(s, n, target) 型判定 char ベーストリミング wchar_t ベーストリミング str / wstr (入力と同じ)
strf(format, ...) 型判定 sprintf() swprintf() str / wstr (format引数と同じ)
getpath(s, type) 型判定 char ベースパス処理 wchar_t ベースパス処理 str / wstr (入力と同じ)
notefind(target, mode) 型判定 char ベース行検索 wchar_t ベース行検索 int
noteinfo(type) 自動 notesel で選択中のバッファ型に応じて自動切替 int / str / wstr

3.2 文字列命令 (戻り値なし)

命令対応str 時の動作wstr 時の動作
strrep s, old, new 型判定 char ベース置換 wchar_t ベース置換
split s, delim, v1, v2... 型判定 char ベース分割 wchar_t ベース分割 → 各変数も wstr
getstr buf, src, offset, delim 型判定 char バッファ読み出し wchar_t バッファ読み出し
strexchange file, mode 対象外 スクリプト置換(ランタイム時は不要)

3.3 ノートパッド命令

notesel で選択した変数が wstr の場合、以降の note 系命令は全て wchar_t ベースで動作する。 改行コードは L"\r\n" (0x000D 0x000A) を使用。

命令対応備考
notesel s 型判定 s が wstr なら以降 wchar モード。内部フラグで記録
noteunsel 自動 フラグをリセット
noteget s, n 型判定 notesel のバッファ型に応じて動作。出力先が str なら自動変換
noteadd s, n, mode 型判定 wstr バッファに wchar_t 行を追加/置換
notedel n 自動 改行文字 (0x000A) で行を判定
noteload file 型判定 wstr バッファの場合: UTF-16 LE ファイルとして読み込み (BOM 自動判定)
notesave file 型判定 wstr バッファの場合: UTF-16 LE + BOM で保存

3.4 変換命令

命令/関数対応備考
cnvstow 拡張 出力先が wstr 変数なら直接代入。従来の byte バッファ方式も互換維持
cnvwtos 拡張 入力が wstr 変数なら直接読み取り。従来の byte バッファ方式も互換維持
cnvstoa 自動 wstr 入力時: UTF-16 → ANSI 変換
cnvatos 自動 wstr 出力時: ANSI → UTF-16 変換

3.5 新規命令・関数

命令/関数説明
wsdim var, len wstr 変数を宣言。len は文字数(バイト数ではない)。内部的に len * 2 + 2 バイト確保
L"..." UTF-16 文字列リテラル。コンパイル時に UTF-16 LE に変換して DS に格納

4. 内部実装

4.1 hspvar_wstr.cpp

既存の hspvar_str.cpp と同様の FlexBuffer 方式。ただし char の代わりに wchar_t を使用。

// 主要関数
HspVarWstr_Cnv()       // str/int/double → wstr 変換
HspVarWstr_CnvCustom() // wstr → str/int/double 変換
HspVarWstr_Set()       // wchar_t* のコピー
HspVarWstr_AddI()      // 文字列結合 (wcscat)
HspVarWstr_GetSize()   // wcslen() * sizeof(wchar_t)

// FlexBuffer: wchar_t* の配列
// pval->pt → wchar_t* (offset 0)
// pval->master → wchar_t*[] (配列要素)

4.2 型判定パターン(既存関数の拡張)

// hsp3int.cpp - strlen の例

case 0x002:  // strlen
{
    int chk = code_get();
    if (chk <= PARAM_END) throw HSPERR_INVALID_FUNCPARAM;

    if (mpval->flag == HSPVAR_FLAG_WSTR) {
        // wstr: 文字数を返す
        wchar_t *ws = (wchar_t *)HspVarCoreCnvPtr(mpval, HSPVAR_FLAG_WSTR);
        reffunc_intfunc_ivalue = (int)wcslen(ws);
    } else {
        // str: バイト数を返す(従来通り)
        char *ss = (char *)HspVarCoreCnvPtr(mpval, HSPVAR_FLAG_STR);
        reffunc_intfunc_ivalue = (int)strlen(ss);
    }
    ptr = &reffunc_intfunc_ivalue;
    break;
}

4.3 L"..." リテラルのコンパイル

// codegen.cpp - トークナイザ

if ((a1 == 'L' || a1 == 'l') && wp[1] == 0x22) {  // L"
    wp += 2;
    Pickstr();  // s3 に SJIS/UTF-8 文字列を取得

    // UTF-16 に変換
    int wlen = MultiByteToWideChar(codepage, 0, (char*)s3, -1, NULL, 0);
    wchar_t *wbuf = new wchar_t[wlen];
    MultiByteToWideChar(codepage, 0, (char*)s3, -1, wbuf, wlen);

    // DS に UTF-16 バイト列を格納
    int dsofs = PutDSBufW(wbuf, wlen * sizeof(wchar_t));
    delete[] wbuf;

    val = dsofs;
    return TK_WSTRING;  // 新トークン型
}

// PutCS で TYPE_WSTR として出力
// ランタイムが DS からワイド文字列ポインタを取得

5. 実装フェーズ

Phase内容対象ファイル状態
1 wstr 変数型 + wsdim + CnvCustom (自動変換) hspvar_wstr.cpp (新規), hspvar_core.h/cpp, hsp3code.cpp 完了
2 L"..." リテラル (PP + CG + RT) token.cpp, token.h, codegen.cpp, hsp3code.cpp 完了
3 文字列関数の型判定分岐 (strlen/strmid/instr/strtrim/getpath) hsp3int.cpp 完了
4 文字列命令の型判定分岐 (strrep/split/getstr) hsp3int.cpp 完了
5 note 系命令の wstr 対応 (notesel/noteget/noteadd/notedel/noteload/notesave/noteinfo/notefind) hsp3int.cpp 完了
6 変換命令 (cnvstow/cnvwtos) — 自動変換で代替可能、既存実装維持 hsp3ext_win.cpp (既存) 完了
strf は現状フォーマット文字列が char ベースのため wstr 非対応。wstr 引数は CnvCustom で自動的に str に変換される。

6. 互換性