v / vlib / encoding / iconv / iconv_nix.c.v
65 lines · 52 sloc · 1.97 KB · 8e35f4d9848f7ad35d857a187dddbfd2eca5e19d
Raw
1module iconv
2
3// Module iconv provides functions convert between vstring(UTF8) to/from different encodings.
4
5#flag openbsd -I/usr/local/include
6
7#include <iconv.h>
8
9#flag darwin -liconv
10#flag freebsd -L/usr/local/lib -liconv
11#flag openbsd -L/usr/local/lib -liconv
12#flag termux -L/data/data/com.termux/files/usr/lib -liconv
13
14fn C.iconv_open(tocode charptr, fromcode charptr) voidptr
15fn C.iconv_close(cd voidptr) i32
16fn C.iconv(cd voidptr, inbuf &charptr, inbytesleft &usize, outbuf &charptr, outbytesleft &usize) usize
17
18// conv convert `fromcode` encoding string to `tocode` encoding string
19@[direct_array_access]
20fn conv(tocode string, fromcode string, src &u8, src_len int) ![]u8 {
21 if src_len < 0 {
22 return error('src length error')
23 }
24
25 mut src_encoding := fromcode.to_upper()
26 mut dst_encoding := tocode.to_upper()
27
28 // As macos-12 has no UTF16LE/UTF16BE/UTF32LE/UTF32BE, change them to UTF-16LE/UTF-16BE/UTF-32LE/UTF-32BE
29 match src_encoding {
30 'UTF16LE' { src_encoding = 'UTF-16LE' }
31 'UTF16BE' { src_encoding = 'UTF-16BE' }
32 'UTF32LE' { src_encoding = 'UTF-32LE' }
33 'UTF32BE' { src_encoding = 'UTF-32BE' }
34 else {}
35 }
36
37 match dst_encoding {
38 'UTF16LE' { dst_encoding = 'UTF-16LE' }
39 'UTF16BE' { dst_encoding = 'UTF-16BE' }
40 'UTF32LE' { dst_encoding = 'UTF-32LE' }
41 'UTF32BE' { dst_encoding = 'UTF-32BE' }
42 else {}
43 }
44
45 mut cd := C.iconv_open(charptr(dst_encoding.str), charptr(src_encoding.str))
46 if isize(cd) == -1 {
47 return error('platform can\'t convert from ${src_encoding} to ${dst_encoding}')
48 }
49 defer { C.iconv_close(cd) }
50
51 mut dst := []u8{len: (src_len + 1) * 4} // this should be enough to hold the dst encoding string
52
53 mut src_ptr := charptr(src)
54 mut dst_ptr := charptr(dst.data)
55 mut src_left := usize(src_len)
56 mut dst_left := usize(dst.len)
57 res := C.iconv(cd, &src_ptr, &src_left, &dst_ptr, &dst_left)
58 if res == usize(-1) {
59 return error('convert encoding string fail, iconv return ${res}')
60 }
61
62 // resize dst buf to real length
63 dst.trim(dst.len - int(dst_left))
64 return dst
65}
66