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.
This commit is contained in:
27
src/coding.c
27
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);
|
||||
|
||||
@@ -383,6 +383,17 @@
|
||||
(should-not (eq (encode-coding-string s nil nil) s))
|
||||
(should (eq (encode-coding-string s nil t) s))))
|
||||
|
||||
(ert-deftest coding-nocopy-ascii ()
|
||||
"Check that the NOCOPY parameter works for ASCII-only strings."
|
||||
(let* ((uni (apply #'string (number-sequence 0 127)))
|
||||
(multi (string-to-multibyte uni)))
|
||||
(dolist (s (list uni multi))
|
||||
(dolist (coding '(us-ascii iso-latin-1 utf-8))
|
||||
(should-not (eq (decode-coding-string s coding nil) s))
|
||||
(should-not (eq (encode-coding-string s coding nil) s))
|
||||
(should (eq (decode-coding-string s coding t) s))
|
||||
(should (eq (encode-coding-string s coding t) s))))))
|
||||
|
||||
;; Local Variables:
|
||||
;; byte-compile-warnings: (not obsolete)
|
||||
;; End:
|
||||
|
||||
Reference in New Issue
Block a user