aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllen Li2018-10-24 20:44:01 -0600
committerEli Zaretskii2018-11-10 11:41:51 +0200
commit5578112e182e20661783a1fef2c779b8844cf082 (patch)
treef7ab48c6949bf6b0598ed705578a4cacae554207
parent705adc237629a78c10165f9a3b3260cb56242cda (diff)
downloademacs-5578112e182e20661783a1fef2c779b8844cf082.tar.gz
emacs-5578112e182e20661783a1fef2c779b8844cf082.zip
Add 'ring-resize' function
* lisp/emacs-lisp/ring.el (ring-resize): New function. (Bug#32849) * doc/lispref/sequences.texi (Rings): Document new function 'ring-resize'. * etc/NEWS: Document new function 'ring-resize'. * test/lisp/emacs-lisp/ring-tests.el (ring-test-ring-resize): New tests.
-rw-r--r--doc/lispref/sequences.texi5
-rw-r--r--etc/NEWS4
-rw-r--r--lisp/emacs-lisp/ring.el33
-rw-r--r--test/lisp/emacs-lisp/ring-tests.el37
4 files changed, 68 insertions, 11 deletions
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 554716084ee..955ad669b80 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -1777,6 +1777,11 @@ If the ring is full, this function removes the newest element to make
1777room for the inserted element. 1777room for the inserted element.
1778@end defun 1778@end defun
1779 1779
1780@defun ring-resize ring size
1781Set the size of @var{ring} to @var{size}. If the new size is smaller,
1782then the oldest items in the ring are discarded.
1783@end defun
1784
1780@cindex fifo data structure 1785@cindex fifo data structure
1781 If you are careful not to exceed the ring size, you can 1786 If you are careful not to exceed the ring size, you can
1782use the ring as a first-in-first-out queue. For example: 1787use the ring as a first-in-first-out queue. For example:
diff --git a/etc/NEWS b/etc/NEWS
index 7f3e74457da..668b59a20a4 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1218,6 +1218,10 @@ to mean that it is not known whether DST is in effect.
1218'json-insert', 'json-parse-string', and 'json-parse-buffer'. These 1218'json-insert', 'json-parse-string', and 'json-parse-buffer'. These
1219are implemented in C using the Jansson library. 1219are implemented in C using the Jansson library.
1220 1220
1221+++
1222** New function 'ring-resize'.
1223'ring-resize' can be used to grow or shrink a ring.
1224
1221** Mailcap 1225** Mailcap
1222 1226
1223--- 1227---
diff --git a/lisp/emacs-lisp/ring.el b/lisp/emacs-lisp/ring.el
index 312df6b2de3..1b36811f9e5 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."
189(defun ring-extend (ring x) 189(defun ring-extend (ring x)
190 "Increase the size of RING by X." 190 "Increase the size of RING by X."
191 (when (and (integerp x) (> x 0)) 191 (when (and (integerp x) (> x 0))
192 (let* ((hd (car ring)) 192 (ring-resize ring (+ x (ring-size ring)))))
193 (length (ring-length ring)) 193
194 (size (ring-size ring)) 194(defun ring-resize (ring size)
195 (old-vec (cddr ring)) 195 "Set the size of RING to SIZE.
196 (new-vec (make-vector (+ size x) nil))) 196If the new size is smaller, then the oldest items in the ring are
197 (setcdr ring (cons length new-vec)) 197discarded."
198 ;; If the ring is wrapped, the existing elements must be written 198 (when (integerp size)
199 ;; out in the right order. 199 (let ((length (ring-length ring))
200 (dotimes (j length) 200 (new-vec (make-vector size nil)))
201 (aset new-vec j (aref old-vec (mod (+ hd j) size)))) 201 (if (= length 0)
202 (setcar ring 0)))) 202 (setcdr ring (cons 0 new-vec))
203 (let* ((hd (car ring))
204 (old-size (ring-size ring))
205 (old-vec (cddr ring))
206 (copy-length (min size length))
207 (copy-hd (mod (+ hd (- length copy-length)) length)))
208 (setcdr ring (cons copy-length new-vec))
209 ;; If the ring is wrapped, the existing elements must be written
210 ;; out in the right order.
211 (dotimes (j copy-length)
212 (aset new-vec j (aref old-vec (mod (+ copy-hd j) old-size))))
213 (setcar ring 0))))))
203 214
204(defun ring-insert+extend (ring item &optional grow-p) 215(defun ring-insert+extend (ring item &optional grow-p)
205 "Like `ring-insert', but if GROW-P is non-nil, then enlarge ring. 216 "Like `ring-insert', but if GROW-P is non-nil, then enlarge ring.
diff --git a/test/lisp/emacs-lisp/ring-tests.el b/test/lisp/emacs-lisp/ring-tests.el
index 0b4e3d9a694..9fa36aa3d33 100644
--- a/test/lisp/emacs-lisp/ring-tests.el
+++ b/test/lisp/emacs-lisp/ring-tests.el
@@ -162,6 +162,43 @@
162 (should (= (ring-size ring) 5)) 162 (should (= (ring-size ring) 5))
163 (should (equal (ring-elements ring) '(3 2 1))))) 163 (should (equal (ring-elements ring) '(3 2 1)))))
164 164
165(ert-deftest ring-resize/grow ()
166 (let ((ring (make-ring 3)))
167 (ring-insert ring 1)
168 (ring-insert ring 2)
169 (ring-insert ring 3)
170 (ring-resize ring 5)
171 (should (= (ring-size ring) 5))
172 (should (equal (ring-elements ring) '(3 2 1)))))
173
174(ert-deftest ring-resize/grow-empty ()
175 (let ((ring (make-ring 3)))
176 (ring-resize ring 5)
177 (should (= (ring-size ring) 5))
178 (should (equal (ring-elements ring) '()))))
179
180(ert-deftest ring-resize/grow-wrapped-ring ()
181 (let ((ring (make-ring 3)))
182 (ring-insert ring 1)
183 (ring-insert ring 2)
184 (ring-insert ring 3)
185 (ring-insert ring 4)
186 (ring-insert ring 5)
187 (ring-resize ring 5)
188 (should (= (ring-size ring) 5))
189 (should (equal (ring-elements ring) '(5 4 3)))))
190
191(ert-deftest ring-resize/shrink ()
192 (let ((ring (make-ring 5)))
193 (ring-insert ring 1)
194 (ring-insert ring 2)
195 (ring-insert ring 3)
196 (ring-insert ring 4)
197 (ring-insert ring 5)
198 (ring-resize ring 3)
199 (should (= (ring-size ring) 3))
200 (should (equal (ring-elements ring) '(5 4 3)))))
201
165(ert-deftest ring-tests-insert () 202(ert-deftest ring-tests-insert ()
166 (let ((ring (make-ring 2))) 203 (let ((ring (make-ring 2)))
167 (ring-insert+extend ring :a) 204 (ring-insert+extend ring :a)