diff options
| author | Allen Li | 2018-10-24 20:44:01 -0600 |
|---|---|---|
| committer | Eli Zaretskii | 2018-11-10 11:41:51 +0200 |
| commit | 5578112e182e20661783a1fef2c779b8844cf082 (patch) | |
| tree | f7ab48c6949bf6b0598ed705578a4cacae554207 | |
| parent | 705adc237629a78c10165f9a3b3260cb56242cda (diff) | |
| download | emacs-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.texi | 5 | ||||
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | lisp/emacs-lisp/ring.el | 33 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/ring-tests.el | 37 |
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 | |||
| 1777 | room for the inserted element. | 1777 | room for the inserted element. |
| 1778 | @end defun | 1778 | @end defun |
| 1779 | 1779 | ||
| 1780 | @defun ring-resize ring size | ||
| 1781 | Set the size of @var{ring} to @var{size}. If the new size is smaller, | ||
| 1782 | then 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 |
| 1782 | use the ring as a first-in-first-out queue. For example: | 1787 | use the ring as a first-in-first-out queue. For example: |
| @@ -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 |
| 1219 | are implemented in C using the Jansson library. | 1219 | are 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))) | 196 | If the new size is smaller, then the oldest items in the ring are |
| 197 | (setcdr ring (cons length new-vec)) | 197 | discarded." |
| 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) |