00001 /*! \file cyclic_buffer.c 00002 This file contains a basic implementation of cyclic buffer. 00003 */ 00004 00005 #include "cyclic_buffer.h" 00006 00007 00008 /*! \brief Create a new cyclic buffer. 00009 \param size Maximum number of elements of the buffer. 00010 \return The function return a handle on the newly vreated cyclic buffer, or NULL if an error occured (out of memory). 00011 \warning The function create_cyclic_buffer() allocates memory (using malloc()). Therefore, when you don't need the 00012 buffer anymore, you should destry it using destroy_cyclic_buffer(). 00013 */ 00014 00015 cyclic_buffer create_cyclic_buffer (unsigned long size) 00016 { 00017 cyclic_buffer buffer; 00018 unsigned long i; 00019 00020 /* ======================================================= */ 00021 /* Allocate new data structure */ 00022 /* ======================================================= */ 00023 00024 buffer = (cyclic_buffer)malloc(sizeof(struct s_cyclic_buffer)); 00025 if (buffer == NULL) { return NULL; } 00026 00027 buffer->buffer = (void**)malloc(size*sizeof(void*)); 00028 if (buffer->buffer == NULL) 00029 { 00030 free (buffer); 00031 return NULL; 00032 } 00033 00034 /* ======================================================= */ 00035 /* Initialize data structure */ 00036 /* ======================================================= */ 00037 00038 for (i=0; i<size; i++) { (buffer->buffer)[i] = NULL; } 00039 buffer->size = size; 00040 buffer->start = 0; 00041 buffer->stop = 0; 00042 buffer->current = 0; 00043 buffer->current_size = 0; 00044 buffer->n = 0; 00045 00046 return buffer; 00047 } 00048 00049 /*! \example test_cyclic_buffer.c 00050 This file shows how to use the function create_cyclic_buffer(). 00051 */ 00052 00053 /*! \brief Destroy a cyclic buffer (free all allocated memory). 00054 \param buffer Handle to the cyclic buffer to destroy. 00055 */ 00056 00057 void destroy_cyclic_buffer (cyclic_buffer buffer) 00058 { 00059 unsigned long i; 00060 00061 /* ======================================================= */ 00062 /* Free all alocated memory */ 00063 /* ======================================================= */ 00064 00065 for (i=0; i<buffer->size; i++) 00066 { 00067 if ((buffer->buffer)[i] != NULL) { free ((buffer->buffer)[i]); } 00068 } 00069 00070 free (buffer->buffer); 00071 free (buffer); 00072 } 00073 00074 /*! \example test_cyclic_buffer.c 00075 This file shows how to use the function destroy_cyclic_buffer(). 00076 */ 00077 00078 /*! \brief Add a new element to the cyclic buffer. 00079 \param buffer Handle to the cyclic buffer that will be used to receive the new element. 00080 \param element Pointer to the element to add to the cyclic buffer. 00081 \param element_size Size (in bytes) of the element to add. 00082 \return If succees, the function returns a pointer to the element in the cyclic buffer. Otherwise, if an error occured, 00083 the function returns NULL. 00084 \warning Please note that the element is <B>copied</B> into the cyclic buffer. This implies that memory is allocated. 00085 */ 00086 00087 void* cyclic_buffer_add_element (cyclic_buffer buffer, void* element, unsigned element_size) 00088 { 00089 void *elem; 00090 00091 /* ======================================================== */ 00092 /* Delete element if necessary */ 00093 /* ======================================================== */ 00094 00095 if ((buffer->buffer)[buffer->stop] != NULL) 00096 { 00097 free ((buffer->buffer)[buffer->stop]); 00098 (buffer->buffer)[buffer->stop] = NULL; 00099 } 00100 00101 /* ======================================================== */ 00102 /* Allocate new element */ 00103 /* ======================================================== */ 00104 00105 (buffer->buffer)[buffer->stop] = (void*)malloc(element_size); 00106 if ((buffer->buffer)[buffer->stop] == NULL) { return NULL; } 00107 00108 /* ======================================================== */ 00109 /* Copy element */ 00110 /* ======================================================== */ 00111 00112 memcpy ((buffer->buffer)[buffer->stop], element, element_size); 00113 elem = (buffer->buffer)[buffer->stop]; 00114 00115 /* ======================================================== */ 00116 /* update indexes */ 00117 /* ======================================================== */ 00118 00119 buffer->stop = (buffer->stop + 1) % buffer->size; 00120 if (buffer->stop == buffer->start) { buffer->start = (buffer->stop + 1) % buffer->size; } 00121 00122 /* ======================================================== */ 00123 /* One more element */ 00124 /* ======================================================== */ 00125 00126 if (buffer->current_size < buffer->size) { buffer->current_size += 1; } 00127 00128 return elem; 00129 } 00130 00131 /*! \example test_cyclic_buffer.c 00132 This file shows how to use the function add_element(). 00133 */ 00134 00135 00136 /*! \brief Reset the current buffer's pointer (used to extract element from the buffer). 00137 \param buffer Handle to the cyclic buffer. 00138 */ 00139 00140 void rewind_cyclic_buffer (cyclic_buffer buffer) 00141 { 00142 buffer->current = buffer->start; 00143 buffer->n = 0; 00144 } 00145 00146 /*! \example test_cyclic_buffer.c 00147 This file shows how to use the function rewind_cyclic_buffer(). 00148 */ 00149 00150 /*! \brief Returns the current element of the cyclic buffer. 00151 \param buffer Handle to the cyclic buffer. 00152 \return The function returns a pointer to the current buffer's element, or NULL if the buffer's pointer reached the end 00153 of the buffer. 00154 \warning Before calling get_element(), you should call rewind_cyclic_buffer() first. 00155 */ 00156 00157 void* cyclic_buffer_get_element(cyclic_buffer buffer) 00158 { 00159 void *elem; 00160 00161 if (buffer->n >= buffer->current_size) { buffer->n = 0; return NULL; } 00162 00163 elem = (buffer->buffer)[buffer->current]; 00164 buffer->current = (buffer->current + 1) % buffer->size; 00165 (buffer->n)++; 00166 00167 return elem; 00168 } 00169 00170 /*! \example test_cyclic_buffer.c 00171 This file shows how to use the function get_element(). 00172 */ 00173 00174 /*! \brief Return the index of the first element in the buffer. 00175 \param buffer Handle to the cyclic buffer. 00176 \return The function returns the index of the first element in the buffer. 00177 */ 00178 00179 unsigned long cyclic_buffer_get_start(cyclic_buffer buffer) { return buffer->start; } 00180 00181 /*! \example test_cyclic_buffer.c 00182 This file shows how to use the function get_start(). 00183 */ 00184 00185 /*! \brief Return the index of the last element in the buffer. 00186 \param buffer Handle to the cyclic buffer. 00187 \return The function returns the index of the last element in the buffer. 00188 */ 00189 00190 unsigned long cyclic_buffer_get_stop(cyclic_buffer buffer) { return buffer->stop; } 00191 00192 /*! \example test_cyclic_buffer.c 00193 This file shows how to use the function get_stop(). 00194 */ 00195 00196 /*! \brief Return the number of elements in the cyclic buffer. 00197 \param buffer Handle to the cyclic buffer. 00198 \return The function returns the number of elements in the cyclic buffer. 00199 */ 00200 00201 unsigned long cyclic_buffer_get_current_size(cyclic_buffer buffer) { return buffer->current_size; } 00202 00203 /*! \example test_cyclic_buffer.c 00204 This file shows how to use the function get_current_size(). 00205 */ 00206 00207