mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 02:57:46 +00:00
compiler: implement range over a string
This commit is contained in:
@@ -12,6 +12,12 @@ type _string struct {
|
||||
length lenType
|
||||
}
|
||||
|
||||
// The iterator state for a range over a string.
|
||||
type stringIterator struct {
|
||||
byteindex lenType
|
||||
rangeindex lenType
|
||||
}
|
||||
|
||||
// Return true iff the strings match.
|
||||
//go:nobounds
|
||||
func stringEqual(x, y string) bool {
|
||||
@@ -75,6 +81,18 @@ func stringFromUnicode(x rune) _string {
|
||||
return _string{ptr: (*byte)(unsafe.Pointer(&array)), length: length}
|
||||
}
|
||||
|
||||
// Iterate over a string.
|
||||
// Returns (ok, key, value).
|
||||
func stringNext(s string, it *stringIterator) (bool, int, rune) {
|
||||
if len(s) <= int(it.byteindex) {
|
||||
return false, 0, 0
|
||||
}
|
||||
r, length := decodeUTF8(s, it.byteindex)
|
||||
it.byteindex += length
|
||||
it.rangeindex += 1
|
||||
return true, int(it.rangeindex), r
|
||||
}
|
||||
|
||||
// Convert a Unicode code point into an array of bytes and its length.
|
||||
func encodeUTF8(x rune) ([4]byte, lenType) {
|
||||
// https://stackoverflow.com/questions/6240055/manually-converting-unicode-codepoints-into-utf-8-and-utf-16
|
||||
@@ -102,3 +120,31 @@ func encodeUTF8(x rune) ([4]byte, lenType) {
|
||||
return [4]byte{0xef, 0xbf, 0xbd, 0}, 3
|
||||
}
|
||||
}
|
||||
|
||||
// Decode a single UTF-8 character from a string.
|
||||
//go:nobounds
|
||||
func decodeUTF8(s string, index lenType) (rune, lenType) {
|
||||
remaining := lenType(len(s)) - index // must be >= 1 before calling this function
|
||||
x := s[index]
|
||||
switch {
|
||||
case x&0x80 == 0x00: // 0xxxxxxx
|
||||
return rune(x), 1
|
||||
case x&0xe0 == 0xc0: // 110xxxxx
|
||||
if remaining < 2 {
|
||||
return 0xfffd, 1
|
||||
}
|
||||
return (rune(x&0x1f) << 6) | (rune(s[index+1]) & 0x3f), 2
|
||||
case x&0xf0 == 0xe0: // 1110xxxx
|
||||
if remaining < 3 {
|
||||
return 0xfffd, 1
|
||||
}
|
||||
return (rune(x&0x0f) << 12) | ((rune(s[index+1]) & 0x3f) << 6) | (rune(s[index+2]) & 0x3f), 3
|
||||
case x&0xf8 == 0xf0: // 11110xxx
|
||||
if remaining < 4 {
|
||||
return 0xfffd, 1
|
||||
}
|
||||
return (rune(x&0x07) << 18) | ((rune(s[index+1]) & 0x3f) << 12) | ((rune(s[index+2]) & 0x3f) << 6) | (rune(s[index+3]) & 0x3f), 4
|
||||
default:
|
||||
return 0xfffd, 1
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user