@@ -835,20 +835,27 @@ func appendLengthEncodedInteger(b []byte, n uint64) []byte {
835835 byte (n >> 32 ), byte (n >> 40 ), byte (n >> 48 ), byte (n >> 56 ))
836836}
837837
838+ // reserveBuffer checks cap(buf) and expand buffer to len(buf) + appendSize.
839+ // If cap(buf) is not enough, reallocate new buffer.
840+ func reserveBuffer (buf []byte , appendSize int ) []byte {
841+ newSize := len (buf ) + appendSize
842+ if cap (buf ) < newSize {
843+ // Grow buffer exponentially
844+ newBuf := make ([]byte , len (buf )* 2 + appendSize )
845+ copy (newBuf , buf )
846+ buf = newBuf
847+ }
848+ return buf [:newSize ]
849+ }
850+
838851// escapeBytesBackslash escapes []byte with backslashes (\)
839852// This escapes the contents of a string (provided as []byte) by adding backslashes before special
840853// characters, and turning others into specific escape sequences, such as
841854// turning newlines into \n and null bytes into \0.
842855// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L823-L932
843856func escapeBytesBackslash (buf , v []byte ) []byte {
844857 pos := len (buf )
845- end := pos + len (v )* 2
846- if cap (buf ) < end {
847- n := make ([]byte , pos + end )
848- copy (n , buf )
849- buf = n
850- }
851- buf = buf [0 :end ]
858+ buf = reserveBuffer (buf , len (v )* 2 )
852859
853860 for _ , c := range v {
854861 switch c {
@@ -892,13 +899,7 @@ func escapeBytesBackslash(buf, v []byte) []byte {
892899// escapeStringBackslash is similar to escapeBytesBackslash but for string.
893900func escapeStringBackslash (buf []byte , v string ) []byte {
894901 pos := len (buf )
895- end := pos + len (v )* 2
896- if cap (buf ) < end {
897- n := make ([]byte , pos + end )
898- copy (n , buf )
899- buf = n
900- }
901- buf = buf [0 :end ]
902+ buf = reserveBuffer (buf , len (v )* 2 )
902903
903904 for i := 0 ; i < len (v ); i ++ {
904905 c := v [i ]
@@ -947,13 +948,7 @@ func escapeStringBackslash(buf []byte, v string) []byte {
947948// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L963-L1038
948949func escapeBytesQuotes (buf , v []byte ) []byte {
949950 pos := len (buf )
950- end := pos + len (v )* 2
951- if cap (buf ) < end {
952- n := make ([]byte , pos + end )
953- copy (n , buf )
954- buf = n
955- }
956- buf = buf [0 :end ]
951+ buf = reserveBuffer (buf , len (v )* 2 )
957952
958953 for _ , c := range v {
959954 if c == '\'' {
@@ -972,13 +967,7 @@ func escapeBytesQuotes(buf, v []byte) []byte {
972967// escapeStringQuotes is similar to escapeBytesQuotes but for string.
973968func escapeStringQuotes (buf []byte , v string ) []byte {
974969 pos := len (buf )
975- end := pos + len (v )* 2
976- if cap (buf ) < end {
977- n := make ([]byte , pos + end )
978- copy (n , buf )
979- buf = n
980- }
981- buf = buf [0 :end ]
970+ buf = reserveBuffer (buf , len (v )* 2 )
982971
983972 for i := 0 ; i < len (v ); i ++ {
984973 c := v [i ]
0 commit comments