-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstrings.lua
122 lines (107 loc) · 2.54 KB
/
strings.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
local strings = {}
local bit = require("bit")
local io = require("io")
local oo = require("oo")
local band = bit.band
local rshift = bit.rshift
local lshift = bit.lshift
local Bits = oo.Class("bit")
function Bits:init(reader)
self._reader = reader
self._bits = 0
self._size = 0
end
function Bits:read1()
if self._size == 0 then
self._bits = self._reader:read8()
self._size = 8
end
local b = band(self._bits, 1)
self._bits = rshift(self._bits, 1)
self._size = self._size - 1
return b
end
function strings.putNum(n)
io.write(n)
end
function strings.putChar(c)
if c > 127 then
io.write(string.format("0x%x", c))
else
io.write(string.char(c))
end
end
local function putCString(r)
local c = r:read8()
while c ~= 0 do
strings.putChar(c)
c = r:read8()
end
end
local function putUnicodeString(r)
r:setAddr(r:addr() + 3)
local c = r:read32()
while c ~= 0 do
strings.putChar(c)
c = r:read32()
end
end
local BRANCH_NODE = 0
local END_NODE = 1
local CHAR_NODE = 2
local STRING_NODE = 3
local UNICHAR_NODE = 4
local UNISTRING_MODE = 5
local REF_NODE = 8
local DOUBLE_REF_NODE =9
local REF_ARGS_NODE = 10
local DOUBLE_REF_ARGS_NODE = 11
local function putCompressedString(vm, r)
local bits = Bits(r)
local table = vm:reader(vm.stringTable)
local length = table:read32() -- Number of entries in the table
local count = table:read32() -- Size of the table in bytes
local root = table:read32() -- Address of the root node
while true do
local node = vm:reader(root)
local kind = node:read8()
while kind == BRANCH_NODE do
local addr = node:read32()
if bits:read1() == 1 then
addr = node:read32()
end
node:setAddr(addr)
kind = node:read8()
end
if kind == END_NODE then
return
elseif kind == CHAR_NODE then
strings.putChar(node:read8())
elseif kind == STRING_NODE then
putCString(node)
elseif kind == UNICHAR_NODE then
strings.putChar(node:read32())
elseif kind == UNISTRING_NODE then
putUnicodeString(node)
else
assert(false, "Unknown string table node: " .. kind)
end
end
end
local C_STRING = 0xE0
local COMPRESSED_STRING = 0xE1
local UNICODE_STRING = 0xE2
function strings.putString(vm, addr)
local r = vm:reader(addr)
local kind = r:read8()
if kind == C_STRING then
putCString(r)
elseif kind == UNICODE_STRING then
putUnicodeString(r)
elseif kind == COMPRESSED_STRING then
putCompressedString(vm, r)
else
assert(false, "Unknown string tag: " .. kind)
end
end
return strings