UWSCでINIのセクション・キーの一覧を取得する

UWSCのREADINI関数には、セクションやキーの一覧を取得する方法がない。
GetPrivateProfileStringでは、セクションやキーの一覧を取得する方法がある。
キー数可変で動作したい時、この一覧が便利なんですよね。
ということで、モジュールを書いてみた。



スクリプト

Ini.uws

OPTION EXPLICIT

IFB GET_UWSC_NAME = "Ini.uws" THEN
        DIM ss = Ini.Read()
        DIM i, j, ks
        //Ini.Write("sec1", "c", "C")
        FOR i = 0 TO LENGTH(ss) - 1
                PRINT "[" + ss[i] + "]"
                ks = Ini.Read(ss[i])
                FOR j = 0 TO LENGTH(ks) - 1
                        PRINT " " + ks[j] + " = " + Ini.Read(ss[i], ks[j])
                NEXT
        NEXT
        //Ini.Write("sec1", "c", " b")
ENDIF

TEXTBLOCK DummyIni
[sec1]
a = b
b = b
c = b

[sec2]
a = c
b = d

[end]
msg1=以下はスクリプトのため正常に表示されません
msg2=また、今ないセクションや今ない最終セクションのキーを増やすと末尾(TEXTBLOCKの外)に書かれることに注意
ENDTEXTBLOCK



MODULE Ini
        DEF_DLL GetPrivateProfileStringW(wstring,wstring,wstring,var pwchar,dword,wstring):dword:kernel32
        DEF_DLL WritePrivateProfileStringW(wstring,wstring,wstring,wstring):bool:kernel32

        FUNCTION Read(sec=NULL, key=NULL, ini=NULL, def=EMPTY)
                IF ini = NULL THEN ini = GET_CUR_DIR + "\" + GET_UWSC_NAME
                DIM n = 64, buf, r = n, i
                WHILE r >= n - 2
                        n = n * 2
                        buf = FORMAT(CHR(0), n)
                        r = GetPrivateProfileStringW(sec, key, def, buf, n, ini)
                WEND
                RESULT = SPLIT(buf, CHR(0), TRUE)
                IF sec <> NULL AND key <> NULL THEN RESULT = RESULT[0]
        FEND

        FUNCTION Write(sec, key, val, ini=NULL)
                IF ini = NULL THEN ini = GET_CUR_DIR + "\" + GET_UWSC_NAME
                RESULT = WritePrivateProfileStringW(sec, key, val, ini)
        FEND

ENDMODULE

解説

テストコードを読んでくださいな。
セクションが省略(NULL)されると、対象ファイルのセクション一覧SAFEARRAYが取得できます。
キーが省略(NULL)されると、対象セクションのキー一覧SAFEARRAYが取得できます。
セクションとキーが指定されると、値が返ります。
ファイルを省略すると、スクリプトファイル自身となります。


スクリプト中にも書きましたが、存在しないセクションや最後のセクションに存在しないキーを追加しようとすると、ファイルの末尾に追加してしまうことに注意が必要です。
設定をスクリプトファイル自身のTEXTBLOCKに書いている場合、問題となります。


一応、面倒ながら対策はあります。
準備

  1. INI領域用のTEXTBLOCKを、ファイル末尾に置く
  2. ENDTEXTBLOCK部分を「ENDTEXTBLOCK;//=eoi」とする(eoiは何でも良い)


追加手順

  1. 最後のセクション名を取得する
  2. ENDTEXTBLOCKを削除する(Ini.Write("最後のセクション", "ENDTEXTBLOCK;//", NULL))
  3. 追加する
  4. ENDTEXTBLOCKを追加する(Ini.Write("最後のセクション", "ENDTEXTBLOCK;//", "eoi"))
    セクションも追加した場合は、最後のセクションが追加したものになることに注意


もしくは、Ini.Write等ではなく、自前でFOPENして追加するかになります。
、、、その方がきれいか。