status-go/vendor/github.com/francoispqt/gojay/decode_string_unicode.go

99 lines
2.0 KiB
Go
Raw Normal View History

2022-04-01 16:16:46 +00:00
package gojay
import (
"unicode/utf16"
"unicode/utf8"
)
func (dec *Decoder) getUnicode() (rune, error) {
i := 0
r := rune(0)
for ; (dec.cursor < dec.length || dec.read()) && i < 4; dec.cursor++ {
c := dec.data[dec.cursor]
if c >= '0' && c <= '9' {
r = r*16 + rune(c-'0')
} else if c >= 'a' && c <= 'f' {
r = r*16 + rune(c-'a'+10)
} else if c >= 'A' && c <= 'F' {
r = r*16 + rune(c-'A'+10)
} else {
return 0, InvalidJSONError("Invalid unicode code point")
}
i++
}
return r, nil
}
func (dec *Decoder) appendEscapeChar(str []byte, c byte) ([]byte, error) {
switch c {
case 't':
str = append(str, '\t')
case 'n':
str = append(str, '\n')
case 'r':
str = append(str, '\r')
case 'b':
str = append(str, '\b')
case 'f':
str = append(str, '\f')
case '\\':
str = append(str, '\\')
default:
return nil, InvalidJSONError("Invalid JSON")
}
return str, nil
}
func (dec *Decoder) parseUnicode() ([]byte, error) {
// get unicode after u
r, err := dec.getUnicode()
if err != nil {
return nil, err
}
// no error start making new string
str := make([]byte, 16, 16)
i := 0
// check if code can be a surrogate utf16
if utf16.IsSurrogate(r) {
if dec.cursor >= dec.length && !dec.read() {
return nil, dec.raiseInvalidJSONErr(dec.cursor)
}
c := dec.data[dec.cursor]
if c != '\\' {
i += utf8.EncodeRune(str, r)
return str[:i], nil
}
dec.cursor++
if dec.cursor >= dec.length && !dec.read() {
return nil, dec.raiseInvalidJSONErr(dec.cursor)
}
c = dec.data[dec.cursor]
if c != 'u' {
i += utf8.EncodeRune(str, r)
str, err = dec.appendEscapeChar(str[:i], c)
if err != nil {
dec.err = err
return nil, err
}
i++
dec.cursor++
return str[:i], nil
}
dec.cursor++
r2, err := dec.getUnicode()
if err != nil {
return nil, err
}
combined := utf16.DecodeRune(r, r2)
if combined == '\uFFFD' {
i += utf8.EncodeRune(str, r)
i += utf8.EncodeRune(str, r2)
} else {
i += utf8.EncodeRune(str, combined)
}
return str[:i], nil
}
i += utf8.EncodeRune(str, r)
return str[:i], nil
}