Module:Sandbox/Erutuon/UTF-8

From blackwiki
< Module:Sandbox‎ | Erutuon
Revision as of 09:45, 17 September 2017 by blackwiki>Erutuon (highlighting non-codepoint parts of encoding)
Jump to navigation Jump to search

An experiment with printing binary digit representations of characters.

Usage

01100001 01111110 11000010 10100001 11000011 10100001 11001110 10110001 11100001 10111110 10110000 11110000 10100000 10000000 10000000

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

-- 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 markDigits(byteTable)
	local tag1 = { '<span style="color: deeppink;>', '</span>' }
	local tag2 = { '<span style="color: chocolate;>', '</span>' }
	local last
	local onesCount = 0
	for i, digit in ipairs(byteTable) do
		if digit == 1 then
			onesCount = onesCount + 1
			last = digit
		else
			local tag
			if onesCount > 1 then
				tag = tag1
			else
				tag = tag2
			end
			table.insert(byteTable, i + 1, tag[2])
			table.insert(byteTable, 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 = {}
	local bytes = {}
	local uLen = mw.ustring.len(str)
	for i = 1, uLen do
		local char = mw.ustring.sub(str, i, i)
		table.insert(chars, char)
		table.insert(bytes, printBytes(char))
	end
	return chars, bytes
end

local function print(chars, bytes)
	local output = { '{| class="wikitable"'}
	for i, char in ipairs(chars) do
		table.insert(output, "| " .. char)
	end
	table.insert(output, "|-")
	for i, byteString in ipairs(bytes) do
		table.insert(output, "| <code>" .. byteString .. "<code>")
	end
	table.insert(output, "|}")
	return table.concat(output, "\n")
end

function p.show(frame)
	local str = frame.args[1] or "ᾰ̓τῑμᾰ́ζω"
	return printBytes(str) .. "\n" .. print(makeCharByteTables(str))
end

return p