UWSCでスタックとキュー処理
UWSCには連想配列はあるけど、スタックやキューがない。
スタックは連想配列を使えば簡単なので、スレッドセーフなものを考えてみた。
で、Pushしてから先頭を取り出せば、Queueになるので、Stackモジュールだけど、キューも実装した。
スクリプト
Stack.uws
OPTION EXPLICIT IFB GET_UWSC_NAME = "Stack.uws" THEN DIM i FOR i = 10 TO 21 Stack.Push(i) NEXT PRINT Stack.Dump() PRINT "Stack.Top " + Stack.Top() PRINT "Stack.Pop " + Stack.Pop() PRINT Stack.Dump() Stack.Dispose() Stack.Stack FOR i = 0 TO 9 Stack.Push(i) NEXT FOR i = 10 TO 1034 Stack.Push(i) IF Stack.Top() <> i - 10 THEN PRINT "NG " + i NEXT PRINT Stack.Dump() Stack.Top() Stack.Push(1034) PRINT Stack.Dump() Stack.Dispose() ENDIF MODULE Stack HASHTBL _stack DIM _event = NULL DEF_DLL CloseHandle(DWORD): BOOL: kernel32 DEF_DLL WaitForSingleObject(DWORD,DWORD): DWORD: kernel32 DEF_DLL CreateEventW(DWORD,BOOL,BOOL,wstring): DWORD: kernel32 DEF_DLL SetEvent(DWORD): BOOL: kernel32 CONST WAIT_TIMEOUT = 258 CONST REP_NUM = 1024 PROCEDURE Stack IFB _event = NULL THEN _event = CreateEventW(NULL, FALSE, TRUE, NULL) ENDIF FEND PROCEDURE Dispose() _stack = HASH_REMOVEALL CloseHandle(_event) _event = NULL FEND FUNCTION Wait(timeout=$7FFFFFFF, waitUnit=100) RESULT = WAIT_TIMEOUT WHILE RESULT = WAIT_TIMEOUT AND timeout > 0 RESULT = WaitForSingleObject(_event, waitUnit) timeout = timeout - waitUnit WEND FEND FUNCTION Push(obj) Wait() RESULT = LENGTH(_stack) IF RESULT THEN RESULT = VAL(_stack[RESULT - 1, HASH_KEY]) + 1 _stack[RESULT] = obj SetEvent(_event) FEND FUNCTION Pop(emp=EMPTY) Wait() RESULT = emp DIM key = LENGTH(_stack) IFB key THEN key = _stack[key - 1, HASH_KEY] RESULT = _stack[key] key = _stack[key, HASH_REMOVE] ENDIF SetEvent(_event) FEND FUNCTION Top(emp=EMPTY) Wait() RESULT = emp DIM i, key = LENGTH(_stack) IFB key THEN key = VAL(_stack[0, HASH_KEY]) RESULT = _stack[key] i = _stack[key, HASH_REMOVE] IFB key > REP_NUM THEN HASHTBL tmp FOR i = 0 TO LENGTH(_stack) - 1 tmp[i] = _stack[i, HASH_VAL] NEXT _stack = HASH_REMOVEALL FOR i = 0 TO LENGTH(tmp) - 1 _stack[i] = tmp[i] NEXT ENDIF ENDIF SetEvent(_event) FEND FUNCTION Size() RESULT = LENGTH(_stack) FEND FUNCTION Dump() Wait() RESULT = "Stack Dump<#CR>" DIM i FOR i = 0 TO LENGTH(_stack) - 1 RESULT = RESULT + " " + _stack[i, HASH_KEY] + " : " + _stack[i, HASH_VAL] + "<#CR>" NEXT SetEvent(_event) FEND ENDMODULE
Pushすれば最後に積みます。
Popすると最後を取り出します。
Topすると先頭を取り出します。
Stackを使い終わったら、Dispose。
Dispose後再度使いたい場合は、Stack.Stackを呼んでください。
原理
Pushは、連想配列に0から積むようにしています。
空なら0で積んで、空でない場合は、最後に積んだ番号+1で積む。
Popは、最後を取り出します。
Topは、先頭を取り出しますが、さらに、開始番号が指定数より大きくなったら積みなおしを行います。
(もうちょっと工夫した方が良い気もしますが)
Pop/Topの第一引数は、なかった場合のリターン。
初期EMPTYだけど、スタックにEMPTYを積みたい場合に備えて用意しています。
課題
スタックを一つしかもてません。
複数持ちたい場合、連想配列もどきを使えば良いかと思います。
UWSCで連想配列を配列にする - じゅんじゅんのきまぐれ
各関数が名前を引数にとって、連想配列に連想配列もどきをその名前で入れればOK。