libisdn
|
00001 /***************************************************************************** 00002 00003 Filename: mfifo.c 00004 00005 Description: mfifo is a message orriented fifo system with support of 00006 both message and byte per byte retriaval of messages. 00007 00008 The fifo has been designed with two usages in mind: 00009 00010 - Queueing of frames for hdlc and feeding out byte per byte 00011 with the possibility of re-sending of frames etc. 00012 00013 - fifo for messages of dynamic size. 00014 00015 The fifo is allocated on top of any buffer and creates an 00016 index of message in the queue. The user can write/read 00017 messages or write messages and read the message one byte 00018 at the time. 00019 00020 Interface: 00021 MFIFOCreate Create/reset/initialize fifo. 00022 MFIFOClear Clear FIFO. 00023 MFIFOWriteMes Write message into fifo 00024 * MFIFOReadMes Read message from fifo. 00025 MFIFOGetMesPtr Get ptr to next message. 00026 MFIFOKillNext Kill next message. 00027 00028 * currently not implemented. 00029 00030 Note: The message will always be saved continuously. If there is not 00031 sufficient space at the end of the buffer, the fifo will skip 00032 the last bytes and save the message at the top of the buffer. 00033 00034 This is required to allow direct ptr access to messages 00035 stored in the queue. 00036 00037 License/Copyright: 00038 00039 Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved. 00040 email:janvb@caselaboratories.com 00041 00042 Redistribution and use in source and binary forms, with or without 00043 modification, are permitted provided that the following conditions are 00044 met: 00045 00046 * Redistributions of source code must retain the above copyright notice, 00047 this list of conditions and the following disclaimer. 00048 * Redistributions in binary form must reproduce the above copyright notice, 00049 this list of conditions and the following disclaimer in the documentation 00050 and/or other materials provided with the distribution. 00051 * Neither the name of the Case Labs, Ltd nor the names of its contributors 00052 may be used to endorse or promote products derived from this software 00053 without specific prior written permission. 00054 00055 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00056 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00057 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00058 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00059 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00060 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00061 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00062 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00063 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00064 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00065 POSSIBILITY OF SUCH DAMAGE. 00066 *****************************************************************************/ 00067 00068 #include "mfifo.h" 00069 #include <stdlib.h> 00070 #include <string.h> 00071 00072 /***************************************************************************** 00073 00074 Function: MFIFOCreate 00075 00076 Description: Creates a fifo on top of an existing buffer. 00077 00078 Parameters: buf ptr to buffer. 00079 size size of buffer in bytes. 00080 index size of index entries (max no messages). 00081 00082 Return value: 0 if failure, 1 if ok. 00083 00084 *****************************************************************************/ 00085 int MFIFOCreate(unsigned char *buf, int size, int index) 00086 { 00087 MFIFO *mf = (MFIFO *)buf; 00088 00089 mf->first = mf->last = 0; 00090 mf->ixsize = index; 00091 mf->buf = &buf[sizeof(MFIFO) + (sizeof(MINDEX) * index)]; 00092 00093 if (mf->buf > &buf[size]) 00094 return 0; 00095 00096 mf->bsize = size - sizeof(MFIFO) - (sizeof(MINDEX) * index); 00097 00098 return 1; 00099 } 00100 00101 /***************************************************************************** 00102 00103 Function: MFIFOClear 00104 00105 Description: Clear the FIFO 00106 00107 Paremeters: buf ptr to fifo 00108 00109 Return Value: none 00110 00111 *****************************************************************************/ 00112 void MFIFOClear(unsigned char * buf) 00113 { 00114 MFIFO *mf = (MFIFO *)buf; 00115 00116 mf->first = mf->last = 0; 00117 } 00118 00119 /***************************************************************************** 00120 00121 Function: MFIFOGetLBOffset 00122 00123 Description: Helper function caclulating offset to the 'first out' byte. 00124 00125 Paremeters: buf ptr to fifo 00126 00127 Return Value: offset. 00128 00129 *****************************************************************************/ 00130 int MFIFOGetLBOffset(unsigned char *buf) 00131 { 00132 MFIFO *mf = (MFIFO *)buf; 00133 00134 if (mf->last != mf->first) 00135 return mf->ix[mf->last].offset; 00136 00137 return 0; 00138 } 00139 00140 /***************************************************************************** 00141 00142 Function: MFIFOGetFBOffset 00143 00144 Description: Helper function calculating the offset to the 'first in' 00145 byte in the buffer. This is the position the next byte 00146 entering the fifo will occupy. 00147 00148 Paremeters: buf ptr to fifo 00149 00150 Return Value: offset 00151 00152 *****************************************************************************/ 00153 int MFIFOGetFBOffset(unsigned char *buf) 00154 { 00155 MFIFO *mf = (MFIFO *)buf; 00156 int x; 00157 00158 if (mf->last == mf->first) 00159 return 0; 00160 00161 x = mf->first - 1; 00162 00163 if (x < 0) 00164 x = mf->ixsize - 1; 00165 00166 return mf->ix[x].offset + mf->ix[x].size; 00167 } 00168 00169 /***************************************************************************** 00170 00171 Function: MFIFOWriteIX 00172 00173 Description: Helper function writing a calculated entry. The function 00174 will perform a memcpy to move the message and set the index 00175 values as well as increase the 'first in' index. 00176 00177 Paremeters: buf ptr to fifo 00178 mes ptr to message 00179 size size of message in bytes. 00180 ix index to index entry. 00181 off offset to position to receive the message 00182 00183 Return Value: none 00184 00185 *****************************************************************************/ 00186 void MFIFOWriteIX(unsigned char *buf, unsigned char *mes, int size, int ix, int off) 00187 { 00188 MFIFO *mf = (MFIFO *)buf; 00189 int x; 00190 00191 memcpy(&mf->buf[off], mes, size); 00192 mf->ix[ix].offset = off; 00193 mf->ix[ix].size = size; 00194 00195 x = mf->first + 1; 00196 00197 if (x >= mf->ixsize) 00198 x = 0; 00199 00200 mf->first = x; 00201 } 00202 00203 /***************************************************************************** 00204 00205 Function: MFIFOWriteMes 00206 00207 Description: 00208 00209 Paremeters: 00210 00211 Return Value: 00212 00213 *****************************************************************************/ 00214 int MFIFOWriteMes(unsigned char *buf, unsigned char *mes, int size) 00215 { 00216 MFIFO *mf = (MFIFO *)buf; 00217 int of, ol, x; 00218 00219 x = mf->first + 1; 00220 00221 if (x >= mf->ixsize) 00222 x = 0; 00223 00224 if (x == mf->last) 00225 return 0; /* full queue */ 00226 00227 of = MFIFOGetFBOffset(buf); 00228 ol = MFIFOGetLBOffset(buf); 00229 if (mf->last == mf->first) { /* empty queue */ 00230 mf->first = mf->last = 0; /* optimize */ 00231 00232 MFIFOWriteIX(buf, mes, size, mf->first, 0); 00233 return 1; 00234 } 00235 else if (of > ol) { 00236 if (mf->bsize - of >= size) { 00237 MFIFOWriteIX(buf, mes, size, mf->first, of); 00238 return 1; 00239 } 00240 else if (ol > size) { 00241 MFIFOWriteIX(buf, mes, size, mf->first, ol); 00242 return 1; 00243 } 00244 } 00245 else if (ol - of > size) { 00246 MFIFOWriteIX(buf, mes, size, mf->first, of); 00247 return 1; 00248 } 00249 00250 return 0; 00251 } 00252 00253 /***************************************************************************** 00254 00255 Function: MFIFOGetMesPtr 00256 00257 Description: 00258 00259 Paremeters: 00260 00261 Return Value: 00262 00263 *****************************************************************************/ 00264 unsigned char * MFIFOGetMesPtr(unsigned char *buf, int *size) 00265 { 00266 MFIFO *mf = (MFIFO *)buf; 00267 00268 if (mf->first == mf->last) { 00269 return NULL; 00270 } 00271 00272 *size = mf->ix[mf->last].size; 00273 return &mf->buf[mf->ix[mf->last].offset]; 00274 } 00275 00276 /***************************************************************************** 00277 00278 Function: MFIFOKillNext 00279 00280 Description: 00281 00282 Paremeters: 00283 00284 Return Value: 00285 00286 *****************************************************************************/ 00287 void MFIFOKillNext(unsigned char *buf) 00288 { 00289 MFIFO *mf = (MFIFO *)buf; 00290 int x; 00291 00292 if (mf->first != mf->last) { 00293 x = mf->last + 1; 00294 if (x >= mf->ixsize) { 00295 x = 0; 00296 } 00297 00298 mf->last = x; 00299 } 00300 } 00301 00302 00303 /* 00304 * Queue-style accessor functions 00305 */ 00306 00311 unsigned char * MFIFOGetMesPtrOffset(unsigned char *buf, int *size, const int pos) 00312 { 00313 MFIFO *mf = (MFIFO *)buf; 00314 int x; 00315 00316 if (mf->first == mf->last) { 00317 return NULL; 00318 } 00319 00320 if (pos < 0 || pos >= mf->ixsize) { 00321 return NULL; 00322 } 00323 00324 x = pos - mf->last; 00325 if (x < 0) { 00326 x += (mf->ixsize - 1); 00327 } 00328 00329 *size = mf->ix[x].size; 00330 return &mf->buf[mf->ix[x].offset]; 00331 } 00332 00333 00338 int MFIFOGetMesCount(unsigned char *buf) 00339 { 00340 MFIFO *mf = (MFIFO *)buf; 00341 00342 if (mf->first == mf->last) { 00343 return 0; 00344 } 00345 else if (mf->first > mf->last) { 00346 return mf->first - mf->last; 00347 } 00348 else { 00349 return (mf->ixsize - mf->last) + mf->first; 00350 } 00351 } 00352 00357 int MFIFOWriteMesOverwrite(unsigned char *buf, unsigned char *mes, int size) 00358 { 00359 MFIFO *mf = (MFIFO *)buf; 00360 int of, ol, x; 00361 00362 x = mf->first + 1; 00363 00364 if (x >= mf->ixsize) 00365 x = 0; 00366 00367 if (x == mf->last) { 00368 /* advance last pointer */ 00369 mf->last++; 00370 00371 if (mf->last >= mf->ixsize) 00372 mf->last = 0; 00373 } 00374 00375 of = MFIFOGetFBOffset(buf); 00376 ol = MFIFOGetLBOffset(buf); 00377 00378 if (mf->last == mf->first) { /* empty queue */ 00379 mf->first = mf->last = 0; /* optimize */ 00380 00381 MFIFOWriteIX(buf, mes, size, mf->first, 0); 00382 return 1; 00383 } 00384 else if (of > ol) { 00385 if (mf->bsize - of >= size) { 00386 MFIFOWriteIX(buf, mes, size, mf->first, of); 00387 return 1; 00388 } 00389 else if (ol > size) { 00390 MFIFOWriteIX(buf, mes, size, mf->first, ol); 00391 return 1; 00392 } 00393 } 00394 else if (ol - of > size) { 00395 MFIFOWriteIX(buf, mes, size, mf->first, of); 00396 return 1; 00397 } 00398 return 0; 00399 }