from which to start."
(let* ((spaces 0)
(multi-char-table (char-table-extra-slot character-fold-table 0))
- (lower-case-table (current-case-table))
- (upper-case-table (char-table-extra-slot lower-case-table 0))
(i (or from 0))
(end (length string))
(out nil))
(setq spaces 0))
(let ((regexp (or (aref character-fold-table c)
(regexp-quote (string c))))
- (alist nil))
- ;; Long string. The regexp would probably be too long.
- (unless (> end 50)
- (setq alist (aref multi-char-table c))
- (when case-fold-search
- (let ((other-c (aref lower-case-table c)))
- (when (or (not other-c)
- (eq other-c c))
- (setq other-c (aref upper-case-table c)))
- (when other-c
- (setq alist (append alist (aref multi-char-table other-c)))
- (setq regexp (concat "\\(?:" regexp "\\|"
- (or (aref character-fold-table other-c)
- (regexp-quote (string other-c)))
- "\\)"))))))
+ ;; Long string. The regexp would probably be too long.
+ (alist (unless (> end 50)
+ (aref multi-char-table c))))
(push (let ((matched-entries nil)
(max-length 0))
(dolist (entry alist)
(push (character-fold--make-space-string spaces) out))
(let ((regexp (apply #'concat (nreverse out))))
;; Limited by `MAX_BUF_SIZE' in `regex.c'.
- (if (> (length regexp) 10000)
+ (if (> (length regexp) 5000)
(regexp-quote string)
regexp))))
;; (character-fold--test-match-exactly "a12" "xxyy")
))
+(ert-deftest character-fold--speed-test ()
+ (dolist (string (append '("tty-set-up-initial-frame-face"
+ "tty-set-up-initial-frame-face-frame-faceframe-faceframe-faceframe-face")
+ (mapcar #'character-fold--random-word '(10 50 100
+ 50 100))))
+ (message "Testing %s" string)
+ ;; Make sure we didn't just fallback on the trivial search.
+ (should-not (string= (regexp-quote string)
+ (character-fold-to-regexp string)))
+ (with-temp-buffer
+ (save-excursion (insert string))
+ (let ((time (time-to-seconds (current-time))))
+ ;; Our initial implementation of case-folding in char-folding
+ ;; created a lot of redundant paths in the regexp. Because of
+ ;; that, if a really long string "almost" matches, the regexp
+ ;; engine took a long time to realise that it doesn't match.
+ (should-not (character-fold-search-forward (concat string "c") nil 'noerror))
+ ;; Ensure it took less than a second.
+ (should (< (- (time-to-seconds (current-time))
+ time)
+ 1))))))
(provide 'character-fold-tests)
;;; character-fold-tests.el ends here