Difference between revisions of "Module:Sandbox/Erutuon/UTF-8"

From blackwiki
Jump to navigation Jump to search
blackwiki>Erutuon
(printing binary digits for characters)
 
m (13 revisions imported)
 
(12 intermediate revisions by 2 users not shown)
Line 5: Line 5:
 
local rshift = bit.rshift
 
local rshift = bit.rshift
  
 +
function table.forEach(t, func)
 +
for i, item in ipairs(t) do
 +
func(item)
 +
end
 +
end
 +
 +
local function setMt(arr)
 +
return setmetatable(arr, { __index =  table })
 +
end
 +
 +
-- Converts a string representing a number in binary base to a Lua number.
 +
local function binary(stringBinary)
 +
return tonumber(stringBinary, 2)
 +
end
 +
 +
-- Find the digit at a certain position in a byte.
 +
local function digitAt(number, index)
 +
if type(number) == "string" then
 +
number = binary(number)
 +
end
 +
return band(rshift(number, 8 - index), 1)
 +
end
 +
 +
-- Returns a table containing bits in a byte, from highest to lowest.
 
local function getBits(byte)
 
local function getBits(byte)
    local t = {}
+
local t = {}
    for bit = 8, 1, -1 do
+
for bit = 8, 1, -1 do
        t[bit] = band(byte, 1)
+
t[bit] = band(byte, 1)
        byte = rshift(byte, 1)
+
byte = rshift(byte, 1)
    end
+
end
    return t
+
return t
 
end
 
end
  
 +
-- mw.log(table.concat(getBits(rshift(binary("11100001"), 8 - 3))))
 +
 +
-- Do something to each byte in a string; put the result in a table.
 
local function iterBytes(str, func)
 
local function iterBytes(str, func)
    local out = {}
+
local out = {}
    for i = 1, #str do
+
for i = 1, #str do
        table.insert(out, func(string.byte(str, i)))
+
table.insert(out, func(string.byte(str, i)))
    end
+
end
    return out
+
return out
 +
end
 +
 
 +
local function makeTag(color)
 +
return { '<span style="color: ' .. color .. ';">', '</span>' }
 +
end
 +
 
 +
-- Find leading digits marking ASCII, leading bytes, or continuation bytes,
 +
-- else tag byte as red.
 +
local function markDigits(byteTable)
 +
local onesCount = 0
 +
setMt(byteTable)
 +
for i, digit in ipairs(byteTable) do
 +
if digit == 1 then
 +
onesCount = onesCount + 1
 +
if onesCount > 4 then
 +
local tag = makeTag("red")
 +
byteTable:insert(#byteTable, tag[2])
 +
byteTable:insert(1, tag[1])
 +
end
 +
else
 +
local tag
 +
-- ASCII (0x00 - 0x7F)
 +
if onesCount == 0 then
 +
tag = makeTag("darkgray")
 +
 +
-- continuation bytes
 +
elseif onesCount == 1 then
 +
tag = makeTag("chocolate")
 +
 +
-- leading bytes
 +
else
 +
tag = makeTag("deeppink")
 +
end
 +
byteTable:insert(i + 1, tag[2])
 +
byteTable:insert(1, tag[1])
 +
return byteTable
 +
end
 +
end
 +
return byteTable
 +
end
 +
 
 +
local function printBytes(str)
 +
return table.concat(
 +
iterBytes(
 +
str,
 +
function(byte)
 +
return table.concat(markDigits(getBits(byte)))
 +
end
 +
),
 +
" "
 +
)
 +
end
 +
 
 +
local function makeCharByteTables(str)
 +
local chars = setMt {}
 +
local bytes = setMt {}
 +
for char in mw.ustring.gmatch(str, ".") do
 +
chars:insert(char)
 +
bytes:insert(printBytes(char))
 +
end
 +
return chars, bytes
 +
end
 +
 
 +
local function print(chars, bytes)
 +
setMt(chars)
 +
setMt(bytes)
 +
local output = setMt { '{| class="wikitable"' }
 +
chars:forEach(
 +
function(char)
 +
output:insert("| " .. char)
 +
end
 +
)
 +
output:insert("|-")
 +
bytes:forEach(
 +
function(byteString)
 +
output:insert("| <code>" .. byteString .. "</code>")
 +
end
 +
)
 +
output:insert("|}")
 +
return output:concat("\n")
 
end
 
end
  
 
function p.show(frame)
 
function p.show(frame)
local str = frame.args[1] or "ᾰ̓τῑμᾰ́ζω"
+
local str = frame.args[1] or "abc πρᾶγμᾰ"
    return table.concat(
+
return print(makeCharByteTables(str))
        iterBytes(
 
            str,
 
            function(byte)
 
                return table.concat(getBits(byte))
 
            end
 
        ),
 
        " "
 
    )
 
 
end
 
end
 +
 +
return p

Latest revision as of 09:45, 27 September 2020

An experiment with printing binary digit representations of characters.

Usage

a ~ ¡ á α 𠀀
01100001 01111110 11000010 10100001 11000011 10100001 11001110 10110001 11100001 10111110 10110000 11110000 10100000 10000000 10000000



local p = {}

local bit = require("bit32")
local band = bit.band
local rshift = bit.rshift

function table.forEach(t, func)
	for i, item in ipairs(t) do
		func(item)
	end
end

local function setMt(arr)
	return setmetatable(arr, { __index =  table })
end

-- Converts a string representing a number in binary base to a Lua number.
local function binary(stringBinary)
	return tonumber(stringBinary, 2)
end

-- Find the digit at a certain position in a byte.
local function digitAt(number, index)
	if type(number) == "string" then
		number = binary(number)
	end
	return band(rshift(number, 8 - index), 1)
end

-- Returns a table containing bits in a byte, from highest to lowest.
local function getBits(byte)
	local t = {}
	for bit = 8, 1, -1 do
		t[bit] = band(byte, 1)
		byte = rshift(byte, 1)
	end
	return t
end

-- mw.log(table.concat(getBits(rshift(binary("11100001"), 8 - 3))))

-- Do something to each byte in a string; put the result in a table.
local function iterBytes(str, func)
	local out = {}
	for i = 1, #str do
		table.insert(out, func(string.byte(str, i)))
	end
	return out
end

local function makeTag(color)
	return { '<span style="color: ' .. color .. ';">', '</span>' }
end

-- Find leading digits marking ASCII, leading bytes, or continuation bytes,
-- else tag byte as red.
local function markDigits(byteTable)
	local onesCount = 0
	setMt(byteTable)
	for i, digit in ipairs(byteTable) do
		if digit == 1 then
			onesCount = onesCount + 1
			if onesCount > 4 then
				local tag = makeTag("red")
				byteTable:insert(#byteTable, tag[2])
				byteTable:insert(1, tag[1])
			end
		else
			local tag
			-- ASCII (0x00 - 0x7F)
			if onesCount == 0 then
				tag = makeTag("darkgray")
			
			-- continuation bytes
			elseif onesCount == 1 then
				tag = makeTag("chocolate")
			
			-- leading bytes
			else
				tag = makeTag("deeppink")
			end
			byteTable:insert(i + 1, tag[2])
			byteTable:insert(1, tag[1])
			return byteTable
		end
	end
	return byteTable
end

local function printBytes(str)
	return table.concat(
		iterBytes(
			str,
			function(byte)
				return table.concat(markDigits(getBits(byte)))
			end
		),
		" "
	)
end

local function makeCharByteTables(str)
	local chars = setMt {}
	local bytes = setMt {}
	for char in mw.ustring.gmatch(str, ".") do
		chars:insert(char)
		bytes:insert(printBytes(char))
	end
	return chars, bytes
end

local function print(chars, bytes)
	setMt(chars)
	setMt(bytes)
	local output = setMt { '{| class="wikitable"' }
	chars:forEach(
		function(char)
			output:insert("| " .. char)
		end
	)
	output:insert("|-")
	bytes:forEach(
		function(byteString)
			output:insert("| <code>" .. byteString .. "</code>")
		end
	)
	output:insert("|}")
	return output:concat("\n")
end

function p.show(frame)
	local str = frame.args[1] or "abc πρᾶγμᾰ"
	return print(makeCharByteTables(str))
end

return p