Use a table lookup for escaping unprintable bytes (#846)
This commit is contained in:
parent
c0747f060e
commit
2c039114d2
5
msg.go
5
msg.go
|
@ -416,10 +416,7 @@ Loop:
|
|||
s = append(s, '\\', b)
|
||||
default:
|
||||
if b < ' ' || b > '~' { // unprintable, use \DDD
|
||||
var buf [3]byte
|
||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
||||
s = append(s, '\\', '0', '0', '0')
|
||||
copy(s[len(s)-len(bufs):], bufs)
|
||||
s = append(s, escapeByte(b)...)
|
||||
} else {
|
||||
s = append(s, b)
|
||||
}
|
||||
|
|
|
@ -275,7 +275,7 @@ func unpackString(msg []byte, off int) (string, int, error) {
|
|||
s.WriteByte('\\')
|
||||
s.WriteByte(b)
|
||||
case b < ' ' || b > '~': // unprintable
|
||||
writeEscapedByte(&s, b)
|
||||
s.WriteString(escapeByte(b))
|
||||
default:
|
||||
s.WriteByte(b)
|
||||
}
|
||||
|
|
42
types.go
42
types.go
|
@ -460,7 +460,7 @@ func sprintTxtOctet(s string) string {
|
|||
case b == '.':
|
||||
dst.WriteByte('.')
|
||||
case b < ' ' || b > '~':
|
||||
writeEscapedByte(&dst, b)
|
||||
dst.WriteString(escapeByte(b))
|
||||
default:
|
||||
dst.WriteByte(b)
|
||||
}
|
||||
|
@ -508,20 +508,44 @@ func writeTXTStringByte(s *strings.Builder, b byte) {
|
|||
s.WriteByte('\\')
|
||||
s.WriteByte(b)
|
||||
case b < ' ' || b > '~':
|
||||
writeEscapedByte(s, b)
|
||||
s.WriteString(escapeByte(b))
|
||||
default:
|
||||
s.WriteByte(b)
|
||||
}
|
||||
}
|
||||
|
||||
func writeEscapedByte(s *strings.Builder, b byte) {
|
||||
var buf [3]byte
|
||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
||||
s.WriteByte('\\')
|
||||
for i := len(bufs); i < 3; i++ {
|
||||
s.WriteByte('0')
|
||||
const (
|
||||
escapedByteSmall = "" +
|
||||
`\000\001\002\003\004\005\006\007\008\009` +
|
||||
`\010\011\012\013\014\015\016\017\018\019` +
|
||||
`\020\021\022\023\024\025\026\027\028\029` +
|
||||
`\030\031`
|
||||
escapedByteLarge = `\127\128\129` +
|
||||
`\130\131\132\133\134\135\136\137\138\139` +
|
||||
`\140\141\142\143\144\145\146\147\148\149` +
|
||||
`\150\151\152\153\154\155\156\157\158\159` +
|
||||
`\160\161\162\163\164\165\166\167\168\169` +
|
||||
`\170\171\172\173\174\175\176\177\178\179` +
|
||||
`\180\181\182\183\184\185\186\187\188\189` +
|
||||
`\190\191\192\193\194\195\196\197\198\199` +
|
||||
`\200\201\202\203\204\205\206\207\208\209` +
|
||||
`\210\211\212\213\214\215\216\217\218\219` +
|
||||
`\220\221\222\223\224\225\226\227\228\229` +
|
||||
`\230\231\232\233\234\235\236\237\238\239` +
|
||||
`\240\241\242\243\244\245\246\247\248\249` +
|
||||
`\250\251\252\253\254\255`
|
||||
)
|
||||
|
||||
// escapeByte returns the \DDD escaping of b which must
|
||||
// satisfy b < ' ' || b > '~'.
|
||||
func escapeByte(b byte) string {
|
||||
if b < ' ' {
|
||||
return escapedByteSmall[b*4 : b*4+4]
|
||||
}
|
||||
s.Write(bufs)
|
||||
|
||||
b -= '~' + 1
|
||||
// The cast here is needed as b*4 may overflow byte.
|
||||
return escapedByteLarge[int(b)*4 : int(b)*4+4]
|
||||
}
|
||||
|
||||
func nextByte(s string, offset int) (byte, int) {
|
||||
|
|
Loading…
Reference in New Issue