aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond1993-04-25 22:26:48 +0000
committerEric S. Raymond1993-04-25 22:26:48 +0000
commitd3af54acef262f6340231fb409978374dc91716c (patch)
treec81b2d6eb2b2541f80e837d41c2274fc94bc070e
parent5b08a462d2e2cb35cd8dbe1d3bcb275883cfa997 (diff)
downloademacs-d3af54acef262f6340231fb409978374dc91716c.tar.gz
emacs-d3af54acef262f6340231fb409978374dc91716c.zip
Rewritten. A poor choice of representation made the old code excessively
complex. The new version is smaller and faster. The interface is unchanged, except that ring-remove now accepts an optional numeric argument specifying the element to remove.
-rw-r--r--lisp/emacs-lisp/ring.el73
1 files changed, 46 insertions, 27 deletions
diff --git a/lisp/emacs-lisp/ring.el b/lisp/emacs-lisp/ring.el
index eedc801e16a..28f568d17fd 100644
--- a/lisp/emacs-lisp/ring.el
+++ b/lisp/emacs-lisp/ring.el
@@ -24,15 +24,15 @@
24;;; Commentary: 24;;; Commentary:
25 25
26;;; This code defines a ring data structure. A ring is a 26;;; This code defines a ring data structure. A ring is a
27;;; (hd-index tl-index . vector) 27;;; (hd-index length . vector)
28;;; list. You can insert to, remove from, and rotate a ring. When the ring 28;;; list. You can insert to, remove from, and rotate a ring. When the ring
29;;; fills up, insertions cause the oldest elts to be quietly dropped. 29;;; fills up, insertions cause the oldest elts to be quietly dropped.
30;;; 30;;;
31;;; In ring-ref, 0 is the index of the newest element. Higher indexes 31;;; In ring-ref, 0 is the index of the newest element. Higher indexes
32;;; correspond to older elements until they wrap. 32;;; correspond to older elements until they wrap.
33;;; 33;;;
34;;; HEAD = index of the newest item on the ring. 34;;; hd-index = index of the newest item on the ring.
35;;; TAIL = index of the oldest item on the ring. 35;;; length = number of ring items.
36;;; 36;;;
37;;; These functions are used by the input history mechanism, but they can 37;;; These functions are used by the input history mechanism, but they can
38;;; be used for other purposes as well. 38;;; be used for other purposes as well.
@@ -49,7 +49,7 @@
49;;;###autoload 49;;;###autoload
50(defun make-ring (size) 50(defun make-ring (size)
51 "Make a ring that can contain SIZE elements." 51 "Make a ring that can contain SIZE elements."
52 (cons 1 (cons 0 (make-vector (+ size 1) nil)))) 52 (cons 0 (cons 0 (make-vector size nil))))
53 53
54(defun ring-plus1 (index veclen) 54(defun ring-plus1 (index veclen)
55 "INDEX+1, with wraparound" 55 "INDEX+1, with wraparound"
@@ -62,29 +62,50 @@
62 62
63(defun ring-length (ring) 63(defun ring-length (ring)
64 "Number of elements in the ring." 64 "Number of elements in the ring."
65 (let ((hd (car ring)) (tl (car (cdr ring))) (siz (length (cdr (cdr ring))))) 65 (car (cdr ring)))
66 (let ((len (if (<= hd tl) (+ 1 (- tl hd)) (+ 1 tl (- siz hd)))))
67 (if (= len siz) 0 len))))
68 66
69(defun ring-empty-p (ring) 67(defun ring-empty-p (ring)
70 (= 0 (ring-length ring))) 68 (= 0 (car (cdr ring))))
69
70(defun ring-index (index head ringlen veclen)
71 (setq index (ring-mod index ringlen))
72 (ring-mod (1- (+ head (- ringlen index))) veclen))
71 73
72(defun ring-insert (ring item) 74(defun ring-insert (ring item)
73 "Insert a new item onto the ring. If the ring is full, dump the oldest 75 "Insert a new item onto the ring. If the ring is full, dump the oldest
74item to make room." 76item to make room."
75 (let* ((vec (cdr (cdr ring))) (len (length vec)) 77 (let* ((vec (cdr (cdr ring)))
76 (new-hd (ring-minus1 (car ring) len))) 78 (veclen (length vec))
77 (setcar ring new-hd) 79 (hd (car ring))
78 (aset vec new-hd item) 80 (ln (car (cdr ring))))
79 (if (ring-empty-p ring) ;overflow -- dump one off the tail. 81 (prog1
80 (setcar (cdr ring) (ring-minus1 (car (cdr ring)) len))))) 82 (aset vec (ring-mod (+ hd ln) veclen) item)
81 83 (if (= ln veclen)
82(defun ring-remove (ring) 84 (setcar ring (ring-plus1 hd veclen))
83 "Remove the oldest item retained on the ring." 85 (setcar (cdr ring) (1+ ln))))))
84 (if (ring-empty-p ring) (error "Ring empty") 86
85 (let ((tl (car (cdr ring))) (vec (cdr (cdr ring)))) 87(defun ring-remove (ring &optional index)
86 (setcar (cdr ring) (ring-minus1 tl (length vec))) 88 "Remove an item from the RING. Return the removed item.
87 (aref vec tl)))) 89If optional INDEX is nil, remove the oldest item. If it's
90numeric, remove the element indexed."
91 (if (ring-empty-p ring)
92 (error "Ring empty")
93 (let* ((hd (car ring))
94 (ln (car (cdr ring)))
95 (vec (cdr (cdr ring)))
96 (veclen (length vec))
97 (tl (ring-mod (1- (+ hd ln)) veclen))
98 oldelt)
99 (if (null index)
100 (setq index (1- ln)))
101 (setq index (ring-index index hd ln veclen))
102 (setq oldelt (aref vec index))
103 (while (/= index tl)
104 (aset vec index (aref vec (ring-plus1 index veclen)))
105 (setq index (ring-plus1 index veclen)))
106 (aset vec tl nil)
107 (setcar (cdr ring) (1- ln))
108 oldelt)))
88 109
89(defun ring-mod (n m) 110(defun ring-mod (n m)
90 "Returns N mod M. M is positive. 111 "Returns N mod M. M is positive.
@@ -99,12 +120,10 @@ Answer is guaranteed to be non-negative, and less than m."
99INDEX need not be <= the ring length, the appropriate modulo operation 120INDEX need not be <= the ring length, the appropriate modulo operation
100will be performed. Element 0 is the most recently inserted; higher indices 121will be performed. Element 0 is the most recently inserted; higher indices
101correspond to older elements until they wrap." 122correspond to older elements until they wrap."
102 (let ((numelts (ring-length ring))) 123 (if (ring-empty-p ring)
103 (if (= numelts 0) (error "indexed empty ring") 124 (error "indexed empty ring")
104 (let* ((hd (car ring)) (tl (car (cdr ring))) (vec (cdr (cdr ring))) 125 (let* ((hd (car ring)) (ln (car (cdr ring))) (vec (cdr (cdr ring))))
105 (index (ring-mod index numelts)) 126 (aref vec (ring-index index hd ln (length vec))))))
106 (vec-index (ring-mod (+ index hd) (length vec))))
107 (aref vec vec-index)))))
108 127
109(provide 'ring) 128(provide 'ring)
110 129