Module:Xconv
Jump to navigation
Jump to search
Lua
CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules
The main function in this module is "xconv
", for Template:{{Xconv}}
LUA performs conversions very differently:
- h→d tonumber ( HEXNUM, 16 )
- d→h string.format ( "%X", DECNUM )
An example can be performed with the functions h2d
and d2h
{{#invoke:Xconv|h2d|50FFFF2FFFF0}}<sub>d</sub>
gives 89060428218352d{{#invoke:Xconv|d2h|4096}}<sub>h</sub>
will give 1000h
Code
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].."<sub>h</sub>"
elseif fnc == "2" then return tostring(dect[1]).."<sub>d</sub>"
elseif fnc == "3" then return sp0..dect[1]..sp1..dect[2]..sp1..dect[3]..sp3
elseif fnc == "4" then return "#"..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;