mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-25 03:06:10 +01:00
136 lines
2.4 KiB
Go
136 lines
2.4 KiB
Go
package mahonia
|
|
|
|
import (
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// ConvertString converts a string from UTF-8 to e's encoding.
|
|
func (e Encoder) ConvertString(s string) string {
|
|
dest := make([]byte, len(s)+10)
|
|
destPos := 0
|
|
|
|
for _, rune := range s {
|
|
retry:
|
|
size, status := e(dest[destPos:], rune)
|
|
|
|
if status == NO_ROOM {
|
|
newDest := make([]byte, len(dest)*2)
|
|
copy(newDest, dest)
|
|
dest = newDest
|
|
goto retry
|
|
}
|
|
|
|
if status == STATE_ONLY {
|
|
destPos += size
|
|
goto retry
|
|
}
|
|
|
|
destPos += size
|
|
}
|
|
|
|
return string(dest[:destPos])
|
|
}
|
|
|
|
// ConvertString converts a string from d's encoding to UTF-8.
|
|
func (d Decoder) ConvertString(s string) string {
|
|
bytes := []byte(s)
|
|
runes := make([]rune, len(s))
|
|
destPos := 0
|
|
|
|
for len(bytes) > 0 {
|
|
c, size, status := d(bytes)
|
|
|
|
if status == STATE_ONLY {
|
|
bytes = bytes[size:]
|
|
continue
|
|
}
|
|
|
|
if status == NO_ROOM {
|
|
c = 0xfffd
|
|
size = len(bytes)
|
|
status = INVALID_CHAR
|
|
}
|
|
|
|
bytes = bytes[size:]
|
|
runes[destPos] = c
|
|
destPos++
|
|
}
|
|
|
|
return string(runes[:destPos])
|
|
}
|
|
|
|
// ConvertStringOK converts a string from UTF-8 to e's encoding. It also
|
|
// returns a boolean indicating whether every character was converted
|
|
// successfully.
|
|
func (e Encoder) ConvertStringOK(s string) (result string, ok bool) {
|
|
dest := make([]byte, len(s)+10)
|
|
destPos := 0
|
|
ok = true
|
|
|
|
for i, r := range s {
|
|
// The following test is copied from utf8.ValidString.
|
|
if r == utf8.RuneError && ok {
|
|
_, size := utf8.DecodeRuneInString(s[i:])
|
|
if size == 1 {
|
|
ok = false
|
|
}
|
|
}
|
|
|
|
retry:
|
|
size, status := e(dest[destPos:], r)
|
|
|
|
switch status {
|
|
case NO_ROOM:
|
|
newDest := make([]byte, len(dest)*2)
|
|
copy(newDest, dest)
|
|
dest = newDest
|
|
goto retry
|
|
|
|
case STATE_ONLY:
|
|
destPos += size
|
|
goto retry
|
|
|
|
case INVALID_CHAR:
|
|
ok = false
|
|
}
|
|
|
|
destPos += size
|
|
}
|
|
|
|
return string(dest[:destPos]), ok
|
|
}
|
|
|
|
// ConvertStringOK converts a string from d's encoding to UTF-8.
|
|
// It also returns a boolean indicating whether every character was converted
|
|
// successfully.
|
|
func (d Decoder) ConvertStringOK(s string) (result string, ok bool) {
|
|
bytes := []byte(s)
|
|
runes := make([]rune, len(s))
|
|
destPos := 0
|
|
ok = true
|
|
|
|
for len(bytes) > 0 {
|
|
c, size, status := d(bytes)
|
|
|
|
switch status {
|
|
case STATE_ONLY:
|
|
bytes = bytes[size:]
|
|
continue
|
|
|
|
case NO_ROOM:
|
|
c = 0xfffd
|
|
size = len(bytes)
|
|
ok = false
|
|
|
|
case INVALID_CHAR:
|
|
ok = false
|
|
}
|
|
|
|
bytes = bytes[size:]
|
|
runes[destPos] = c
|
|
destPos++
|
|
}
|
|
|
|
return string(runes[:destPos]), ok
|
|
}
|