summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/ring.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/ring.el')
-rw-r--r--lisp/emacs-lisp/ring.el33
1 files changed, 22 insertions, 11 deletions
diff --git a/lisp/emacs-lisp/ring.el b/lisp/emacs-lisp/ring.el
index cfbe4eb9ef8..c7d0268a77f 100644
--- a/lisp/emacs-lisp/ring.el
+++ b/lisp/emacs-lisp/ring.el
@@ -189,17 +189,28 @@ Raise error if ITEM is not in the RING."
(defun ring-extend (ring x)
"Increase the size of RING by X."
(when (and (integerp x) (> x 0))
- (let* ((hd (car ring))
- (length (ring-length ring))
- (size (ring-size ring))
- (old-vec (cddr ring))
- (new-vec (make-vector (+ size x) nil)))
- (setcdr ring (cons length new-vec))
- ;; If the ring is wrapped, the existing elements must be written
- ;; out in the right order.
- (dotimes (j length)
- (aset new-vec j (aref old-vec (mod (+ hd j) size))))
- (setcar ring 0))))
+ (ring-resize ring (+ x (ring-size ring)))))
+
+(defun ring-resize (ring size)
+ "Set the size of RING to SIZE.
+If the new size is smaller, then the oldest items in the ring are
+discarded."
+ (when (integerp size)
+ (let ((length (ring-length ring))
+ (new-vec (make-vector size nil)))
+ (if (= length 0)
+ (setcdr ring (cons 0 new-vec))
+ (let* ((hd (car ring))
+ (old-size (ring-size ring))
+ (old-vec (cddr ring))
+ (copy-length (min size length))
+ (copy-hd (mod (+ hd (- length copy-length)) length)))
+ (setcdr ring (cons copy-length new-vec))
+ ;; If the ring is wrapped, the existing elements must be written
+ ;; out in the right order.
+ (dotimes (j copy-length)
+ (aset new-vec j (aref old-vec (mod (+ copy-hd j) old-size))))
+ (setcar ring 0))))))
(defun ring-insert+extend (ring item &optional grow-p)
"Like `ring-insert', but if GROW-P is non-nil, then enlarge ring.