Skip to content

Commit

Permalink
add encoding.iconv
Browse files Browse the repository at this point in the history
  • Loading branch information
kbkpbot committed Sep 27, 2024
1 parent 2db53a4 commit afa6d92
Show file tree
Hide file tree
Showing 3 changed files with 617 additions and 0 deletions.
52 changes: 52 additions & 0 deletions vlib/encoding/iconv/iconv_nix.c.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module iconv

// Module iconv provides functions conversion between vstring(UTF8) to/from difference encodings.

fn C.iconv_open(tocode &u8, fromcode &u8) int
fn C.iconv_close(cd int) int
fn C.iconv(cd int, inbuf &&u8, inbytesleft &usize, outbuf &&u8, outbytesleft &usize) usize

// conv convert `fromcode` encoding string to `tocode` encoding string
fn conv(tocode string, fromcode string, src &u8, src_len int) []u8 {
if isnil(src) || src_len <= 0 {
return []u8{}
}
mut dst := []u8{len: src_len * 4} // this should be enough to hold the dst encoding string
cd := C.iconv_open(tocode.str, fromcode.str)
if cd == -1 {
return []u8{}
}
defer { C.iconv_close(cd) }

mut src_ptr := unsafe { src }
mut dst_ptr := &u8(dst.data)
mut src_left := usize(src_len)
mut dst_left := usize(dst.len)
res := C.iconv(cd, &src_ptr, &src_left, &dst_ptr, &dst_left)
if res == usize(-1) {
return []u8{}
}

// resize dst buf to real length
dst.trim(dst.len - int(dst_left))
return dst
}

// vstring_to_encoding convert vstring `str` to `tocode` encoding string
// tips: use `iconv --list` check for supported encodings
pub fn vstring_to_encoding(tocode string, str string) []u8 {
return conv(tocode, 'UTF-8', str.str, str.len)
}

// encoding_to_vstring convert `fromcode` encoding string to vstring
// tips: use `iconv --list` check for supported encodings
pub fn encoding_to_vstring(fromcode string, str []u8) string {
dst := conv('UTF-8', fromcode, str.data, str.len)
defer {
unsafe { dst.free() }
}
if dst.len == 0 {
return ''
}
return unsafe { cstring_to_vstring(dst.data) }
}
16 changes: 16 additions & 0 deletions vlib/encoding/iconv/iconv_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import encoding.iconv

fn test_vstring_to_encoding() {
assert iconv.vstring_to_encoding('UTF8', 'abc') == [u8(97), 98, 99]
assert iconv.vstring_to_encoding('GB18030', 'V大法好') == [u8(86), 180, 243, 183, 168, 186,
195]
assert iconv.vstring_to_encoding('encoding_not_exist', 'abc') == []
assert iconv.vstring_to_encoding('GB18030', '') == []
}

fn test_encoding_to_vstring() {
assert iconv.encoding_to_vstring('UTF8', [u8(97), 98, 99]) == 'abc'
assert iconv.encoding_to_vstring('GB18030', [u8(86), 180, 243, 183, 168, 186, 195]) == 'V大法好'
assert iconv.encoding_to_vstring('encoding_not_exist', [u8(97), 98, 99]) == ''
assert iconv.encoding_to_vstring('GB18030', []) == ''
}
Loading

0 comments on commit afa6d92

Please sign in to comment.