diff options
Diffstat (limited to 'vendor/github.com/francoispqt/gojay/decode_string_unicode.go')
-rw-r--r-- | vendor/github.com/francoispqt/gojay/decode_string_unicode.go | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/vendor/github.com/francoispqt/gojay/decode_string_unicode.go b/vendor/github.com/francoispqt/gojay/decode_string_unicode.go new file mode 100644 index 00000000..9e14d52b --- /dev/null +++ b/vendor/github.com/francoispqt/gojay/decode_string_unicode.go @@ -0,0 +1,98 @@ +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 +} |