Initial commit
This commit is contained in:
260
src/main/lua/bit/todo/bit.lua
Normal file
260
src/main/lua/bit/todo/bit.lua
Normal file
@@ -0,0 +1,260 @@
|
||||
--[[---------------
|
||||
LuaBit v0.4
|
||||
-------------------
|
||||
a bitwise operation lib for lua.
|
||||
|
||||
http://luaforge.net/projects/bit/
|
||||
|
||||
How to use:
|
||||
-------------------
|
||||
bit.bnot(n) -- bitwise not (~n)
|
||||
bit.band(m, n) -- bitwise and (m & n)
|
||||
bit.bor(m, n) -- bitwise or (m | n)
|
||||
bit.bxor(m, n) -- bitwise xor (m ^ n)
|
||||
bit.brshift(n, bits) -- right shift (n >> bits)
|
||||
bit.blshift(n, bits) -- left shift (n << bits)
|
||||
bit.blogic_rshift(n, bits) -- logic right shift(zero fill >>>)
|
||||
|
||||
Please note that bit.brshift and bit.blshift only support number within
|
||||
32 bits.
|
||||
|
||||
2 utility functions are provided too:
|
||||
bit.tobits(n) -- convert n into a bit table(which is a 1/0 sequence)
|
||||
-- high bits first
|
||||
bit.tonumb(bit_tbl) -- convert a bit table into a number
|
||||
-------------------
|
||||
|
||||
Under the MIT license.
|
||||
|
||||
copyright(c) 2006~2007 hanzhao (abrash_han@hotmail.com)
|
||||
--]]---------------
|
||||
|
||||
do
|
||||
|
||||
------------------------
|
||||
-- bit lib implementions
|
||||
|
||||
local function check_int(n)
|
||||
-- checking not float
|
||||
if(n - math.floor(n) > 0) then
|
||||
error("trying to use bitwise operation on non-integer!")
|
||||
end
|
||||
end
|
||||
|
||||
local function to_bits(n)
|
||||
check_int(n)
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
return to_bits(bit.bnot(math.abs(n)) + 1)
|
||||
end
|
||||
-- to bits table
|
||||
local tbl = {}
|
||||
local cnt = 1
|
||||
while (n > 0) do
|
||||
local last = math.mod(n,2)
|
||||
if(last == 1) then
|
||||
tbl[cnt] = 1
|
||||
else
|
||||
tbl[cnt] = 0
|
||||
end
|
||||
n = (n-last)/2
|
||||
cnt = cnt + 1
|
||||
end
|
||||
|
||||
return tbl
|
||||
end
|
||||
|
||||
local function tbl_to_number(tbl)
|
||||
local n = table.getn(tbl)
|
||||
|
||||
local rslt = 0
|
||||
local power = 1
|
||||
for i = 1, n do
|
||||
rslt = rslt + tbl[i]*power
|
||||
power = power*2
|
||||
end
|
||||
|
||||
return rslt
|
||||
end
|
||||
|
||||
local function expand(tbl_m, tbl_n)
|
||||
local big = {}
|
||||
local small = {}
|
||||
if(table.getn(tbl_m) > table.getn(tbl_n)) then
|
||||
big = tbl_m
|
||||
small = tbl_n
|
||||
else
|
||||
big = tbl_n
|
||||
small = tbl_m
|
||||
end
|
||||
-- expand small
|
||||
for i = table.getn(small) + 1, table.getn(big) do
|
||||
small[i] = 0
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function bit_or(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
|
||||
for i = 1, rslt do
|
||||
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
|
||||
return tbl_to_number(tbl)
|
||||
end
|
||||
|
||||
local function bit_and(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
|
||||
for i = 1, rslt do
|
||||
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
|
||||
return tbl_to_number(tbl)
|
||||
end
|
||||
|
||||
local function bit_not(n)
|
||||
|
||||
local tbl = to_bits(n)
|
||||
local size = math.max(table.getn(tbl), 32)
|
||||
for i = 1, size do
|
||||
if(tbl[i] == 1) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
return tbl_to_number(tbl)
|
||||
end
|
||||
|
||||
local function bit_xor(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
|
||||
for i = 1, rslt do
|
||||
if(tbl_m[i] ~= tbl_n[i]) then
|
||||
tbl[i] = 1
|
||||
else
|
||||
tbl[i] = 0
|
||||
end
|
||||
end
|
||||
|
||||
--table.foreach(tbl, print)
|
||||
|
||||
return tbl_to_number(tbl)
|
||||
end
|
||||
|
||||
local function bit_rshift(n, bits)
|
||||
check_int(n)
|
||||
|
||||
local high_bit = 0
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
n = bit_not(math.abs(n)) + 1
|
||||
high_bit = 2147483648 -- 0x80000000
|
||||
end
|
||||
|
||||
for i=1, bits do
|
||||
n = n/2
|
||||
n = bit_or(math.floor(n), high_bit)
|
||||
end
|
||||
return math.floor(n)
|
||||
end
|
||||
|
||||
-- logic rightshift assures zero filling shift
|
||||
local function bit_logic_rshift(n, bits)
|
||||
check_int(n)
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
n = bit_not(math.abs(n)) + 1
|
||||
end
|
||||
for i=1, bits do
|
||||
n = n/2
|
||||
end
|
||||
return math.floor(n)
|
||||
end
|
||||
|
||||
local function bit_lshift(n, bits)
|
||||
check_int(n)
|
||||
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
n = bit_not(math.abs(n)) + 1
|
||||
end
|
||||
|
||||
for i=1, bits do
|
||||
n = n*2
|
||||
end
|
||||
return bit_and(n, 4294967295) -- 0xFFFFFFFF
|
||||
end
|
||||
|
||||
local function bit_xor2(m, n)
|
||||
local rhs = bit_or(bit_not(m), bit_not(n))
|
||||
local lhs = bit_or(m, n)
|
||||
local rslt = bit_and(lhs, rhs)
|
||||
return rslt
|
||||
end
|
||||
|
||||
--------------------
|
||||
-- bit lib interface
|
||||
|
||||
bit = {
|
||||
-- bit operations
|
||||
bnot = bit_not,
|
||||
band = bit_and,
|
||||
bor = bit_or,
|
||||
bxor = bit_xor,
|
||||
brshift = bit_rshift,
|
||||
blshift = bit_lshift,
|
||||
bxor2 = bit_xor2,
|
||||
blogic_rshift = bit_logic_rshift,
|
||||
|
||||
-- utility func
|
||||
tobits = to_bits,
|
||||
tonumb = tbl_to_number,
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
--[[
|
||||
for i = 1, 100 do
|
||||
for j = 1, 100 do
|
||||
if(bit.bxor(i, j) ~= bit.bxor2(i, j)) then
|
||||
error("bit.xor failed.")
|
||||
end
|
||||
end
|
||||
end
|
||||
--]]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
95
src/main/lua/bit/todo/hex.lua
Normal file
95
src/main/lua/bit/todo/hex.lua
Normal file
@@ -0,0 +1,95 @@
|
||||
--[[---------------
|
||||
Hex v0.4
|
||||
-------------------
|
||||
Hex conversion lib for lua.
|
||||
|
||||
How to use:
|
||||
hex.to_hex(n) -- convert a number to a hex string
|
||||
hex.to_dec(hex) -- convert a hex string(prefix with '0x' or '0X') to number
|
||||
|
||||
Part of LuaBit(http://luaforge.net/projects/bit/).
|
||||
|
||||
Under the MIT license.
|
||||
|
||||
copyright(c) 2006~2007 hanzhao (abrash_han@hotmail.com)
|
||||
--]]---------------
|
||||
|
||||
require 'bit'
|
||||
|
||||
do
|
||||
|
||||
local function to_hex(n)
|
||||
if(type(n) ~= "number") then
|
||||
error("non-number type passed in.")
|
||||
end
|
||||
|
||||
-- checking not float
|
||||
if(n - math.floor(n) > 0) then
|
||||
error("trying to apply bitwise operation on non-integer!")
|
||||
end
|
||||
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
n = bit.tobits(bit.bnot(math.abs(n)) + 1)
|
||||
n = bit.tonumb(n)
|
||||
end
|
||||
|
||||
hex_tbl = {'A', 'B', 'C', 'D', 'E', 'F'}
|
||||
hex_str = ""
|
||||
|
||||
while(n ~= 0) do
|
||||
last = math.mod(n, 16)
|
||||
if(last < 10) then
|
||||
hex_str = tostring(last) .. hex_str
|
||||
else
|
||||
hex_str = hex_tbl[last-10+1] .. hex_str
|
||||
end
|
||||
n = math.floor(n/16)
|
||||
end
|
||||
if(hex_str == "") then
|
||||
hex_str = "0"
|
||||
end
|
||||
return "0x" .. hex_str
|
||||
end
|
||||
|
||||
local function to_dec(hex)
|
||||
if(type(hex) ~= "string") then
|
||||
error("non-string type passed in.")
|
||||
end
|
||||
|
||||
head = string.sub(hex, 1, 2)
|
||||
|
||||
if( head ~= "0x" and head ~= "0X") then
|
||||
error("wrong hex format, should lead by 0x or 0X.")
|
||||
end
|
||||
|
||||
v = tonumber(string.sub(hex, 3), 16)
|
||||
|
||||
return v;
|
||||
end
|
||||
|
||||
--------------------
|
||||
-- hex lib interface
|
||||
hex = {
|
||||
to_dec = to_dec,
|
||||
to_hex = to_hex,
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
--[[
|
||||
-- test
|
||||
d = 4341688
|
||||
h = to_hex(d)
|
||||
print(h)
|
||||
print(to_dec(h))
|
||||
|
||||
|
||||
for i = 1, 100000 do
|
||||
h = hex.to_hex(i)
|
||||
d = hex.to_dec(h)
|
||||
if(d ~= i) then
|
||||
error("failed " .. i .. ", " .. h)
|
||||
end
|
||||
end
|
||||
--]]
|
||||
332
src/main/lua/bit/todo/noki.lua
Normal file
332
src/main/lua/bit/todo/noki.lua
Normal file
@@ -0,0 +1,332 @@
|
||||
--[[---------------
|
||||
Noki v0.4
|
||||
-------------------
|
||||
Noki is a toolkit to convert Nokia PC Suite backuped SMS to a
|
||||
unicode .txt file, which is more accessible than the original
|
||||
.nfb or .nfc.
|
||||
|
||||
It works well for Nokia PC Suite 6.5.12 and my mobile phone is
|
||||
Nokia 7360. There might be some compatibility problem if you
|
||||
use earlier version of the PC Suite.
|
||||
|
||||
How to use:
|
||||
noki.save_sms('nokia.nfb', 'sms.txt')
|
||||
|
||||
Under the MIT license.
|
||||
|
||||
Noki is a part of LuaBit(http://luaforge.net/projects/bit/).
|
||||
|
||||
copyright(c) 2006~2007 hanzhao (abrash_han@hotmail.com)
|
||||
--]]---------------
|
||||
|
||||
require 'hex'
|
||||
require 'bit'
|
||||
|
||||
do
|
||||
-- globals
|
||||
local RETURN = '\13\0\10\0'
|
||||
local SMS_FILE = '\\MPAPI\\MESSAGES'
|
||||
local SMS_INBOX = 'PIT_MESSAGE_INBOX'
|
||||
local SMS_OUTBOX = 'PIT_MESSAGE_OUTBOX'
|
||||
local SMS_ARCHIVEBOX = 'PIT_MESSAGE_ARCHIVE'
|
||||
|
||||
-- output decorator
|
||||
local SMS_INBOX_DEC = '[INBOX] '
|
||||
local SMS_OUTBOX_DEC = '[OUTBOX] '
|
||||
local SMS_ARCHIVE_DEC = '[ARCHIVE] '
|
||||
|
||||
-- box type
|
||||
local BoxType = {
|
||||
NON = 0,
|
||||
IN = 1,
|
||||
OUT = 2,
|
||||
ARCHIVE = 3,
|
||||
}
|
||||
|
||||
-- feed each char with an extra \0
|
||||
local function asci_to_uni(asci)
|
||||
--print("-------")
|
||||
local uni = ""
|
||||
for i = 1, string.len(asci) do
|
||||
local str = string.format('%c\0', string.byte(asci, i))
|
||||
--print(string.len(str))
|
||||
uni = uni .. str
|
||||
|
||||
end
|
||||
return uni
|
||||
end
|
||||
|
||||
local function asci_padding(asci, pad)
|
||||
local uni = ""
|
||||
for i = 1, string.len(asci) do
|
||||
local str = string.format('%c', string.byte(asci, i))
|
||||
--print(string.len(str))
|
||||
uni = uni .. str .. pad
|
||||
|
||||
end
|
||||
return uni
|
||||
end
|
||||
|
||||
-- shrink the \0 in uni code string
|
||||
local function uni_to_asci(uni)
|
||||
local asci = ''
|
||||
--print('uni len ' .. string.len(uni))
|
||||
for i = 1, string.len(uni), 2 do
|
||||
asci = asci .. string.sub(uni, i, i)
|
||||
end
|
||||
return asci
|
||||
end
|
||||
|
||||
local function reader(str)
|
||||
local index = 1
|
||||
return function (n)
|
||||
--print('reader>>> idx ' .. index .. " n " .. n)
|
||||
local sub = string.sub(str, index, index + n - 1)
|
||||
--[[print(hex.to_hex(string.byte(sub, 1)))
|
||||
print(hex.to_hex(string.byte(sub, 2)))
|
||||
print(hex.to_hex(string.byte(sub, 3)))
|
||||
print(hex.to_hex(string.byte(sub, 4)))
|
||||
--]]
|
||||
index = index + n
|
||||
return sub
|
||||
end
|
||||
end
|
||||
|
||||
local function read_number(read, n)
|
||||
local str = read(n)
|
||||
local rslt = 0
|
||||
for i = 1, n do
|
||||
local v = string.byte(str, i)
|
||||
rslt = bit.bor(rslt, bit.blshift(v, (i-1)*8))
|
||||
end
|
||||
return rslt
|
||||
end
|
||||
|
||||
local function read_int(read)
|
||||
return read_number(read, 4)
|
||||
end
|
||||
|
||||
|
||||
local function read_short(read)
|
||||
return read_number(read, 2)
|
||||
end
|
||||
|
||||
local function read_nfb_string(read)
|
||||
local len = read_int(read)
|
||||
local unistr = read(len*2)
|
||||
return unistr
|
||||
end
|
||||
|
||||
local function read_nfb_header(read)
|
||||
local nfb_header = {
|
||||
ver = read_int(read),
|
||||
firmware = read_nfb_string(read),
|
||||
phone = read_nfb_string(read),
|
||||
entries = read_int(read),
|
||||
}
|
||||
return nfb_header
|
||||
end
|
||||
|
||||
local function read_nfb_file(read)
|
||||
local nfbf = {}
|
||||
nfbf.path = read_nfb_string(read)
|
||||
|
||||
nfbf.nbytes = read_int(read)
|
||||
|
||||
nfbf.bytes = read(nfbf.nbytes)
|
||||
local stamp = read_int(read)
|
||||
|
||||
return nfbf
|
||||
end
|
||||
|
||||
local function read_nfb_dir(read)
|
||||
local nfbd = {
|
||||
path = read_nfb_string(read)
|
||||
}
|
||||
return nfbd
|
||||
end
|
||||
|
||||
local function save_entry(fp, tbl)
|
||||
for k, v in pairs(tbl) do
|
||||
fp:write(v)
|
||||
fp:write(RETURN)
|
||||
end
|
||||
end
|
||||
|
||||
-- save sms entries
|
||||
local function save_sms(fp, ctnt)
|
||||
-- print("save sms ----")
|
||||
local in_box = asci_padding(SMS_INBOX, "%z")
|
||||
local out_box = asci_padding(SMS_OUTBOX, "%z")
|
||||
local archive_box = asci_padding(SMS_ARCHIVEBOX, "%z")
|
||||
local line_s = asci_padding("1020", "%z")
|
||||
local head = asci_padding("1033", "%z")
|
||||
local tail = asci_padding("1040", "%z")
|
||||
local service_center_tail = asci_padding("1080", "%z")
|
||||
local phone_nb = "%+%z%d%z%d%z[%d%z]+" -- default is type 145 with '+'
|
||||
local phone_nb_129 = string.rep("%d%z", 11) -- phone number type 129 without '+'
|
||||
local time = "[%d%z]+%-%z%d%z%d%z%-%z%d%z%d%zT%z%d%z%d%z:%z%d%z%d%z"
|
||||
|
||||
local pattern = "([^\10]+)\13%z\10%z"
|
||||
local line_end = "\13%z\10%z"
|
||||
local lineb, linee = string.find(ctnt, line_end)
|
||||
local start = 1
|
||||
local line_number = 1
|
||||
while(lineb and linee) do
|
||||
local line = string.sub(ctnt, start, lineb - 1)
|
||||
--line = string.sub(ctnt, gb, ge)
|
||||
local type = BoxType.NON
|
||||
--print('capture ' .. string.len(line))
|
||||
--print(uni_to_asci(box))
|
||||
if(string.find(line, in_box)) then
|
||||
fp:write(asci_to_uni(SMS_INBOX_DEC))
|
||||
type = BoxType.IN
|
||||
elseif(string.find(line, out_box)) then
|
||||
fp:write(asci_to_uni(SMS_OUTBOX_DEC))
|
||||
type = BoxType.OUT
|
||||
elseif(string.find(line, archive_box)) then
|
||||
fp:write(asci_to_uni(SMS_ARCHIVE_DEC))
|
||||
type = BoxType.ARCHIVE
|
||||
else
|
||||
--print(uni_to_asci(line))
|
||||
io.close(fp)
|
||||
--error('unknown sms type')
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
hb, he = string.find(line, head)
|
||||
tb, te = string.find(line, tail)
|
||||
|
||||
local first_number = ""
|
||||
-- service center address
|
||||
sb, se = string.find(line, phone_nb, tb)
|
||||
--print("" .. sb .. ", " .. se)
|
||||
if(sb and se) then
|
||||
--print(uni_to_asci(string.sub(line, sb, se)))
|
||||
-- keep the find number, if the second find for sender address fails
|
||||
-- then this number is the sender address
|
||||
first_number = string.sub(line, sb, se)
|
||||
else
|
||||
sb, se = string.find(line, phone_nb_129, tb)
|
||||
if(not (sb and se)) then
|
||||
--io.close(fp)
|
||||
--error("error service center address")
|
||||
--return
|
||||
first_number = "empty number"
|
||||
-- nokia's pc suite may leave the serivce center address empty
|
||||
end
|
||||
end
|
||||
|
||||
-- sender address
|
||||
se_old = se
|
||||
sb, se = string.find(line, phone_nb, se)
|
||||
--print("" .. sb .. ", " .. se)
|
||||
local sender_address = ""
|
||||
if(sb and se) then
|
||||
--print(uni_to_asci(string.sub(line, sb, se)))
|
||||
sender_address = string.sub(line, sb, se)
|
||||
else
|
||||
sb, se = string.find(line, phone_nb_129, se_old)
|
||||
if(not (sb and se)) then
|
||||
--[[
|
||||
print(line_number)
|
||||
io.close(fp)
|
||||
error("error sender address")
|
||||
--]]
|
||||
sender_address = first_number
|
||||
end
|
||||
end
|
||||
-- write sender
|
||||
fp:write(sender_address)
|
||||
fp:write(" \0")
|
||||
|
||||
-- date time
|
||||
-- out box have no date time slot
|
||||
if(type ~= BoxType.OUT and first_number ~= "empty number") then
|
||||
tmb, tme = string.find(line, time, se)
|
||||
--print('' .. tmb .. ", " .. tme)
|
||||
if(tmb and tme) then
|
||||
--print(uni_to_asci(string.sub(line, tmb+1, tme)))
|
||||
else
|
||||
io.close(fp)
|
||||
error("error reading date time")
|
||||
return
|
||||
end
|
||||
fp:write(string.sub(line, tmb+1, tme))
|
||||
end
|
||||
fp:write(RETURN)
|
||||
|
||||
fp:write(string.sub(line, he+3, tb-3))
|
||||
|
||||
fp:write(RETURN)
|
||||
fp:write(RETURN)
|
||||
--end
|
||||
start = linee + 1
|
||||
lineb, linee = string.find(ctnt, line_end, linee)
|
||||
line_number = line_number + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- save sms from a .nfc or .nfb file to a unicode .txt file
|
||||
local function save_nfx_to(from, too)
|
||||
local fp = io.open(too, 'wb')
|
||||
if(not fp) then
|
||||
error("error opening file " .. too .. " to write")
|
||||
return
|
||||
end
|
||||
v = string.format('%c%c', 255, 254)
|
||||
-- unicode .txt 'FF FE'
|
||||
fp:write(v)
|
||||
|
||||
-- read the .nfc file
|
||||
local nokia = io.open(from, 'rb')
|
||||
if(not nokia) then
|
||||
error("error open file " .. from .. " to read")
|
||||
end
|
||||
local ctnt = nokia:read("*a")
|
||||
io.close(nokia)
|
||||
|
||||
local read = reader(ctnt)
|
||||
|
||||
local header = read_nfb_header(read)
|
||||
--print(header.ver)
|
||||
--print(header.entries)
|
||||
|
||||
for i=1, header.entries do
|
||||
--print(i)
|
||||
local type = read_int(read)
|
||||
if(type == 1) then
|
||||
-- file entry
|
||||
--print('file')
|
||||
local fe = read_nfb_file(read)
|
||||
--save_entry(fp, fe)
|
||||
if(uni_to_asci(fe.path) == SMS_FILE) then
|
||||
local smsctnt = fe.bytes
|
||||
--print('sms len ' .. fe.nbytes)
|
||||
save_sms(fp, smsctnt)
|
||||
return
|
||||
end
|
||||
|
||||
elseif(type == 2) then
|
||||
-- dir entry
|
||||
--print('dir')
|
||||
local fd = read_nfb_dir(read)
|
||||
--save_entry(fp, fd)
|
||||
else
|
||||
io.close(fp)
|
||||
error('unknown entry type : ' .. hex.to_hex(type))
|
||||
end
|
||||
end
|
||||
io.close(fp)
|
||||
end
|
||||
|
||||
-- noki interface --
|
||||
noki = {
|
||||
save_sms = save_nfx_to
|
||||
}
|
||||
|
||||
end -- end block
|
||||
|
||||
-- sample
|
||||
-- noki.save_sms('nokia2.nfb', 'sms2.txt')
|
||||
143
src/main/lua/bit/todo/readme.txt
Normal file
143
src/main/lua/bit/todo/readme.txt
Normal file
@@ -0,0 +1,143 @@
|
||||
LuaBit
|
||||
------
|
||||
LuaBit is a bitwise operation lib completely written in Lua. It's
|
||||
written in the belief that Lua is self-contained.
|
||||
|
||||
The supported operations are: not, and, or, xor, right shift, logic
|
||||
right shift and left shift.
|
||||
|
||||
Several utilities are designed to leverage the power of bit operation:
|
||||
1. hex: a dec <-> hex number converter
|
||||
2. utf8: convert utf8 string to ucs2
|
||||
3. noki: convert nokia pc suite backuped SMS file to .txt
|
||||
|
||||
Under the MIT license.
|
||||
|
||||
Visit http://luaforge.net/projects/bit/ to get latest version.
|
||||
|
||||
Status
|
||||
------
|
||||
Now LuaBit is in v0.4.
|
||||
Release date: Mar 18, 2007
|
||||
|
||||
Content
|
||||
-------
|
||||
3 files are there for LuaBit:
|
||||
1) bit.lua
|
||||
is the bitwise operation lib, all operations are implemented here.
|
||||
|
||||
2) hex.lua
|
||||
is a helper lib for ease of using hex numbers with bitwise
|
||||
operation.
|
||||
|
||||
3) noki.lua
|
||||
a utility(based on bit and hex) to convert Nokia PC Suite backuped
|
||||
SMS to a unicode .txt file, which is more accessible than the
|
||||
original .nfb or .nfc file.
|
||||
|
||||
4) utf8.lua
|
||||
convert utf8 string to ucs2 string
|
||||
|
||||
How to use
|
||||
----------
|
||||
Bit
|
||||
---
|
||||
Just require 'bit' in your project and the bit lib will be
|
||||
available:
|
||||
bit.bnot(n) -- bitwise not (~n)
|
||||
bit.band(m, n) -- bitwise and (m & n)
|
||||
bit.bor(m, n) -- bitwise or (m | n)
|
||||
bit.bxor(m, n) -- bitwise xor (m ^ n)
|
||||
bit.brshift(n, bits) -- right shift (n >> bits)
|
||||
bit.blshift(n, bits) -- left shift (n << bits)
|
||||
bit.blogic_rshift(n, bits) -- logic right shift(zero fill >>>)
|
||||
|
||||
Please note that bit.brshift and bit.blshift only support number within
|
||||
32 bits.
|
||||
|
||||
2 utility functions are provided too:
|
||||
bit.tobits(n) -- convert n into a bit table(which is a 1/0 sequence)
|
||||
-- high bits first
|
||||
bit.tonumb(bit_tbl) -- convert a bit table into a number
|
||||
|
||||
Hex
|
||||
---
|
||||
For ease of using hex numbers, a utility hex lib is also included in
|
||||
LuaBit. You can require 'hex' to use them:
|
||||
hex.to_hex(n) -- convert a number to a hex string
|
||||
hex.to_dec(hex) -- convert a hex string(prefix with '0x' or '0X') to number
|
||||
|
||||
With hex, you can write code like:
|
||||
bit.band(258, hex.to_dec('0xFF'))
|
||||
to get the lower 8 bits of 258, that's 2.
|
||||
|
||||
Noki
|
||||
----
|
||||
require 'noki', to save your sms to .txt file:
|
||||
noki.save_sms('nokia.nfb', 'sms.txt')
|
||||
and you can view the output sms.txt in notepad or other editor which
|
||||
support unicode.
|
||||
|
||||
Utf8
|
||||
----
|
||||
require 'utf8', to convert a utf8 string:
|
||||
ucs2_string = utf8.utf_to_uni(utf8_string)
|
||||
|
||||
History
|
||||
-------
|
||||
v0.4
|
||||
* utf8 to ucs2 converter(utf8.lua).
|
||||
* clean up for compatible with Lua5.1 and 5.0.
|
||||
* add 'How to use' section for bit.lua and hex.lua.
|
||||
|
||||
v0.3
|
||||
* noki added as an application of bit.
|
||||
* typo correction.
|
||||
|
||||
v0.2
|
||||
* add logic right shift(>>>) support: bit.blogic_rshift.
|
||||
* add 2 utility functions: bit.tobits and bit.tonumb.
|
||||
* update hex.to_hex(in hex.lua) to support negative number.
|
||||
|
||||
v0.1
|
||||
LuaBit is written when I do my own game project(Fio at http://fio.edithis.info).
|
||||
When loading resources, I have to do some bit operation. And I do not
|
||||
like the embedded way of bit operation. So I decide to implement those
|
||||
ops in lua. And that's LuaBit. It's not as fast as the embedded one, but
|
||||
it works. And Lua is self-contained :-)
|
||||
|
||||
To-Do List
|
||||
---------
|
||||
v0.1
|
||||
It'll be useful if LuaBit support those bitwise op like:
|
||||
bit.band(258, '0xFF')
|
||||
ease to type and use. This will be supported in next release.
|
||||
|
||||
v0.2
|
||||
I decide to delay this feature to later version for it'll mess up the
|
||||
interface of LuaBit.
|
||||
|
||||
v0.3
|
||||
May more utility functions add to Noki - phonebook might be a nice candidate.
|
||||
|
||||
v0.4
|
||||
There's no UCS2 -> UTF8 convertion now, this feature may add in next release
|
||||
or when the project need.
|
||||
|
||||
Noki'll be be exluded from LuaBit in next release; I decide to let Noki grow
|
||||
into a powerful tool to support more Nokia PC Suite backup format(.nfb,
|
||||
.nfc and .nbu).
|
||||
|
||||
Trial Noki demo at http://nokisms.googlepages.com/(in Chinese)
|
||||
|
||||
Known issues
|
||||
------------
|
||||
LuaBit doesn't play very well with negative number. The return value of the
|
||||
bitwise operations might change to positive when applied on negative numbers
|
||||
though the bit sequence is correct. So if you want do some arithmetic with
|
||||
the result of bit operation, be careful.
|
||||
|
||||
Feedback
|
||||
--------
|
||||
Please send your comments, bugs, patches or change request to
|
||||
hanzhao(abrash_han@hotmail.com).
|
||||
163
src/main/lua/bit/todo/utf8.lua
Normal file
163
src/main/lua/bit/todo/utf8.lua
Normal file
@@ -0,0 +1,163 @@
|
||||
--[[---------------
|
||||
Utf8 v0.4
|
||||
-------------------
|
||||
utf8 -> unicode ucs2 converter
|
||||
|
||||
How to use:
|
||||
to convert:
|
||||
ucs2_string = utf8.utf_to_uni(utf8_string)
|
||||
|
||||
to view a string in hex:
|
||||
utf8.print_hex(str)
|
||||
|
||||
Under the MIT license.
|
||||
|
||||
Utf8 is a part of LuaBit Project(http://luaforge.net/projects/bit/).
|
||||
|
||||
copyright(c) 2007 hanzhao (abrash_han@hotmail.com)
|
||||
--]]---------------
|
||||
|
||||
require 'hex'
|
||||
require 'bit'
|
||||
|
||||
do
|
||||
local BYTE_1_HEAD = hex.to_dec('0x00') -- 0### ####
|
||||
local BYTE_2_HEAD = hex.to_dec('0xC0') -- 110# ####
|
||||
local BYTE_3_HEAD = hex.to_dec('0xE0') -- 1110 ####
|
||||
|
||||
-- mask to get the head
|
||||
local BYTE_1_MASK = hex.to_dec('0x80') -- 1### ####
|
||||
local BYTE_2_MASK = hex.to_dec('0xE0') -- 111# ####
|
||||
local BYTE_3_MASK = hex.to_dec('0xF0') -- 1111 ####
|
||||
|
||||
-- tail byte mask
|
||||
local TAIL_MASK = hex.to_dec('0x3F') -- 10## ####
|
||||
|
||||
local mask_tbl = {
|
||||
BYTE_3_MASK,
|
||||
BYTE_2_MASK,
|
||||
BYTE_1_MASK,
|
||||
}
|
||||
local head_tbl = {
|
||||
BYTE_3_HEAD,
|
||||
BYTE_2_HEAD,
|
||||
BYTE_1_HEAD,
|
||||
}
|
||||
|
||||
local len_tbl = {
|
||||
[BYTE_1_HEAD] = 1,
|
||||
[BYTE_2_HEAD] = 2,
|
||||
[BYTE_3_HEAD] = 3,
|
||||
}
|
||||
|
||||
local function utf_read_char(utf, start)
|
||||
local head_byte = string.byte(utf, start)
|
||||
--print('head byte ' .. hex.to_hex(head_byte))
|
||||
for m = 1, table.getn(mask_tbl) do
|
||||
local mask = mask_tbl[m]
|
||||
-- head match
|
||||
local head = bit.band(head_byte, mask)
|
||||
--print('head ' .. hex.to_hex(head) .. ' ' .. hex.to_hex(mask))
|
||||
if(head == head_tbl[m]) then
|
||||
local len = len_tbl[head_tbl[m]]
|
||||
--print('len ' .. len)
|
||||
local tail_idx = start + len - 1
|
||||
local char = 0
|
||||
-- tail
|
||||
for i = tail_idx, start + 1, -1 do
|
||||
local tail_byte = string.byte(utf, i)
|
||||
local byte = bit.band(tail_byte, TAIL_MASK)
|
||||
--print('byte ' .. hex.to_hex(byte).. ' = ' .. hex.to_hex(tail_byte) .. '&'..hex.to_hex(TAIL_MASK))
|
||||
if(tail_idx - i > 0) then
|
||||
local sft = bit.blshift(byte, (tail_idx - i) * 6)
|
||||
--print('shift ' .. hex.to_hex(sft) .. ' ' .. hex.to_hex(byte) .. ' ' .. ((tail_idx - i) * 6))
|
||||
char = bit.bor(char, sft)
|
||||
--print('char ' .. hex.to_hex(char))
|
||||
else
|
||||
char = byte
|
||||
end
|
||||
end -- tails
|
||||
|
||||
-- add head
|
||||
local head_val = bit.band(head_byte, bit.bnot(mask))
|
||||
--print('head val ' .. hex.to_hex(head_val))
|
||||
head_val = bit.blshift(head_val, (len-1) * 6)
|
||||
--print('head val ' .. hex.to_hex(head_val))
|
||||
char = bit.bor(head_val, char)
|
||||
--print('char ' .. hex.to_hex(char))
|
||||
|
||||
return char, len
|
||||
end -- if head match
|
||||
end -- for mask
|
||||
error('not find proper head mask')
|
||||
end
|
||||
|
||||
local function print_hex(str)
|
||||
local cat = ''
|
||||
for i=1, string.len(str) do
|
||||
cat = cat .. ' ' .. hex.to_hex(string.byte(str, i))
|
||||
end
|
||||
print(cat)
|
||||
end
|
||||
|
||||
local HI_MASK = hex.to_dec('0xF0')
|
||||
local LO_MASK = hex.to_dec('0xFF')
|
||||
|
||||
local function char_to_str(char)
|
||||
local hi, lo = bit.brshift(char, 8), bit.band(char, LO_MASK)
|
||||
-- print(hex.to_hex(char)..' '..hex.to_hex(hi)..' ' .. hex.to_hex(lo))
|
||||
if(hi == 0) then
|
||||
return string.format('%c\0', lo)
|
||||
elseif(lo == 0) then
|
||||
return string.format('\0%c', hi)
|
||||
else
|
||||
return string.format('%c%c', lo, hi)
|
||||
end
|
||||
end
|
||||
|
||||
local function utf_to_uni(utf)
|
||||
local n = string.len(utf)
|
||||
local i = 1
|
||||
local uni = ''
|
||||
while(i <= n) do
|
||||
--print('---')
|
||||
char, len = utf_read_char(utf, i)
|
||||
i = i + len
|
||||
--print(string.len(char_to_str(char)))
|
||||
|
||||
uni = uni..char_to_str(char)
|
||||
end
|
||||
--print_hex(uni)
|
||||
return uni
|
||||
end
|
||||
|
||||
-- interface
|
||||
utf8 = {
|
||||
utf_to_uni = utf_to_uni,
|
||||
print_hex = print_hex,
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
--[[
|
||||
-- test
|
||||
byte_3 = string.format('%c%c%c', hex.to_dec('0xE7'), hex.to_dec('0x83'), hex.to_dec('0xad'))
|
||||
print(string.len(byte_3))
|
||||
utf8.utf_to_uni(byte_3)
|
||||
--]]
|
||||
--[[
|
||||
byte_2 = string.format('%c%c', hex.to_dec('0xC2'), hex.to_dec('0x9D'))
|
||||
utf8.utf_to_uni(byte_2)
|
||||
|
||||
byte_1 = string.format('%c', hex.to_dec('0xB'))
|
||||
utf8.utf_to_uni(byte_1)
|
||||
--]]
|
||||
--[[
|
||||
test_mul = string.format(
|
||||
'%c%c%c%c%c%c%c%c%c',
|
||||
hex.to_dec('0xE8'),hex.to_dec('0xAF'), hex.to_dec('0xBA'),
|
||||
hex.to_dec('0xE5'),hex.to_dec('0x9F'), hex.to_dec('0xBA'),
|
||||
hex.to_dec('0xE4'),hex.to_dec('0xBA'), hex.to_dec('0x9A'))
|
||||
|
||||
utf8.print_hex(utf8.utf_to_uni(test_mul))
|
||||
--]]
|
||||
Reference in New Issue
Block a user