Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Related Pages

ringbuffer.c

00001 /* 00002 00003 The BLAH library, a container library 00004 Copyright (C) 1997-2004 The CDG Team <cdg@nats.informatik.uni-hamburg.de> 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 00020 Contact: blah@nats.informatik.uni-hamburg.de 00021 00022 $Id: ringbuffer.c,v 1.5 2004/09/23 15:46:39 micha Exp $ 00023 00024 */ 00025 00026 /* ------------------------------------------------------------------- */ 00027 /* ---------------------------------------------------------------------- 00028 * @defgroup Ringbuffer Ringbuffers 00029 * Implementation of ring buffers. 00030 * 00031 * It is similar to the vector that stores a series of objects,though the head 00032 * and the tail are attached inorder to enhance cyclic operations. 00033 * @{ 00034 */ 00035 00036 #include <stdio.h> 00037 #include <string.h> 00038 #include "blah.h" 00039 00040 /* ---------------------------------------------------------------------- 00041 * internal representation of the ring buffer. 00042 */ 00043 struct RingBufferStruct { 00044 int first; /**< index of first item */ 00045 int last; /**< index of the item after the last item */ 00046 int count; /**< number of entries */ 00047 int capacity; /**< capacity of table */ 00048 Pointer *entries; /**< table of entries */ 00049 }; 00050 00051 /* ---------------------------------------------------------------------- 00052 * creates a new ringbuffer. 00053 * 00054 * @param capacity specifies the capacity with which the new ringbuffer has to be created. 00055 * @returns a new ringBuffer with the size \a capacity. 00056 */ 00057 RingBuffer rbNew(int capacity) 00058 { 00059 RingBuffer rb; 00060 00061 if(capacity <= 0) { 00062 capacity = 1; 00063 } 00064 00065 rb = (RingBuffer)memMalloc(sizeof(RingBufferStruct)); 00066 rb->first = 0; 00067 rb->last = 0; 00068 rb->count = 0; 00069 rb->capacity = capacity; 00070 rb->entries = (Pointer *)memMalloc(sizeof(Pointer)*capacity); 00071 00072 return (rb); 00073 } 00074 00075 /* ---------------------------------------------------------------------- 00076 * deletes a ringbuffer. 00077 * 00078 * @param rb the ringbuffer that is to be deleted. 00079 */ 00080 void rbDelete(RingBuffer rb) 00081 { 00082 memFree(rb->entries); 00083 memFree(rb); 00084 } 00085 00086 /* ---------------------------------------------------------------------- 00087 * checks if the given ringbuffer is empty. 00088 * 00089 * @param rb ringbuffer that is to be checked. 00090 * @returns \a TRUE if the buffer is empty and \a FALSE otherwise. 00091 */ 00092 Boolean rbIsEmpty(RingBuffer rb) 00093 { 00094 return (rb->count == 0); 00095 } 00096 00097 /* ---------------------------------------------------------------------- 00098 * checks if a given ring buffer is full. 00099 * 00100 * @param rb ringbuffer that is to be checked 00101 * @returns \a TRUE if buffer is full and \a FALSE otherwise. 00102 */ 00103 Boolean rbIsFull(RingBuffer rb) 00104 { 00105 return (rb->count == rb->capacity); 00106 } 00107 00108 /* ---------------------------------------------------------------------- 00109 * adds a new element to the top of a ring buffer. 00110 * 00111 * @param rb ringbuffer to which addition has to be done. 00112 * @param element element that has to be added to the ring buffer. 00113 * @returns the number of elements in the buffer 00114 */ 00115 int rbAddTopElement(RingBuffer rb, Pointer element) 00116 { 00117 if (rbIsFull(rb)) { 00118 /* a buffer has limited capacity, so no resizing here */ 00119 fprintf(stderr, "WARNING: rbAddTopElement: buffer overflow\n"); 00120 abort(); 00121 } 00122 00123 rb->entries[rb->last] = element; 00124 rb->last++; 00125 if(rb->last == rb->capacity) 00126 rb->last = 0; 00127 00128 return (++rb->count); 00129 } 00130 00131 /* ---------------------------------------------------------------------- 00132 * adds a new element to the bottom of a ring buffer. 00133 * 00134 * @param rb ringbuffer to which addition has to be done. 00135 * @param element element that has to be added to the ring buffer. 00136 * @returns the number of elements in the buffer. 00137 */ 00138 int rbAddBottomElement(RingBuffer rb, Pointer element) 00139 { 00140 if (rbIsFull(rb)) { 00141 /* a buffer has limited capacity, so no resizing here */ 00142 fprintf(stderr, "WARNING: rbAddBottomElement: buffer overflow\n"); 00143 abort(); 00144 } 00145 00146 rb->first--; 00147 if (rb->first < 0) 00148 rb->first = rb->capacity-1; 00149 00150 rb->entries[rb->first] = element; 00151 00152 return (++rb->count); 00153 } 00154 00155 /* ---------------------------------------------------------------------- 00156 * returns the last inserted element without removing it. 00157 * 00158 * @param rb ringbuffer from which top element is returned. 00159 * @returns the last inserted element from the ring buffer rb. 00160 */ 00161 Pointer rbTopPeek(RingBuffer rb) 00162 { 00163 if (rbIsEmpty(rb)) { 00164 fprintf(stderr, "WARNING: rbTopPeek: buffer empty\n"); 00165 abort(); 00166 } else { 00167 if (rb->last) 00168 return (rb->entries[rb->last-1]); 00169 else 00170 return (rb->entries[rb->capacity-1]); 00171 } 00172 } 00173 00174 /* ---------------------------------------------------------------------- 00175 * returns the first inserted element without removing it. 00176 * 00177 * @param rb ringbuffer from which the bottom element is returned. 00178 * @returns the first inserted element from the ringbuffer rb. 00179 */ 00180 Pointer rbBottomPeek(RingBuffer rb) 00181 { 00182 if (rbIsEmpty(rb)) { 00183 fprintf(stderr, "WARNING: rbBottomPeek: buffer empty\n"); 00184 abort(); 00185 } else { 00186 return (rb->entries[rb->first]); 00187 } 00188 } 00189 00190 /* ---------------------------------------------------------------------- 00191 * finds the current size of the buffer. 00192 * 00193 * @param rb ringbuffer whose size is returned. 00194 * @returns the current number of elements in the buffer. 00195 */ 00196 int rbSize(RingBuffer rb) 00197 { 00198 return (rb->count); 00199 } 00200 00201 /*---------------------------------------------------------------------- 00202 * finds the maximum capacity of the specified buffer. 00203 * 00204 * @param rb ringbuffer whose maximum capacity is returned. 00205 * @returns the maximum number of elements the buffer rb can hold. 00206 */ 00207 int rbCapacity(RingBuffer rb) 00208 { 00209 return (rb->capacity); 00210 } 00211 00212 /* ---------------------------------------------------------------------- 00213 * removes the element from the top of the buffer. 00214 * 00215 * @param rb ringbuffer from which the removal is done. 00216 * @returns the last inserted element in the buffer rb. 00217 */ 00218 Pointer rbRemoveTopElement(RingBuffer rb) 00219 { 00220 if (rbIsEmpty(rb)) { 00221 fprintf(stderr, "WARNING: rbRemoveTopElement: buffer empty\n"); 00222 abort(); 00223 } else { 00224 if(rb->last) 00225 rb->last--; 00226 else 00227 rb->last = rb->capacity-1; 00228 00229 rb->count--; 00230 return (rb->entries[rb->last]); 00231 } 00232 } 00233 00234 /* ---------------------------------------------------------------------- 00235 * removes the element from the bottom of the buffer. 00236 * 00237 * @param rb ringbuffer from which the removal is done. 00238 * @returns the first inserted element in the buffer rb. 00239 */ 00240 Pointer rbRemoveBottomElement(RingBuffer rb) 00241 { 00242 if (rbIsEmpty(rb)) { 00243 fprintf(stderr, "WARNING: rbRemoveBottomElement: buffer empty\n"); 00244 abort(); 00245 } else { 00246 Pointer element = rb->entries[rb->first]; 00247 if(++rb->first == rb->capacity) 00248 rb->first = 0; 00249 rb->count--; 00250 return element; 00251 } 00252 } 00253 00254 /* ---------------------------------------------------------------------- 00255 * checks if the ringbuffer contains a specified element. 00256 * 00257 * @param rb ringbuffer in which the search has to be made. 00258 * @param element the element to be seached in the ringbuffer rb. 00259 * @returns \a TRUE if the buffer contains element, \a FALSE otherwise. 00260 */ 00261 Boolean rbContains(RingBuffer rb, Pointer element) 00262 { 00263 int i; 00264 00265 i = rb->first; 00266 while(i != rb->last) { 00267 if (rb->entries[i] == element) 00268 return TRUE; 00269 if(++i == rb->capacity) 00270 i = 0; 00271 } 00272 00273 return FALSE; 00274 } 00275 00276 /* ---------------------------------------------------------------------- 00277 * makes a copy of the container from \a src to \a dst. 00278 * 00279 * @param src this refers to the source ring buffer that has to be copied to the destination buffer. 00280 * @param dst this refers to the destination buffer into which the copying has been done. 00281 * @returns the dst ringbuffer after copying. 00282 */ 00283 RingBuffer rbCopy(RingBuffer dst, RingBuffer src) 00284 { 00285 if (dst->capacity < src->capacity) { 00286 dst->entries = (Pointer *) 00287 memRealloc(dst->entries, sizeof(Pointer) * src->capacity); 00288 } 00289 00290 memcpy(dst->entries, src->entries, sizeof(Pointer) * src->capacity); 00291 00292 dst->count = src->count; 00293 dst->capacity = src->capacity; 00294 dst->first = src->first; 00295 dst->last = src->last; 00296 00297 return dst; 00298 } 00299 00300 /* ---------------------------------------------------------------------- 00301 * makes a new copy of the ring buffer. 00302 * 00303 * @param src source of the ringbuffer to be cloned. 00304 * @returns a new copy of a ring buffer after cloning. 00305 */ 00306 RingBuffer rbClone(RingBuffer src) 00307 { 00308 RingBuffer dst; 00309 00310 dst = rbNew(src->capacity); 00311 return (rbCopy(dst, src)); 00312 } 00313 00314 /* ---------------------------------------------------------------------- 00315 * iterate over all items in the ring buffer and apply a function 00316 * 00317 * @param rb this is the ring buffer in which the iteration is done. 00318 * @param f this is the function that is used for the iteration in the ring buffer rb. 00319 * @param data determines the data in the ringbuffer. 00320 */ 00321 void rbForEachWithData(RingBuffer rb, VoidFunction *f, Pointer data) 00322 { 00323 int i; 00324 00325 i = rb->first; 00326 while(i != rb->last) { 00327 f(rb->entries[i], data); 00328 if(++i == rb->capacity) 00329 i = 0; 00330 } 00331 } 00332 00333 /* ---------------------------------------------------------------------- 00334 * empties the buffer. 00335 * 00336 * @param rb refers to the buffer that is to be emptied. 00337 */ 00338 void rbClear(RingBuffer rb) 00339 { 00340 rb->first = rb->last = rb->count = 0; 00341 } 00342 00343 /* ---------------------------------------------------------------------- */ 00344 /* -- ENDOFFILE --------------------------------------------------------- */ 00345 /** @} */ 00346 00347

BLAH 0.95 (20 Oct 2004)