diff --git a/vlib/builtin/utf8.c.v b/vlib/builtin/utf8.c.v index e2084addbb..de366ed388 100644 --- a/vlib/builtin/utf8.c.v +++ b/vlib/builtin/utf8.c.v @@ -1,5 +1,7 @@ module builtin +import strings + const cp_utf8 = 65001 // to_wide returns a pointer to an UTF-16 version of the string receiver. @@ -34,7 +36,7 @@ pub fn (_str string) to_wide() &u16 { // string_from_wide creates a V string, encoded in UTF-8, given a windows // style string encoded in UTF-16. -[unsafe] +[manualfree; unsafe] pub fn string_from_wide(_wstr &u16) string { $if windows { unsafe { @@ -42,7 +44,11 @@ pub fn string_from_wide(_wstr &u16) string { return string_from_wide2(_wstr, wstr_len) } } $else { - return '' + mut i := 0 + for unsafe { _wstr[i] } != 0 { + i++ + } + return unsafe { string_from_wide2(_wstr, i) } } } @@ -50,7 +56,7 @@ pub fn string_from_wide(_wstr &u16) string { // style string, encoded in UTF-16. It is more efficient, compared to // string_from_wide, but it requires you to know the input string length, // and to pass it as the second argument. -[unsafe] +[manualfree; unsafe] pub fn string_from_wide2(_wstr &u16, len int) string { $if windows { unsafe { @@ -64,6 +70,15 @@ pub fn string_from_wide2(_wstr &u16, len int) string { return tos2(str_to) } } $else { - return '' + mut sb := strings.new_builder(len) + defer { + unsafe { sb.free() } + } + for i := 0; i < len; i++ { + u := unsafe { rune(_wstr[i]) } + sb.write_rune(u) + } + res := sb.str() + return res } } diff --git a/vlib/builtin/utf8_test.v b/vlib/builtin/utf8_test.v index d961800b93..72321251f9 100644 --- a/vlib/builtin/utf8_test.v +++ b/vlib/builtin/utf8_test.v @@ -54,3 +54,24 @@ fn test_to_wide_cyrillic() { assert w[5] == 0 } } + +const wide_serial_number = [u8(67), 0, 76, 0, 52, 0, 54, 0, 73, 0, 49, 0, 65, 0, 48, 0, 48, 0, + 54, 0, 52, 0, 57, 0, 0, 0, 0] + +const swide_serial_number = 'CL46I1A00649' + +fn test_string_from_wide() { + z := unsafe { string_from_wide(wide_serial_number.data) } + assert z == swide_serial_number +} + +fn test_string_from_wide2() { + z := unsafe { string_from_wide2(wide_serial_number.data, 12) } + assert z == swide_serial_number +} + +fn test_reverse_cyrillic_with_string_from_wide() { + s := 'Проба' + z := unsafe { string_from_wide(s.to_wide()) } + assert z == s +}