diff options
author | Mattias EngdegÄrd <mattiase@acm.org> | 2020-04-03 16:01:01 +0200 |
---|---|---|
committer | Mattias EngdegÄrd <mattiase@acm.org> | 2020-04-05 15:37:55 +0200 |
commit | 4ed39549e3f9dbfeb2aea0e2674a7701dbc0e5ea (patch) | |
tree | 192e8b852c9af4e70ee3ec7a7ca26ae82c57bb2c /src/coding.c | |
parent | c7ac76603f291d432586abd2eeb75e1ca6e54863 (diff) | |
download | emacs-4ed39549e3f9dbfeb2aea0e2674a7701dbc0e5ea.tar.gz |
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.
Diffstat (limited to 'src/coding.c')
-rw-r--r-- | src/coding.c | 27 |
1 files changed, 26 insertions, 1 deletions
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); |