diff options
Diffstat (limited to 'misc.go')
-rw-r--r-- | misc.go | 81 |
1 files changed, 53 insertions, 28 deletions
@@ -68,34 +68,42 @@ func writeRune(w io.Writer, c rune) (int, error) { // JSON string encoding //////////////////////////////////////////////////////// -func UnicodeEscapeJSSafe(c rune, _ bool) bool { +type BackslashEscapeMode uint8 + +const ( + BackslashEscapeNone = BackslashEscapeMode(iota) + BackslashEscapeShort + BackslashEscapeUnicode +) + +func EscapeJSSafe(c rune, _ BackslashEscapeMode) BackslashEscapeMode { // JSON is notionally a JS subset, but that's not actually // true. // // http://timelessrepo.com/json-isnt-a-javascript-subset switch c { case '\u2028', '\u2029': - return true + return BackslashEscapeUnicode default: - return false + return BackslashEscapeNone } } -func UnicodeEscapeHTMLSafe(c rune, wasEscaped bool) bool { +func EscapeHTMLSafe(c rune, wasEscaped BackslashEscapeMode) BackslashEscapeMode { switch c { case '&', '<', '>': - return true + return BackslashEscapeUnicode default: - return UnicodeEscapeJSSafe(c, wasEscaped) + return EscapeJSSafe(c, wasEscaped) } } -func UnicodeEscapeDefault(c rune, wasEscaped bool) bool { +func EscapeDefault(c rune, wasEscaped BackslashEscapeMode) BackslashEscapeMode { switch c { case '\b', '\f', utf8.RuneError: - return true + return BackslashEscapeUnicode default: - return UnicodeEscapeHTMLSafe(c, wasEscaped) + return EscapeHTMLSafe(c, wasEscaped) } } @@ -114,31 +122,48 @@ func writeStringShortEscape(w io.Writer, c byte) (int, error) { buf := [2]byte{'\\', c} return w.Write(buf[:]) } -func writeStringChar(w io.Writer, c rune, wasEscaped bool, escaper func(rune, bool) bool) (int, error) { +func writeStringChar(w io.Writer, c rune, wasEscaped BackslashEscapeMode, escaper func(rune, BackslashEscapeMode) BackslashEscapeMode) (int, error) { if escaper == nil { - escaper = UnicodeEscapeDefault + escaper = EscapeDefault } - switch { - case c <= 0xFFFF && escaper(c, wasEscaped): - return writeStringUnicodeEscape(w, c) - case c == '"' || c == '\\': - return writeStringShortEscape(w, byte(c)) - case c < 0x0020: + switch escaper(c, wasEscaped) { + case BackslashEscapeNone: + switch { + case c < 0x0020: + switch c { + case '\b': + return writeStringShortEscape(w, 'b') + case '\f': + return writeStringShortEscape(w, 'f') + case '\n': + return writeStringShortEscape(w, 'n') + case '\r': + return writeStringShortEscape(w, 'r') + case '\t': + return writeStringShortEscape(w, 't') + default: + return writeStringUnicodeEscape(w, c) + } + case c == '"' || c == '\\': + return writeStringShortEscape(w, byte(c)) + default: + return writeRune(w, c) + } + case BackslashEscapeShort: switch c { - case '\b': - return writeStringShortEscape(w, 'b') - case '\f': - return writeStringShortEscape(w, 'f') - case '\n': - return writeStringShortEscape(w, 'n') - case '\r': - return writeStringShortEscape(w, 'r') - case '\t': - return writeStringShortEscape(w, 't') + case '"', '\\', '/', '\b', '\f', '\n', '\r', '\t': + return writeStringShortEscape(w, byte(c)) + default: + return writeRune(w, c) + } + case BackslashEscapeUnicode: + switch { + case c > 0xFFFF: + return writeRune(w, c) default: return writeStringUnicodeEscape(w, c) } default: - return writeRune(w, c) + panic("escaper returned an invalid escape mode") } } |