diff options
| author | Mattias Engdegård | 2024-05-13 10:44:05 +0200 |
|---|---|---|
| committer | Mattias Engdegård | 2024-05-13 12:39:41 +0200 |
| commit | 49e243c0c85d18fc775970d9ebd846eba3a6866e (patch) | |
| tree | 2ee32a6f81bfe93b7d0f3f84d83ee82f655808d1 /test | |
| parent | 334fb0ddfe603097c3493297c3e78a185b22d1af (diff) | |
| download | emacs-49e243c0c85d18fc775970d9ebd846eba3a6866e.tar.gz emacs-49e243c0c85d18fc775970d9ebd846eba3a6866e.zip | |
Avoid resizing mutation in subst-char-in-string, take two
This time we take care to preserve properties, and add a test.
* lisp/subr.el (subst-char-in-string):
Use string-replace to avoid resizing mutation and O(n^2) time.
* test/lisp/subr-tests.el (subr--subst-char-in-string): New test.
Diffstat (limited to 'test')
| -rw-r--r-- | test/lisp/subr-tests.el | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index 119c124f3a5..6f28e057342 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el | |||
| @@ -1330,5 +1330,53 @@ final or penultimate step during initialization.")) | |||
| 1330 | (t x) (:success (1+ x))) | 1330 | (t x) (:success (1+ x))) |
| 1331 | '(error ""))))) | 1331 | '(error ""))))) |
| 1332 | 1332 | ||
| 1333 | (ert-deftest subr--subst-char-in-string () | ||
| 1334 | ;; Cross-validate `subst-char-in-string' with `string-replace', | ||
| 1335 | ;; which should produce the same results when there are no properties. | ||
| 1336 | (dolist (str '("ananas" "na\x80ma\x80s" "hétérogénéité" | ||
| 1337 | "Ω, Ω, Ω" "é-\x80-\x80")) | ||
| 1338 | (dolist (mb '(nil t)) | ||
| 1339 | (unless (and (not mb) (multibyte-string-p str)) | ||
| 1340 | (let ((str (if (and mb (not (multibyte-string-p str))) | ||
| 1341 | (string-to-multibyte str) | ||
| 1342 | str))) | ||
| 1343 | (dolist (inplace '(nil t)) | ||
| 1344 | (dolist (from '(?a ?é ?Ω #x80 #x3fff80)) | ||
| 1345 | (dolist (to '(?o ?á ?ƒ ?☃ #x1313f #xff #x3fffc9)) | ||
| 1346 | ;; Can't put a non-byte value in a non-ASCII unibyte string. | ||
| 1347 | (unless (and (not mb) (> to #xff) | ||
| 1348 | (not (string-match-p (rx bos (* ascii) eos) str))) | ||
| 1349 | (let* ((in (copy-sequence str)) | ||
| 1350 | (ref (if (and (not mb) (> from #xff)) | ||
| 1351 | in ; nothing to replace | ||
| 1352 | (string-replace | ||
| 1353 | (if (and (not mb) (<= from #xff)) | ||
| 1354 | (unibyte-string from) | ||
| 1355 | (string from)) | ||
| 1356 | (if (and (not mb) (<= to #xff)) | ||
| 1357 | (unibyte-string to) | ||
| 1358 | (string to)) | ||
| 1359 | in))) | ||
| 1360 | (out (subst-char-in-string from to in inplace))) | ||
| 1361 | (should (equal out ref)) | ||
| 1362 | (if inplace | ||
| 1363 | (should (eq out in)) | ||
| 1364 | (should (equal in str)))))))))))) | ||
| 1365 | |||
| 1366 | ;; Verify that properties are preserved. | ||
| 1367 | (dolist (str (list "cocoa" (string-to-multibyte "cocoa") "écalé")) | ||
| 1368 | (dolist (from '(?a ?o ?c ?é)) | ||
| 1369 | (dolist (to '(?i ?à ?☃)) | ||
| 1370 | (let ((in (copy-sequence str))) | ||
| 1371 | (put-text-property 0 5 'alpha 1 in) | ||
| 1372 | (put-text-property 1 4 'beta 2 in) | ||
| 1373 | (put-text-property 0 2 'gamma 3 in) | ||
| 1374 | (put-text-property 1 4 'delta 4 in) | ||
| 1375 | (put-text-property 2 3 'epsilon 5 in) | ||
| 1376 | (let* ((props-in (copy-tree (object-intervals in))) | ||
| 1377 | (out (subst-char-in-string from to in)) | ||
| 1378 | (props-out (object-intervals out))) | ||
| 1379 | (should (equal props-out props-in)))))))) | ||
| 1380 | |||
| 1333 | (provide 'subr-tests) | 1381 | (provide 'subr-tests) |
| 1334 | ;;; subr-tests.el ends here | 1382 | ;;; subr-tests.el ends here |