libisdn
mfifo.c
Go to the documentation of this file.
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 }