From 4ed39549e3f9dbfeb2aea0e2674a7701dbc0e5ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Fri, 3 Apr 2020 16:01:01 +0200 Subject: Avoid expensive recoding for ASCII identity cases (bug#40407) Optimise for the common case of encoding or decoding an ASCII-only string using an ASCII-compatible coding, for file names in particular. * src/coding.c (string_ascii_p): New function. (code_convert_string): Return the input string for ASCII-only inputs and ASCII-compatible codings. * test/src/coding-tests.el (coding-nocopy-ascii): New test. --- src/coding.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'src/coding.c') diff --git a/src/coding.c b/src/coding.c index 1049f1b755a..97a6eb949a8 100644 --- a/src/coding.c +++ b/src/coding.c @@ -9471,6 +9471,17 @@ not fully specified.) */) return code_convert_region (start, end, coding_system, destination, 1, 0); } +/* Whether a string only contains chars in the 0..127 range. */ +static bool +string_ascii_p (Lisp_Object str) +{ + ptrdiff_t nbytes = SBYTES (str); + for (ptrdiff_t i = 0; i < nbytes; i++) + if (SREF (str, i) > 127) + return false; + return true; +} + Lisp_Object code_convert_string (Lisp_Object string, Lisp_Object coding_system, Lisp_Object dst_object, bool encodep, bool nocopy, @@ -9502,7 +9513,21 @@ code_convert_string (Lisp_Object string, Lisp_Object coding_system, chars = SCHARS (string); bytes = SBYTES (string); - if (BUFFERP (dst_object)) + if (EQ (dst_object, Qt)) + { + /* Fast path for ASCII-only input and an ASCII-compatible coding: + act as identity. */ + Lisp_Object attrs = CODING_ID_ATTRS (coding.id); + if (! NILP (CODING_ATTR_ASCII_COMPAT (attrs)) + && (STRING_MULTIBYTE (string) + ? (chars == bytes) : string_ascii_p (string))) + return (nocopy + ? string + : (encodep + ? make_unibyte_string (SDATA (string), bytes) + : make_multibyte_string (SDATA (string), bytes, bytes))); + } + else if (BUFFERP (dst_object)) { struct buffer *buf = XBUFFER (dst_object); ptrdiff_t buf_pt = BUF_PT (buf); -- cgit v1.2.1