Module:Xconv

local p = {}

-- main function:	for numeric check --	"hex conv"		and selection of conversion mode function p.xconv ( frame ) --	local lprm = frame    --  local parms local gprm = frame.args-- global parms --	local pprm = mw.getCurrentFrame: getParent.args; local inpt = {}; local sndt = {}; local dect = {0, 0, 0}; local tmp = "";	-- temp. work string local err = "";	-- detected error local fna = "";	-- assumed mode local fnc = "";	-- conversion mode local fno = "";	-- output mode local fnr = "";	-- "r" rgb(, "#" 	local num = "";	-- number bytes	local hex = "";	-- number + hex bytes	local nhs = "";	-- number + hex bytes + separator slashes	local rgp = "";	-- empty or 3 rgb % signs	local pts = 0;	-- numbers of decimal points	local sp0 = '('	-- or 'rgb('	local sp1 = ","	-- or "%,"	local sp3 = ")"	-- or "%)"	for i = 1, 3 do		if gprm[i] == nil then gprm[i] = "" end		inpt[i+3] = mw.text.trim( gprm[i] )		inpt[i] = mw.ustring.upper( inpt[i+3] )	end

if inpt[3] ~= "" then fna = "4" -- three parms: 4a (or 3c) else if inpt[2] ~= "" then	-- 		only one param inpt[5] = mw.ustring.gsub( inpt[5], 'r', '' ); if #inpt[2] > #inpt[5] then sp0 = 'rgb(';			end			if		inpt[5] == "n" then fna = "n" -- 1: d2h			elseif	inpt[5] == "h" then fna = "h" -- 2: h2d			elseif	inpt[5] == "o" then fno = "o" -- 3: rgb (3ab or 4bcd)			elseif	inpt[5] == "no" or inpt[5] == "on" then				fna = "n" -- 1: d2h, or 4bcd				fno = "o" -- edit			elseif	inpt[5] == "s" or inpt[5] == "ns" or inpt[5] == "sn" then				fna = "n" -- 4bcd				fno = "s" -- shorten			elseif	inpt[5] == "ho" or inpt[5] == "oh" then				fna = "h" -- 2: h2d, or 3ab				fno = "o" -- edit			elseif	inpt[5] == "%" then				fna = "h" -- rgb (3ab) 				sp1 = "%,"; sp3 = "%)"; else	err = err.."4"	-- parm2 is wrong function code end end if inpt[1] ~= "" then if	mw.ustring.lower( mw.ustring.sub( inpt[4], 1, 4)) == "rgb(" then				fna = "n"	-- 4cd				fnr = "r"	-- rgb				inpt[1] = mw.ustring.sub( inpt[1], 4, #inpt[1] )			end		end	end

if inpt[3] ~= "" then	-- 4a, 3c inpt[1] = inpt[1] .."/".. inpt[2] .."/".. inpt[3] end

for i = 1, #inpt[1] do		tmp = mw.ustring.sub( inpt[1], i, i) --		if tmp >= "0" and tmp <= "9"	then if tmp == "0" or tmp == "1" or tmp == "2" or tmp == "3" or tmp == "4" or tmp == "5" or tmp == "6" or tmp == "7" or tmp == "8" or tmp == "9"	then num = num .. tmp hex = hex .. tmp nhs = nhs .. tmp elseif tmp == "." then	-- fnc = 4d if pts == 0 then num = num .. "."				hex = hex .. "."				nhs = nhs .. "."				pts = 1 else err = err.."5"		--	more than one point end --		elseif tmp >= "A" and tmp <= "F"	then elseif tmp == "A" or tmp == "B" or tmp == "C" or tmp == "D" or tmp == "E" or tmp == "F" then hex = hex .. tmp nhs = nhs .. tmp elseif tmp == " " or tmp == "," or tmp == "-" or tmp == "/" then if mw.ustring.sub( nhs, #nhs, #nhs ) ~= "/" then nhs = nhs .. "/"				pts = 0				--	reset for next item elseif	mw.ustring.sub( inpt[1], i-1, i) ~= ", " then err = err.."3"		--	more than one delimiter in sequ. end elseif tmp == "%" then		-- fnc = 4d if i < #inpt[1]	then inpt[7] = mw.ustring.sub( inpt[1], i+1, i+1)	end if	inpt[7] == ","	or	inpt[7] == ")"	then inpt[7] = "/"	end			if i < #inpt[1]	and	inpt[7] ~= "/"  then				nhs = nhs .. "/"				pts = 0				--	reset for next item			end			rgp = rgp .. "%"		--	3 times			if #rgp > 3 then				err = err.."6"		--	% sign error			end		elseif i == 1 then			if		tmp == "(" then fnr = 'r'			elseif	tmp == "#" then fnr = '#' else err = err.."2"		--	'(' or '#' not first char			end		elseif i == #inpt[1] then			if	tmp == ")" and fnr == 'r' then tmp = tmp	end		--	ignore end-')' when 'r'		elseif	tmp	~= "'"	then	--	ignore spacing separator			err = err.."1"			--	character not identifyable		end -- if	end -- for

if fnr == '#' and err == ""	then if #hex == 3 then		--	3a inpt[6] = mw.ustring.sub( hex, 3, 3)..mw.ustring.sub( hex, 3, 3) inpt[5] = mw.ustring.sub( hex, 2, 2)..mw.ustring.sub( hex, 2, 2) inpt[4] = mw.ustring.sub( hex, 1, 1)..mw.ustring.sub( hex, 1, 1) elseif #hex == 6 then inpt[6] = mw.ustring.sub( hex, 5, 6) inpt[5] = mw.ustring.sub( hex, 3, 4) inpt[4] = mw.ustring.sub( hex, 1, 2) else err = err.."#"	end	-- neither 6 nor 3 for i = 1, 3 do dect[i] = tonumber( inpt[i+3], 16) if sp3 == "%)" then				dect[i] = math.floor( dect[i] / .00255 ) / 1000			end		end	-- for		fnc = "3"			--	3

elseif #num < #hex or fna == "h" then if #nhs == #hex+2 then	--	3bC sndt = mw.text.split( nhs, "/" ) for i = 1, 3 do dect[i] = tonumber( sndt[i], 16) if dect[i] > 255 then err = err.."8" else if sp3 == "%)" then						dect[i] = math.floor( dect[i] / .00255 ) / 1000					end				end				end	-- for			fnc = "3"			--	3 		else			if fnr ~= '#' then				dect[1] = tonumber( hex, 16)				fnc = "2"		--	2 			end		end	else	-- #num == #hex (a numeric value, and not 'h')		if #nhs == #hex then				fnc = "1"			--	1 			inpt[1]	= mw.ustring.format ( "%X", num )		else	-- #nhs == #hex+2 == #num+2 (3 num values) -- 4A,4b or 4c,4d 			dect = mw.text.split( nhs, "/" )	-- 			fnc = "4"			--	4 			for i = 1, 3 do				if rgp == "" then					if tonumber ( dect[i] ) > 255 then -- 4A,4b,4c						err = err.."8"	-- 					end					inpt[i]	= mw.ustring.format ( "%X", dect[i] )				else			--	rgp = "%%%"			--	4d					if rgp ~= "%%%" then						err = err.."7"	-- (6) not three "%"					end					if tonumber ( dect[i] ) > 100 then -- 4d						err = err.."9"	--					end					dect[i+3] = math.floor( 2.55 * dect[i] + .5 )					inpt[i] = mw.ustring.format ( "%X", dect[i+3] ) end	-- if				if #inpt[i] == 1 then inpt[i] = "0"..inpt[i] end end	-- for if fno == "s"		-- shortening required ? and mw.ustring.sub ( inpt[1], 1, 1 ) ==  mw.ustring.sub ( inpt[1], 2, 2 ) and mw.ustring.sub ( inpt[2], 1, 1 ) ==  mw.ustring.sub ( inpt[2], 2, 2 ) and mw.ustring.sub ( inpt[3], 1, 1 ) ==  mw.ustring.sub ( inpt[3], 2, 2 ) then inpt[1] = mw.ustring.sub ( inpt[1], 1, 1 ) inpt[2] = mw.ustring.sub ( inpt[2], 1, 1 ) inpt[3] = mw.ustring.sub ( inpt[3], 1, 1 ) end	-- shorten #rrggbb to #rgb end	-- if #nhs end	-- if #num

--		now errors may be encountered: --			1:	character not numeric/hexa --			2:	'(' or '#' occurs at not first position --			3:	separator (or separator combination} --			4:	parm2 input wrong function code --			5:	decimal point error --			6:	% sign error --			7:	not three "%" --			8:	not all decimal color codes are < 256 --			9:	more than 100% --		'num' contains all numeric bytes --		'hex' contains all numeric plus hexadecimal bytes --		'nhs' contains all numeric plus hexadecimal bytes plus inbetween slashes --		'rgp' may contain three '%' from rgb notation --		dect contains three dec values --		--	if fnc == "4" then --	return "err="..err..", fn="..fna..fnc..fno..fnr..", "..inpt[1].."; "..num.."~"..hex.."~"..nhs.." "..tostring(dect[1]).."'"..tostring(dect[2]).."'"..tostring(dect[3]).." "..rgp.." "..inpt[1].."'"..inpt[2].."'"..inpt[3] --	else --	return "err="..err..", fn="..fna..fnc..fno..fnr..", "..inpt[1].."; "..num.."~"..hex.."~"..nhs.." "..tostring(dect[1]).."'"..tostring(dect[2]).."'"..tostring(dect[3]).." "..rgp;	-- test --	end

if err ~= "" then return "Error = "..err elseif 	fnc == "1" then return inpt[1].."h" elseif 	fnc == "2" then return tostring(dect[1]).."d" elseif 	fnc == "3" then return sp0..dect[1]..sp1..dect[2]..sp1..dect[3]..sp3 elseif 	fnc == "4" then return "&#35;"..inpt[1]..inpt[2]..inpt[3] end

end	-- function xconv

-- hex to decimal value (0 ... FFFFFFFFFFF) function p.h2d ( frame ) local gprm = frame.args	-- global parms return tonumber ( gprm[1], 16 ) end -- function h2d -- hex to decimal value (0 ... 17592186044415) function p.d2h ( frame ) local gprm = frame.args	-- global parms return mw.ustring.format ( "%X", gprm[1] ) end -- function d2h

return p;