-
Notifications
You must be signed in to change notification settings - Fork 1
/
iconv.lua
74 lines (58 loc) · 1.74 KB
/
iconv.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
local ffi = require("ffi")
ffi.cdef([[
typedef void* libiconv_t;
libiconv_t libiconv_open (const char* tocode, const char* fromcode);
size_t libiconv (libiconv_t cd, const char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);
int libiconv_close (libiconv_t cd);
]])
local libiconv = ffi.load("iconv")
local iconv = {}
iconv.__index = iconv
---@param tocode any
---@param fromcode any
---@return table?
---@return string?
function iconv:open(tocode, fromcode)
local cd = libiconv.libiconv_open(tocode, fromcode)
if cd == -1 then
return nil, "iconv open error"
end
ffi.gc(cd, libiconv.libiconv_close)
return setmetatable({cd = cd}, self)
end
function iconv:close()
local cd = self.cd
libiconv.libiconv_close(cd)
ffi.gc(cd, nil)
end
local outbuff_size = 1024
local outbuff = ffi.new("char[?]", outbuff_size)
local outbuff_ptr = ffi.new("char*[1]", outbuff)
local outbytesleft = ffi.new("size_t[1]", outbuff_size)
local inbuff_ptr = ffi.new("const char*[1]")
local inbytesleft = ffi.new("size_t[1]")
---@param instr string
---@return string?
---@return string?
function iconv:convert(instr)
local out = {}
inbuff_ptr[0] = instr
inbytesleft[0] = #instr
local cd = self.cd
repeat
local inbytesleft0 = inbytesleft[0]
local ok = libiconv.libiconv(cd, inbuff_ptr, inbytesleft, outbuff_ptr, outbytesleft)
-- if ok == -1ull then
-- print("error", ffi.errno()) -- errno doesn't work
-- end
if inbytesleft[0] - inbytesleft0 == 0 and inbytesleft[0] ~= 0 then
return nil, "failed"
end
out[#out + 1] = ffi.string(outbuff, outbuff_size - outbytesleft[0])
outbuff_ptr[0] = outbuff
outbytesleft[0] = outbuff_size
until inbytesleft[0] == 0
libiconv.libiconv(cd, nil, nil, nil, nil)
return table.concat(out)
end
return iconv