Skip to content

Commit fd3309a

Browse files
aykevldeadprogram
authored andcommitted
compiler,runtime: implement []rune to string conversion
This is used by a few packages in the standard library, at least compress/gzip and regexp/syntax.
1 parent fea56d4 commit fd3309a

File tree

4 files changed

+33
-1
lines changed

4 files changed

+33
-1
lines changed

compiler/compiler.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2415,6 +2415,8 @@ func (c *Compiler) parseConvert(typeFrom, typeTo types.Type, value llvm.Value, p
24152415
switch typeFrom.Elem().(*types.Basic).Kind() {
24162416
case types.Byte:
24172417
return c.createRuntimeCall("stringFromBytes", []llvm.Value{value}, ""), nil
2418+
case types.Rune:
2419+
return c.createRuntimeCall("stringFromRunes", []llvm.Value{value}, ""), nil
24182420
default:
24192421
return llvm.Value{}, c.makeError(pos, "todo: convert to string: "+typeFrom.String())
24202422
}

src/runtime/string.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,30 @@ func stringToBytes(x _string) (slice struct {
8989
return
9090
}
9191

92+
// Convert a []rune slice to a string.
93+
func stringFromRunes(runeSlice []rune) (s _string) {
94+
// Count the number of characters that will be in the string.
95+
for _, r := range runeSlice {
96+
_, numBytes := encodeUTF8(r)
97+
s.length += numBytes
98+
}
99+
100+
// Allocate memory for the string.
101+
s.ptr = (*byte)(alloc(s.length))
102+
103+
// Encode runes to UTF-8 and store the resulting bytes in the string.
104+
index := uintptr(0)
105+
for _, r := range runeSlice {
106+
array, numBytes := encodeUTF8(r)
107+
for _, c := range array[:numBytes] {
108+
*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(s.ptr)) + index)) = c
109+
index++
110+
}
111+
}
112+
113+
return
114+
}
115+
92116
// Convert a string to []rune slice.
93117
func stringToRunes(s string) []rune {
94118
var n = 0

testdata/string.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@ func testRangeString() {
88

99
func testStringToRunes() {
1010
var s = "abcü¢€𐍈°x"
11-
for i,c := range []rune(s) {
11+
for i, c := range []rune(s) {
1212
println(i, c)
1313
}
1414
}
1515

16+
func testRunesToString(r []rune) {
17+
println("string from runes:", string(r))
18+
}
19+
1620
func main() {
1721
testRangeString()
1822
testStringToRunes()
23+
testRunesToString([]rune{97, 98, 99, 252, 162, 8364, 66376, 176, 120})
1924
}

testdata/string.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@
1616
6 66376
1717
7 176
1818
8 120
19+
string from runes: abcü¢€𐍈°x

0 commit comments

Comments
 (0)