第2回エンペディア大賞」が2月いっぱい開催中です。2024年に作成された記事の中から、お気に入りの記事に投票しましょう!

モジュール:TSV

出典: 謎の百科事典もどき『エンペディア(Enpedia)』
ナビゲーションに移動 検索に移動

ここに呼び出す説明文 『 モジュール:TSV/doc 』 が作成されていません。

local p = {}

function p.toArr2D(args)
	local tsv = args[1]
	if tsv == nil then return {} end
	local maxStep = args.maxStep or 1000 -- 最大セル解釈数
	
	local tbl = {}
	local row = {}
	
	-- パフォーマンス最適化のため変数宣言をfor文の外に
	local start = nil -- セル内容の開始idx
	local stop = nil -- セル内容の終了idx
	local startDQ = 0
	local stopDQ = 0
	local isLf = false
	local isDQBegin = false
	local isDQSpace = false -- ダブルクォートで囲まれたセルか否か
	local cellTxt = ''
	local tabPos = 0
	
	local cursor = 1
	local cursorDQ = 1
	for i = 1, maxStep do -- maxStepステップ以上のループ拒否
		start = nil
		stop = nil
		isLf = false
		isDQBegin = false
		isDQSpace = false
		
		-- 開始時のダブルクォートらの塊が偶数・奇数のどちらか、判定
		startDQ, stopDQ = tsv:find('^"+', cursor)
		if startDQ ~= nil and startDQ == cursor then
			isDQBegin = (stopDQ - startDQ + 1) % 2 == 1
		end
		
		if isDQBegin then
			cursorDQ = stopDQ + 1
			-- 次のタブの位置を予め把握
			tabPos = tsv:find('\t', cursorDQ, true)
			-- ~ 奇数個ある終了ダブルクォート塊 (タブ|改行)  を検索
			for j = 1, maxStep do
				startDQ, stopDQ = tsv:find('"-[\t\n]', cursorDQ)
				if startDQ > tabPos then break end -- タブ優先
				if startDQ ~= nil and (stopDQ - startDQ) % 2 == 1 then -- マッチ
					start = cursor + 1
					stop = stopDQ - 2
					cursor = stopDQ + 1
					if tsv:sub(stopDQ, stopDQ) == '\n' then isLf = true end
					isDQSpace = true
					break
				end
				if startDQ == nil then
					startDQ, stopDQ = tsv:find('"-$', cursorDQ)
					if startDQ == nil then break end -- 終了塊に最後まで出会わなければbreak
					if startDQ ~= nil and (stopDQ - startDQ + 1) % 2 == 1 then -- マッチ
						start = cursor + 1
						stop = stopDQ - 1
						cursor = stopDQ + 1
						isLf = true
						isDQSpace = true
						break
					end
				end
				cursorDQ = stopDQ + 1
			end
		end
		
		if start == nil then
			-- ~ (改行|タブ)  にマッチ
			start, stop = tsv:find('.-[\n\t]', cursor)
			if start ~= nil then
				cursor = stop + 1
				isLf =  tsv:sub(stop, stop) == '\n'
				stop = stop - 1
			else -- 何にもマッチしない
				start = cursor
				cursor = #tsv + 1
				isLf = true
				stop = cursor - 1
			end
		end
		
		-- セル内容を取得し、列に追加
		cellTxt = tsv:sub(start, stop)
		if isDQSpace then cellTxt = cellTxt:gsub('""', '"') end
		table.insert(row, cellTxt)
		if isLf then -- 次列へ
			table.insert(tbl, row)
			row = {}
		end
		
		if #tsv < cursor then break end
	end
	return tbl
end

return p