summaryrefslogtreecommitdiff
path: root/misc.go
diff options
context:
space:
mode:
Diffstat (limited to 'misc.go')
-rw-r--r--misc.go81
1 files changed, 53 insertions, 28 deletions
diff --git a/misc.go b/misc.go
index a567cc7..4d8b136 100644
--- a/misc.go
+++ b/misc.go
@@ -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")
}
}