UWSCで可変配列

追記 2012/10/05
オブジェクトを作る方法を見つけたので、この記事は不要。
UWSCでオブジェクトを扱う - じゅんじゅんのきまぐれ

いや、そもそも配列は再定義可能だけど、構造体みたいなことをしたい場合を考えて作ってみた。

OPTION EXPLICIT

IFB GET_UWSC_NAME = "Array.uws" THEN
	TextBlock PriceMaster
	名前,path,売価
	a," aaa.bmp",900
	b, bbb.bmp,800
	EndTextBlock

	WITH Array
		DIM name = "PriceMaster"
		.MakeArray(PriceMaster)
		.MakeArray(PriceMaster, TRUE, name)
		PRINT "<#CR>Dump ALL"
		.Dump()
		PRINT "<#CR>Dump " + name
		.Dump(name)
		// 追加
		.Set(2, 0, "c")
		.Set(2, 1, "ccc.bmp")
		.Set(2, 2, "600")
		// 配列表示
		DIM i, j
		PRINT "<#CR>Result"
		FOR i = 0 TO .GetRows() - 1
			FOR j = 0 TO .GetCols() - 1
				PRINT " " + ._def_prefix + "(" + i + "," + j + ")=" + .Get(i, j)
			NEXT
		NEXT
		// 名前表示
		PRINT "<#CR>Result2"
		FOR i = 1 TO .GetRows(name, .Get(0, 0))
			FOR j = 0 TO .GetCols(name) - 1
				PRINT " " + name + "(" + i + "," + .Get(0,j,name) + ")=" + .Get(i,.Get(0,j,name),name)
			NEXT
		NEXT
		// 構造もどき
		name = "Bitmap"
		.Set(0, "name", "a", name)
		.Set(0, "path", "a.bmp", name)
		.Set(0, "x", 10, name)
		.Set(0, "y", 12, name)
		.Set(0, "w", 32, name)
		.Set(0, "h", 32, name)
		.Set(1, "name", "b", name)
		.Set(1, "path", "b.bmp", name)
		.Set(1, "x", 42, name)
		.Set(1, "y", 44, name)
		.Set(1, "w", 16, name)
		.Set(1, "h", 16, name)
		PRINT "<#CR>" + name
		.Dump(name)
	ENDWITH
ENDIF



MODULE Array
	CONST _def_prefix = "Array"
	CONST _sep = ","
	CONST _line_sep = CHR(13)
	HASHTBL _data = HASH_SORT

	FUNCTION GetRows(prefix = _def_prefix, col = 0)
		DIM i, m = LENGTH(_data) - 1, ret = 0, f = FALSE
		DIM suf = _sep + col + _sep, sl = LENGTH(suf)
		FOR i = 0 TO m
			DIM key = _data[i, HASH_KEY], kl = LENGTH(key)
			IFB POS(prefix + _sep, key) = 1 THEN
				IFB POS(suf, key, -1) = kl - sl + 1 THEN
					ret = ret + 1
				ENDIF
				f = TRUE
			ELSEIF f THEN
				BREAK
			ENDIF
		NEXT
		RESULT = ret
	FEND

	FUNCTION GetCols(prefix = _def_prefix, row = 0)
		DIM i, m = LENGTH(_data) - 1, ret = 0, f = FALSE
		FOR i = 0 TO m
			DIM key = _data[i, HASH_KEY]
			IFB POS(prefix + _sep + row + _sep, key) = 1 THEN
				ret = ret + 1
				f = TRUE
			ELSEIF f THEN
				BREAK
			ENDIF
		NEXT
		RESULT = ret
	FEND

	FUNCTION Get(row, col, prefix = _def_prefix)
		DIM ret = EMPTY
		IFB _data[prefix + _sep + row + _sep + col + _sep, HASH_EXISTS] THEN
			ret = _data[prefix + _sep + row + _sep + col + _sep]
		ENDIF
		RESULT = ret
	FEND

	PROCEDURE Remove(prefix = _def_prefix)
		DIM i = 0, m = LENGTH(_data), f = FALSE
		WHILE i < m
			DIM key = _data[i, HASH_KEY]
			IFB POS(prefix + _sep, key) = 1 THEN
				DIM res = _data[key, HASH_REMOVE]
				m = m - 1
				f = TRUE
			ELSEIF f THEN
				BREAK
			ELSE
				i = i + 1
			ENDIF
		WEND
	FEND

	FUNCTION GetTokenLength(data, sep)
		RESULT = (LENGTH(data) - LENGTH(REPLACE(data, sep, "")))
	FEND

	PROCEDURE MakeArray(master, header = FALSE, prefix = _def_prefix, sep = _sep, linesep = _line_sep)
		Remove(prefix)
		DIM strMaster = master, i
		DIM lines = GetTokenLength(strMaster, linesep)
		DIM hs[0], hm
		FOR i = 0 TO lines
			DIM strLine = TOKEN(linesep, strMaster), j
			DIM cols = GetTokenLength(strLine, sep)
			IFB header AND i = 0 THEN
				hm = RESIZE(hs, cols)
			ENDIF
			FOR j = 0 TO cols
				// カンマを含めたい場合は、面倒やね。自作Tokenの必要あり
				DIM data = TRIM(TOKEN(sep, strLine))
				// 前後がダブルクォートならはずす
				IF COPY(data, 1, 1) = "<#DBL>" AND COPY(data, LENGTH(data)) = "<#DBL>" THEN data = COPY(data, 2, LENGTH(data) - 2)
				IFB header AND j <= hm AND i > 0 THEN
					Set(i, hs[j], data, prefix)
				ELSE
					IF header AND i = 0 THEN hs[j] = data
					Set(i, j, data, prefix)
				ENDIF
			NEXT
		NEXT
	FEND

	FUNCTION Set(row, col, data, prefix = _def_prefix)
		RESULT = Get(row, col, prefix)
		_data[prefix + _sep + row + _sep + col + _sep] = data
	FEND

	PROCEDURE Dump(prefix = EMPTY)
		DIM i, m = LENGTH(_data) - 1, f = FALSE
		FOR i = 0 TO m
			DIM key = _data[i, HASH_KEY]
			IFB prefix = EMPTY OR POS(prefix + _sep, key) = 1 THEN
				PRINT key + " = " + _data[i, HASH_VAL]
				f = TRUE
			ELSEIF f THEN
				BREAK
			ENDIF
		NEXT
	FEND
ENDMODULE