summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMattias EngdegÄrd <mattiase@acm.org>2024-05-10 10:35:39 +0200
committerMattias EngdegÄrd <mattiase@acm.org>2024-05-10 15:45:15 +0200
commit184d6e8c02345583264b053bb59ae031bb1c5a00 (patch)
tree14956823cbe37488155d784abe9c921e17b42a45
parent78761d699eed9e05bc4007927e63246c77c70ceb (diff)
downloademacs-184d6e8c02345583264b053bb59ae031bb1c5a00.tar.gz
Avoid resizing mutation in subst-char-in-string
* lisp/subr.el (subst-char-in-string): Use string-replace to avoid resizing mutation and O(n^2) time.
-rw-r--r--lisp/subr.el20
1 files changed, 13 insertions, 7 deletions
diff --git a/lisp/subr.el b/lisp/subr.el
index 0ac71560c59..444afc0e486 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -5690,13 +5690,19 @@ The SEPARATOR regexp defaults to \"\\s-+\"."
(defun subst-char-in-string (fromchar tochar string &optional inplace)
"Replace FROMCHAR with TOCHAR in STRING each time it occurs.
Unless optional argument INPLACE is non-nil, return a new string."
- (let ((i (length string))
- (newstr (if inplace string (copy-sequence string))))
- (while (> i 0)
- (setq i (1- i))
- (if (eq (aref newstr i) fromchar)
- (aset newstr i tochar)))
- newstr))
+ (if (and (not inplace)
+ (if (multibyte-string-p string)
+ (> (max fromchar tochar) 127)
+ (> tochar 255)))
+ ;; Avoid quadratic behaviour from resizing replacement.
+ (string-replace (string fromchar) (string tochar) string)
+ (let ((i (length string))
+ (newstr (if inplace string (copy-sequence string))))
+ (while (> i 0)
+ (setq i (1- i))
+ (if (eq (aref newstr i) fromchar)
+ (aset newstr i tochar)))
+ newstr)))
(defun string-replace (from-string to-string in-string)
"Replace FROM-STRING with TO-STRING in IN-STRING each time it occurs."