Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /**
     18  ******************************************************************************
     19  * @file         M4OSA_FileReader_optim.c
     20  * @brief
     21  * @note         This file implements functions to manipulate filesystem access
     22  ******************************************************************************
     23 */
     24 
     25 /** Addition of Trace ID **/
     26 #include "M4OSA_CoreID.h"
     27 #include "M4OSA_Error.h"
     28 
     29 #ifdef M4TRACE_ID
     30 #undef M4TRACE_ID
     31 #endif
     32 #define M4TRACE_ID    M4OSA_FILE_READER
     33 
     34 
     35 #include "M4OSA_FileCommon.h"
     36 #include "M4OSA_FileReader.h"
     37 #include "M4OSA_FileWriter.h"
     38 #include "M4OSA_Memory.h"
     39 #include "M4OSA_Debug.h"
     40 
     41 #include "LVOSA_FileReader_optim.h"
     42 
     43 #define M4OSA_READER_OPTIM_USE_OSAL_IF
     44 #ifndef M4OSA_READER_OPTIM_USE_OSAL_IF
     45     #include "M4OSA_FileAccess.h"
     46 #endif
     47 
     48 #define M4ERR_CHECK_NULL_RETURN_VALUE(retval, pointer) if ((pointer) == M4OSA_NULL) return (retval);
     49 
     50 
     51 
     52 
     53 /**
     54  ******************************************************************************
     55  * File reader cache buffers parameters (size, number of buffers, etc)
     56  ******************************************************************************
     57 */
     58 #define M4OSA_READBUFFER_SIZE    1024*16
     59 #define M4OSA_READBUFFER_NB        2
     60 #define M4OSA_READBUFFER_NONE    -1
     61 #define M4OSA_EOF               -1
     62 
     63 #define MAX_FILLS_SINCE_LAST_ACCESS    M4OSA_READBUFFER_NB*2
     64 
     65 /**
     66  ******************************************************************************
     67  * structure    M4OSA_FileReader_Buffer
     68  * @brief       This structure defines the File reader Buffers context (private)
     69  ******************************************************************************
     70 */
     71 typedef struct
     72 {
     73     M4OSA_MemAddr8      data;        /**< buffer data */
     74     M4OSA_FilePosition  size;        /**< size of the buffer */
     75     M4OSA_FilePosition  filepos;    /**< position in the file where the buffer starts */
     76     M4OSA_FilePosition  remain;        /**< data amount not already copied from buffer */
     77     M4OSA_UInt32        nbFillSinceLastAcess;    /**< To know since how many time we didn't use this buffer */
     78 } M4OSA_FileReader_Buffer_optim;
     79 
     80 /**
     81  ******************************************************************************
     82  * structure    M4OSA_FileReader_Context
     83  * @brief       This structure defines the File reader context (private)
     84  * @note        This structure is used for all File Reader calls to store the context
     85  ******************************************************************************
     86 */
     87 typedef struct
     88 {
     89     M4OSA_Bool              IsOpened;       /**< Micro state machine */
     90     M4OSA_FileAttribute     FileAttribute;  /**< Opening mode */
     91     M4OSA_FilePosition         readFilePos;    /**< Effective position of the GFL read pointer */
     92     M4OSA_FilePosition         absolutePos;    /**< Virtual position for next reading */
     93     M4OSA_FilePosition         fileSize;        /**< Size of the file */
     94 
     95     M4OSA_FileReader_Buffer_optim buffer[M4OSA_READBUFFER_NB];  /**< Read buffers */
     96 
     97     M4OSA_Void*             aFileDesc;  /**< File descriptor */
     98 
     99 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    100     M4OSA_FileReadPointer*     FS;            /**< Filesystem interface */
    101 #else
    102     M4OSA_FileSystem_FctPtr *FS;        /**< Filesystem interface */
    103 #endif
    104 
    105 } M4OSA_FileReader_Context_optim;
    106 
    107 /* __________________________________________________________ */
    108 /*|                                                          |*/
    109 /*|    Global function for handling low level read access    |*/
    110 /*|__________________________________________________________|*/
    111 
    112 static M4OSA_FileReadPointer* gv_NXPSW_READOPT_lowLevelFunctions;
    113 
    114 M4OSA_ERR NXPSW_FileReaderOptim_init(M4OSA_Void *lowLevel_functionPointers, M4OSA_Void *optimized_functionPointers)
    115 {
    116     M4OSA_FileReadPointer* lowLevel_fp  = (M4OSA_FileReadPointer*) lowLevel_functionPointers;
    117     M4OSA_FileReadPointer* optimized_fp = (M4OSA_FileReadPointer*) optimized_functionPointers;
    118 
    119     //Set the optimized functions, to be called by the user
    120     optimized_fp->openRead  = M4OSA_fileReadOpen_optim;
    121     optimized_fp->readData  = M4OSA_fileReadData_optim;
    122     optimized_fp->seek      = M4OSA_fileReadSeek_optim;
    123     optimized_fp->closeRead = M4OSA_fileReadClose_optim;
    124     optimized_fp->setOption = M4OSA_fileReadSetOption_optim;
    125     optimized_fp->getOption = M4OSA_fileReadGetOption_optim;
    126 
    127 
    128     return M4NO_ERROR;
    129 }
    130 
    131 M4OSA_ERR NXPSW_FileReaderOptim_cleanUp()
    132 {
    133 
    134     gv_NXPSW_READOPT_lowLevelFunctions = M4OSA_NULL;
    135 
    136     return M4NO_ERROR;
    137 }
    138 
    139 
    140 M4OSA_ERR NXPSW_FileReaderOptim_getLowLevelFunctions(M4OSA_Void **FS)
    141 {
    142     M4OSA_FileReadPointer** pFunctionsPointer = (M4OSA_FileReadPointer**) FS;
    143     *pFunctionsPointer = gv_NXPSW_READOPT_lowLevelFunctions;
    144     return M4NO_ERROR;
    145 }
    146 
    147 
    148 /* __________________________________________________________ */
    149 /*|                                                          |*/
    150 /*|        Buffer handling functions for Read access         |*/
    151 /*|__________________________________________________________|*/
    152 
    153 /**************************************************************/
    154 M4OSA_ERR M4OSA_FileReader_BufferInit(M4OSA_FileReader_Context_optim* apContext)
    155 /**************************************************************/
    156 {
    157     M4OSA_UInt8 i;
    158 
    159     for(i=0; i<M4OSA_READBUFFER_NB; i++)
    160     {
    161         apContext->buffer[i].data = M4OSA_NULL;
    162         apContext->buffer[i].size = 0;
    163         apContext->buffer[i].filepos = 0;
    164         apContext->buffer[i].remain = 0;
    165     }
    166 
    167     for(i=0; i<M4OSA_READBUFFER_NB; i++)
    168     {
    169         apContext->buffer[i].data = (M4OSA_MemAddr8) M4OSA_32bitAlignedMalloc(M4OSA_READBUFFER_SIZE,
    170             M4OSA_FILE_READER, (M4OSA_Char *)"M4OSA_FileReader_BufferInit");
    171         M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_ALLOC, apContext->buffer[i].data);
    172     }
    173 
    174     return M4NO_ERROR;
    175 }
    176 
    177 /**************************************************************/
    178 M4OSA_Void M4OSA_FileReader_BufferFree(M4OSA_FileReader_Context_optim* apContext)
    179 /**************************************************************/
    180 {
    181     M4OSA_Int8 i;
    182 
    183     for(i=0; i<M4OSA_READBUFFER_NB; i++)
    184         if(apContext->buffer[i].data != M4OSA_NULL)
    185             free(apContext->buffer[i].data);
    186 }
    187 
    188 /**************************************************************/
    189 M4OSA_FilePosition M4OSA_FileReader_BufferCopy(M4OSA_FileReader_Context_optim* apContext,
    190                                                M4OSA_Int8 i, M4OSA_FilePosition pos,
    191                                                M4OSA_FilePosition size, M4OSA_MemAddr8 pData)
    192 /**************************************************************/
    193 {
    194     M4OSA_FilePosition copysize;
    195     M4OSA_FilePosition offset;
    196 
    197     if(apContext->buffer[i].size == M4OSA_EOF) return M4OSA_EOF;
    198 
    199     if(   (pos < apContext->buffer[i].filepos)
    200        || (pos > (apContext->buffer[i].filepos + apContext->buffer[i].size - 1)) )
    201     {
    202         return 0; /* nothing copied */
    203     }
    204 
    205     offset = pos - apContext->buffer[i].filepos;
    206 
    207     copysize = apContext->buffer[i].size - offset;
    208     copysize = (size < copysize) ? size : copysize;
    209 
    210     memcpy((void *)pData, (void *)(apContext->buffer[i].data + offset), copysize);
    211 
    212     apContext->buffer[i].remain -= copysize;
    213     apContext->buffer[i].nbFillSinceLastAcess = 0;
    214 
    215     return copysize;
    216 }
    217 
    218 /**************************************************************/
    219 M4OSA_ERR M4OSA_FileReader_BufferFill(M4OSA_FileReader_Context_optim* apContext,
    220                                        M4OSA_Int8 i, M4OSA_FilePosition pos)
    221 /**************************************************************/
    222 {
    223     M4OSA_FilePosition     gridPos;
    224     M4OSA_FilePosition    tempPos;
    225     M4OSA_UInt32        bufferSize;
    226     M4OSA_FilePosition     diff;
    227     M4OSA_FilePosition     size;
    228     M4OSA_ERR             err = M4NO_ERROR;
    229 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    230     M4OSA_ERR             errno = M4NO_ERROR;
    231     M4OSA_UInt32         fileReadSize = 0;
    232     M4OSA_FilePosition     fileSeekPosition = 0;
    233 #else
    234     M4OSA_Int32         ret_val;
    235     M4OSA_UInt16         errno;
    236 #endif
    237 
    238     M4OSA_TRACE3_4("BufferFill  i = %d  pos = %ld  read = %ld  old = %ld", i, pos,
    239                               apContext->readFilePos, apContext->buffer[i].filepos);
    240 
    241     /* Avoid cycling statement because of EOF */
    242     if(pos >= apContext->fileSize)
    243         return M4WAR_NO_MORE_AU;
    244 
    245     /* Relocate to absolute postion if necessary */
    246     bufferSize = M4OSA_READBUFFER_SIZE;
    247     tempPos = (M4OSA_FilePosition) (pos / bufferSize);
    248     gridPos = tempPos * M4OSA_READBUFFER_SIZE;
    249     diff = gridPos - apContext->readFilePos;
    250 
    251     if(diff != 0)
    252     {
    253 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    254         fileSeekPosition = diff;
    255         errno = apContext->FS->seek(apContext->aFileDesc, M4OSA_kFileSeekCurrent,
    256                                     &fileSeekPosition);
    257         apContext->readFilePos = gridPos;
    258 
    259         if(M4NO_ERROR != errno)
    260         {
    261             err = errno;
    262             M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR1 = 0x%x", err);
    263             return err;
    264         }
    265 
    266 #else
    267         ret_val = apContext->FS->pFctPtr_Seek(apContext->aFileDesc, diff,
    268                                                M4OSA_kFileSeekCurrent, &errno);
    269         apContext->readFilePos = gridPos;
    270 
    271         if(ret_val != 0)
    272         {
    273             err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno);
    274             M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR1 = 0x%x", err);
    275             return err;
    276         }
    277 #endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/
    278     }
    279 
    280     apContext->buffer[i].filepos = apContext->readFilePos;
    281 
    282     /* Read Data */
    283 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    284     fileReadSize = M4OSA_READBUFFER_SIZE;
    285     errno = apContext->FS->readData(apContext->aFileDesc,
    286                       (M4OSA_MemAddr8)apContext->buffer[i].data, &fileReadSize);
    287 
    288     size = (M4OSA_FilePosition)fileReadSize;
    289     if ((M4NO_ERROR != errno)&&(M4WAR_NO_DATA_YET != errno))
    290     {
    291         apContext->buffer[i].size = M4OSA_EOF;
    292         apContext->buffer[i].remain = 0;
    293 
    294         err = errno;
    295         M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR2 = 0x%x", err);
    296         return err;
    297     }
    298 #else
    299     size = apContext->FS->pFctPtr_Read(apContext->aFileDesc,
    300         (M4OSA_UInt8 *)apContext->buffer[i].data, M4OSA_READBUFFER_SIZE, &errno);
    301     if(size == -1)
    302     {
    303         apContext->buffer[i].size = M4OSA_EOF;
    304         apContext->buffer[i].remain = 0;
    305 
    306         err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno);
    307         M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR2 = 0x%x", err);
    308         return err;
    309     }
    310 #endif
    311 
    312     apContext->buffer[i].size = size;
    313     apContext->buffer[i].remain = size;
    314     apContext->buffer[i].nbFillSinceLastAcess = 0;
    315 
    316     /* Retrieve current position */
    317 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    318     errno = apContext->FS->getOption(apContext->aFileDesc,
    319                                      M4OSA_kFileReadGetFilePosition,
    320                                      (M4OSA_DataOption*) &apContext->readFilePos);
    321 
    322     if (M4NO_ERROR != errno)
    323     {
    324         err = errno;
    325         M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR3 = 0x%x", err);
    326     }
    327     else if(   (apContext->buffer[i].size >= 0)
    328        && (apContext->buffer[i].size < M4OSA_READBUFFER_SIZE) )
    329     {
    330         err = M4WAR_NO_DATA_YET;
    331         M4OSA_TRACE2_0("M4OSA_FileReader_BufferFill returns NO DATA YET");
    332         return err;
    333     }
    334 #else
    335     apContext->readFilePos = apContext->FS->pFctPtr_Tell(apContext->aFileDesc, &errno);
    336 
    337     if(   (apContext->buffer[i].size >= 0)
    338        && (apContext->buffer[i].size < M4OSA_READBUFFER_SIZE) )
    339     {
    340         err = M4WAR_NO_DATA_YET;
    341         M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR3 = 0x%x", err);
    342         return err;
    343     }
    344 #endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/
    345 
    346     /* Return without error */
    347     return M4NO_ERROR;
    348 }
    349 
    350 /**************************************************************/
    351 M4OSA_Int8 M4OSA_FileReader_BufferMatch(M4OSA_FileReader_Context_optim* apContext,
    352                                         M4OSA_FilePosition pos)
    353 /**************************************************************/
    354 {
    355     M4OSA_Int8 i;
    356 
    357 
    358     /* Select the buffer which matches with given pos */
    359     for(i=0; i<M4OSA_READBUFFER_NB; i++)
    360     {
    361         if(   (pos >= apContext->buffer[i].filepos)
    362            && (pos < (apContext->buffer[i].filepos + apContext->buffer[i].size)) )
    363         {
    364             return i;
    365         }
    366     }
    367     return M4OSA_READBUFFER_NONE;
    368 }
    369 
    370 /**************************************************************/
    371 M4OSA_Int8 M4OSA_FileReader_BufferSelect(M4OSA_FileReader_Context_optim* apContext,
    372                                          M4OSA_Int8 current_i)
    373 /**************************************************************/
    374 {
    375     M4OSA_Int8 i,j;
    376     M4OSA_FilePosition min_amount,max_amount;
    377     M4OSA_Int8 min_i,max_count;
    378 
    379     /* update nbFillSinceLastAcess field */
    380     for(i=0; i<M4OSA_READBUFFER_NB; i++)
    381     {
    382         apContext->buffer[i].nbFillSinceLastAcess ++;
    383     }
    384 
    385     /* Plan A : Scan for empty buffer */
    386     for(i=0; i<M4OSA_READBUFFER_NB; i++)
    387     {
    388         if(apContext->buffer[i].remain == 0)
    389         {
    390             return i;
    391         }
    392     }
    393 
    394     max_count = M4OSA_READBUFFER_NB;
    395     max_amount = MAX_FILLS_SINCE_LAST_ACCESS;
    396 
    397     /* Plan B : Scan for dead buffer */
    398     for(i=0; i<M4OSA_READBUFFER_NB; i++)
    399     {
    400         if(apContext->buffer[i].nbFillSinceLastAcess >= (M4OSA_UInt32) max_amount)
    401         {
    402             max_amount = apContext->buffer[i].nbFillSinceLastAcess;
    403             max_count = i;
    404         }
    405     }
    406     if(max_count<M4OSA_READBUFFER_NB)
    407     {
    408         M4OSA_TRACE2_2("DEAD BUFFER: %d, %d",max_count,apContext->buffer[max_count].nbFillSinceLastAcess);
    409         return max_count;
    410     }
    411 
    412     min_i = current_i;
    413     min_amount = M4OSA_READBUFFER_SIZE;
    414 
    415     /* Select the buffer which is the most "empty" */
    416     for(i=0; i<M4OSA_READBUFFER_NB; i++)
    417     {
    418         j = (i+current_i)%M4OSA_READBUFFER_NB;
    419 
    420         if(apContext->buffer[j].remain < min_amount)
    421         {
    422             min_amount = apContext->buffer[j].remain;
    423             min_i = j;
    424         }
    425     }
    426 
    427     return min_i;
    428 
    429 }
    430 
    431 /**************************************************************/
    432 M4OSA_ERR M4OSA_FileReader_CalculateSize(M4OSA_FileReader_Context_optim* apContext)
    433 /**************************************************************/
    434 {
    435     M4OSA_ERR            err = M4NO_ERROR;
    436 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    437     M4OSA_ERR            errno = M4NO_ERROR;
    438 #else
    439     M4OSA_Int32          ret_val;
    440     M4OSA_UInt16         errno;
    441 #endif
    442 
    443     /* go to the end of file*/
    444 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    445     errno = apContext->FS->getOption(apContext->aFileDesc, M4OSA_kFileReadGetFileSize,
    446                                         (M4OSA_DataOption*) &apContext->fileSize);
    447     if (M4NO_ERROR != errno)
    448     {
    449         err = errno;
    450         M4OSA_TRACE1_1("M4OSA_FileReader_CalculateSize ERR = 0x%x", err);
    451     }
    452 #else
    453     ret_val = apContext->FS->pFctPtr_Seek(apContext->aFileDesc, 0, M4OSA_kFileSeekEnd, &errno);
    454 
    455     if (ret_val != 0)
    456     {
    457         apContext->readFilePos = M4OSA_EOF;
    458         err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno);
    459         M4OSA_TRACE1_1("M4OSA_FileReader_CalculateSize ERR = 0x%x", err);
    460     }
    461     else
    462     {
    463         /* Retrieve size of the file */
    464         apContext->fileSize = apContext->FS->pFctPtr_Tell(apContext->aFileDesc, &errno);
    465         apContext->readFilePos = apContext->fileSize;
    466     }
    467 #endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/
    468 
    469     return err;
    470 }
    471 
    472 
    473 /* __________________________________________________________ */
    474 /*|                                                          |*/
    475 /*|                   OSAL filesystem API                    |*/
    476 /*|__________________________________________________________|*/
    477 
    478 /**
    479 ******************************************************************************
    480 * @brief       This method opens the provided fileDescriptor and returns its context.
    481 * @param       pContext:       (OUT) File reader context.
    482 * @param       pFileDescriptor :       (IN) File Descriptor of the input file.
    483 * @param       FileModeAccess :        (IN) File mode access.
    484 * @return      M4NO_ERROR: there is no error
    485 * @return      M4ERR_PARAMETER pContext or fileDescriptor is NULL
    486 * @return      M4ERR_ALLOC     there is no more memory available
    487 * @return      M4ERR_FILE_BAD_MODE_ACCESS      the file mode access is not correct (it must be either isTextMode or read)
    488 * @return      M4ERR_FILE_NOT_FOUND The file can not be opened.
    489 ******************************************************************************
    490 */
    491 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    492     M4OSA_ERR M4OSA_fileReadOpen_optim(M4OSA_Context* pContext,
    493                                        M4OSA_Void* pFileDescriptor,
    494                                        M4OSA_UInt32 FileModeAccess)
    495 #else
    496     M4OSA_ERR M4OSA_fileReadOpen_optim(M4OSA_Context* pContext,
    497                                        M4OSA_Void* pFileDescriptor,
    498                                        M4OSA_UInt32 FileModeAccess,
    499                                        M4OSA_FileSystem_FctPtr *FS)
    500 #endif
    501 {
    502     M4OSA_FileReader_Context_optim* apContext = M4OSA_NULL;
    503 
    504     M4OSA_ERR   err       = M4NO_ERROR;
    505     M4OSA_Void* aFileDesc = M4OSA_NULL;
    506     M4OSA_Bool  buffers_allocated = M4OSA_FALSE;
    507 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    508     M4OSA_ERR errno = M4NO_ERROR;
    509 #else
    510     M4OSA_UInt16 errno;
    511 #endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/
    512 
    513     M4OSA_TRACE2_3("M4OSA_fileReadOpen_optim p = 0x%p fd = %s mode = %lu", pContext,
    514                                                    pFileDescriptor, FileModeAccess);
    515 
    516     /*      Check input parameters */
    517     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pContext);
    518     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pFileDescriptor);
    519 
    520     *pContext = M4OSA_NULL;
    521 
    522     /*      Allocate memory for the File reader context. */
    523     apContext = (M4OSA_FileReader_Context_optim *)M4OSA_32bitAlignedMalloc(sizeof(M4OSA_FileReader_Context_optim),
    524                                       M4OSA_FILE_READER, (M4OSA_Char *)"M4OSA_FileReader_Context_optim");
    525 
    526     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_ALLOC, apContext);
    527 
    528     /* Set filesystem interface */
    529 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    530 
    531     /*Set the optimized functions, to be called by the user*/
    532 
    533     apContext->FS = (M4OSA_FileReadPointer*) M4OSA_32bitAlignedMalloc(sizeof(M4OSA_FileReadPointer),
    534                                        M4OSA_FILE_READER, (M4OSA_Char *)"M4OSA_FileReaderOptim_init");
    535     if (M4OSA_NULL==apContext->FS)
    536     {
    537         M4OSA_TRACE1_0("M4OSA_FileReaderOptim_init - ERROR : allocation failed");
    538         return M4ERR_ALLOC;
    539     }
    540     apContext->FS->openRead  = M4OSA_fileReadOpen;
    541     apContext->FS->readData  = M4OSA_fileReadData;
    542     apContext->FS->seek      = M4OSA_fileReadSeek;
    543     apContext->FS->closeRead = M4OSA_fileReadClose;
    544     apContext->FS->setOption = M4OSA_fileReadSetOption;
    545     apContext->FS->getOption = M4OSA_fileReadGetOption;
    546 #else
    547     apContext->FS = FS;
    548 #endif
    549 
    550     /* Verify access mode */
    551     if (   ((FileModeAccess & M4OSA_kFileAppend) != 0)
    552         || ((FileModeAccess & M4OSA_kFileRead) == 0))
    553     {
    554         err = M4ERR_FILE_BAD_MODE_ACCESS;
    555         goto cleanup;
    556     }
    557 
    558     /* Open file in read mode */
    559     if((FileModeAccess & M4OSA_kFileCreate) != 0)
    560     {
    561         err = M4ERR_FILE_BAD_MODE_ACCESS;
    562     }
    563     else
    564     {
    565         if ((FileModeAccess & M4OSA_kFileRead))
    566         {
    567             /* File is opened in read only*/
    568 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    569             errno = apContext->FS->openRead(&aFileDesc, pFileDescriptor, FileModeAccess);
    570 
    571             if ((aFileDesc == M4OSA_NULL)||(M4NO_ERROR != errno))
    572             {
    573                 /* converts the error to PSW format*/
    574                 err = errno;
    575                 M4OSA_TRACE2_1("M4OSA_fileReadOpen_optim ERR1 = 0x%x", err);
    576                 apContext->IsOpened = M4OSA_FALSE;
    577             }
    578 #else
    579             aFileDesc = apContext->FS->pFctPtr_Open(pFileDescriptor, FileModeAccess, &errno);
    580 
    581             if (aFileDesc == M4OSA_NULL)
    582             {
    583                 /* converts the error to PSW format*/
    584                 err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno);
    585                 M4OSA_TRACE2_1("M4OSA_fileReadOpen_optim ERR1 = 0x%x", err);
    586                 apContext->IsOpened = M4OSA_FALSE;
    587             }
    588 #endif
    589 
    590             else
    591             {
    592                 apContext->IsOpened = M4OSA_TRUE;
    593             }
    594         }
    595         else
    596         {
    597             err = M4ERR_FILE_BAD_MODE_ACCESS;
    598         }
    599     }
    600 
    601     if (M4NO_ERROR != err) goto cleanup;
    602 
    603     /* Allocate buffers */
    604     err = M4OSA_FileReader_BufferInit(apContext);
    605     buffers_allocated = M4OSA_TRUE;
    606 
    607     if (M4NO_ERROR != err) goto cleanup;
    608 
    609     /* Initialize parameters */
    610     apContext->fileSize = 0;
    611     apContext->absolutePos = 0;
    612     apContext->readFilePos = 0;
    613 
    614     /* Retrieve the File Descriptor*/
    615     apContext->aFileDesc = aFileDesc;
    616 
    617     /* Retrieve the File mode Access */
    618     apContext->FileAttribute.modeAccess = (M4OSA_FileModeAccess) FileModeAccess;
    619 
    620     /*Retrieve the File reader context */
    621     *pContext= (M4OSA_Context)apContext;
    622 
    623     /* Compute file size */
    624     err = M4OSA_FileReader_CalculateSize(apContext);
    625 
    626     if (M4NO_ERROR != err) goto cleanup;
    627 
    628     return M4NO_ERROR;
    629 
    630 cleanup:
    631 
    632     /* free context */
    633     if (M4OSA_NULL != apContext)
    634     {
    635         if(buffers_allocated == M4OSA_TRUE)
    636         {
    637             M4OSA_FileReader_BufferFree(apContext);
    638         }
    639 
    640         free( apContext);
    641         *pContext = M4OSA_NULL;
    642     }
    643 
    644     M4OSA_TRACE2_1 ("M4OSA_fileReadOpen_optim: returns error 0x%0x", err)
    645     return err;
    646 }
    647 
    648 /**
    649 ******************************************************************************
    650 * @brief       This method reads the 'size' bytes in the core file reader (selected by its 'context')
    651 *                      and writes the data to the 'data' pointer. If 'size' byte can not be read in the core file reader,
    652 *                      'size' parameter is updated to match the correct number of read bytes.
    653 * @param       pContext:       (IN) File reader context.
    654 * @param       pData : (OUT) Data pointer of the read data.
    655 * @param       pSize : (INOUT) Size of the data to read (in byte).
    656 * @return      M4NO_ERROR: there is no error
    657 * @return      M4ERR_PARAMETER pSize, fileDescriptor or pData is NULL
    658 * @return      M4ERR_ALLOC     there is no more memory available
    659 * @return      M4ERR_BAD_CONTEXT       provided context is not a valid one.
    660 ******************************************************************************
    661 */
    662 M4OSA_ERR M4OSA_fileReadData_optim(M4OSA_Context pContext,M4OSA_MemAddr8 pData,
    663                                                             M4OSA_UInt32* pSize)
    664 {
    665     M4OSA_FileReader_Context_optim* apContext =
    666                                      (M4OSA_FileReader_Context_optim*) pContext;
    667 
    668     M4OSA_ERR err;
    669     M4OSA_FilePosition aSize;
    670     M4OSA_FilePosition copiedSize;
    671     M4OSA_Int8 selected_buffer, current_buffer;
    672 
    673     M4OSA_TRACE3_3("M4OSA_fileReadData_optim p = 0x%p  d = 0x%p  s = %lu",
    674                                                        pContext, pData, *pSize);
    675 
    676     /* Check input parameters */
    677     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext);
    678     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pData);
    679     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pSize);
    680 
    681     if (apContext->IsOpened != M4OSA_TRUE)
    682     {
    683         return M4ERR_BAD_CONTEXT;
    684     }
    685 
    686     /* Prevent reading beyond EOF */
    687     if((*pSize > 0) && (apContext->absolutePos >= apContext->fileSize))
    688     {
    689         copiedSize = 0;
    690         err = M4WAR_NO_MORE_AU;
    691         goto cleanup;
    692     }
    693 
    694     /* Check if data can be read from a buffer */
    695     /* If not, fill one according to quantized positions */
    696     copiedSize = 0;
    697     err = M4NO_ERROR;
    698 
    699     selected_buffer = M4OSA_FileReader_BufferMatch(apContext, apContext->absolutePos);
    700 
    701     if(selected_buffer == M4OSA_READBUFFER_NONE)
    702     {
    703         selected_buffer = M4OSA_FileReader_BufferSelect(apContext, 0);
    704         err = M4OSA_FileReader_BufferFill(apContext, selected_buffer,
    705                                                         apContext->absolutePos);
    706     }
    707 
    708     if(err != M4NO_ERROR)
    709     {
    710         if(err == M4WAR_NO_DATA_YET)
    711         {
    712             if (*pSize <= (M4OSA_UInt32)apContext->buffer[selected_buffer].size)
    713             {
    714                 err = M4NO_ERROR;
    715             }
    716             else
    717             {
    718                 copiedSize = (M4OSA_UInt32)apContext->buffer[selected_buffer].size;
    719                 /*copy the content into pData*/
    720                 M4OSA_FileReader_BufferCopy(apContext, selected_buffer,
    721                                      apContext->absolutePos, copiedSize, pData);
    722                 goto cleanup;
    723             }
    724         }
    725         else
    726         {
    727             goto cleanup;
    728         }
    729     }
    730 
    731     M4OSA_TRACE3_3("read  size = %lu  buffer = %d  pos = %ld", *pSize,
    732                                        selected_buffer, apContext->absolutePos);
    733 
    734     /* Copy buffer into pData */
    735     while(((M4OSA_UInt32)copiedSize < *pSize) && (err == M4NO_ERROR))
    736     {
    737         aSize = M4OSA_FileReader_BufferCopy(apContext, selected_buffer,
    738                                             apContext->absolutePos+copiedSize,
    739                                             *pSize-copiedSize, pData+copiedSize);
    740         copiedSize += aSize;
    741 
    742         if(aSize == 0)
    743         {
    744             err = M4WAR_NO_DATA_YET;
    745         }
    746         else
    747         {
    748             if((M4OSA_UInt32)copiedSize < *pSize)
    749             {
    750                 current_buffer = selected_buffer;
    751                 selected_buffer = M4OSA_FileReader_BufferMatch(apContext,
    752                                              apContext->absolutePos+copiedSize);
    753 
    754                 if(selected_buffer == M4OSA_READBUFFER_NONE)
    755                 {
    756                     selected_buffer = M4OSA_FileReader_BufferSelect(apContext,
    757                                                                 current_buffer);
    758                     err = M4OSA_FileReader_BufferFill(apContext, selected_buffer,
    759                                              apContext->absolutePos+copiedSize);
    760 
    761                     if(err != M4NO_ERROR)
    762                     {
    763                         if(err == M4WAR_NO_DATA_YET)
    764                         {
    765                             /*If we got all the data that we wanted, we should return no error*/
    766                             if ((*pSize-copiedSize) <= (M4OSA_UInt32)apContext->buffer[selected_buffer].size)
    767                             {
    768                                 err = M4NO_ERROR;
    769                             }
    770                             /*If we did not get enough data, we will return NO_DATA_YET*/
    771 
    772                             /*copy the data read*/
    773                             aSize = M4OSA_FileReader_BufferCopy(apContext, selected_buffer,
    774                                                                apContext->absolutePos+copiedSize,
    775                                                                *pSize-copiedSize, pData+copiedSize);
    776                             copiedSize += aSize;
    777 
    778                             /*we reached end of file, so stop trying to read*/
    779                             goto cleanup;
    780                         }
    781                         if (err == M4WAR_NO_MORE_AU)
    782                         {
    783                             err = M4WAR_NO_DATA_YET;
    784 
    785                             /*copy the data read*/
    786                             aSize = M4OSA_FileReader_BufferCopy(apContext, selected_buffer,
    787                                                              apContext->absolutePos+copiedSize,
    788                                                              *pSize-copiedSize, pData+copiedSize);
    789                             copiedSize += aSize;
    790 
    791                             /*we reached end of file, so stop trying to read*/
    792                             goto cleanup;
    793 
    794                         }
    795                         else
    796                         {
    797                             goto cleanup;
    798                         }
    799                     }
    800                 }
    801             }
    802         }
    803     }
    804 
    805 cleanup :
    806 
    807     /* Update the new position of the pointer */
    808     apContext->absolutePos = apContext->absolutePos + copiedSize;
    809 
    810     if((err != M4NO_ERROR)&&(err!=M4WAR_NO_DATA_YET))
    811     {
    812         M4OSA_TRACE2_3("M4OSA_fileReadData_optim size = %ld  copied = %ld  err = 0x%x",
    813                                                            *pSize, copiedSize, err);
    814     }
    815 
    816     /* Effective copied size must be returned */
    817     *pSize = copiedSize;
    818 
    819 
    820     /* Read is done */
    821     return err;
    822 }
    823 
    824 /**
    825 ******************************************************************************
    826 * @brief       This method seeks at the provided position in the core file reader (selected by its 'context').
    827 *              The position is related to the seekMode parameter it can be either :
    828 *              From the beginning (position MUST be positive) : end position = position
    829 *              From the end (position MUST be negative) : end position = file size + position
    830 *              From the current position (signed offset) : end position = current position + position.
    831 * @param       pContext:       (IN) File reader context.
    832 * @param       SeekMode :      (IN) Seek access mode.
    833 * @param       pPosition :     (IN) Position in the file.
    834 * @return      M4NO_ERROR: there is no error
    835 * @return      M4ERR_PARAMETER Seekmode or fileDescriptor is NULL
    836 * @return      M4ERR_ALLOC     there is no more memory available
    837 * @return      M4ERR_BAD_CONTEXT       provided context is not a valid one.
    838 * @return      M4ERR_FILE_INVALID_POSITION the position cannot be reached.
    839 ******************************************************************************
    840 */
    841 M4OSA_ERR M4OSA_fileReadSeek_optim( M4OSA_Context pContext, M4OSA_FileSeekAccessMode SeekMode,
    842                                                               M4OSA_FilePosition* pPosition)
    843 {
    844     M4OSA_FileReader_Context_optim* apContext = (M4OSA_FileReader_Context_optim*) pContext;
    845     M4OSA_ERR err = M4NO_ERROR;
    846     M4OSA_TRACE3_3("M4OSA_fileReadSeek_optim p = 0x%p mode = %d pos = %d", pContext,
    847                                                              SeekMode, *pPosition);
    848 
    849     /* Check input parameters */
    850     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext);
    851     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pPosition);
    852     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, SeekMode);
    853 
    854     if (apContext->IsOpened != M4OSA_TRUE)
    855     {
    856         return M4ERR_BAD_CONTEXT;       /*< The context can not be correct */
    857     }
    858 
    859     /* Go to the desired position */
    860     switch(SeekMode)
    861     {
    862         case M4OSA_kFileSeekBeginning :
    863             if(*pPosition < 0) {
    864                 return M4ERR_PARAMETER; /**< Bad SeekAcess mode */
    865             }
    866             apContext->absolutePos = *pPosition;
    867             *pPosition = apContext->absolutePos;
    868             break;
    869 
    870         case M4OSA_kFileSeekEnd :
    871             if(*pPosition > 0) {
    872                 return M4ERR_PARAMETER; /**< Bad SeekAcess mode */
    873             }
    874             apContext->absolutePos = apContext->fileSize + *pPosition;
    875             *pPosition = apContext->absolutePos;
    876             break;
    877 
    878         case M4OSA_kFileSeekCurrent :
    879             if(((apContext->absolutePos + *pPosition) > apContext->fileSize) ||
    880                 ((apContext->absolutePos + *pPosition) < 0)){
    881                 return M4ERR_PARAMETER; /**< Bad SeekAcess mode */
    882             }
    883             apContext->absolutePos = apContext->absolutePos + *pPosition;
    884             *pPosition = apContext->absolutePos;
    885             break;
    886 
    887         default :
    888             err = M4ERR_PARAMETER; /**< Bad SeekAcess mode */
    889             break;
    890     }
    891 
    892     /* Return without error */
    893     return err;
    894 }
    895 
    896 /**
    897 ******************************************************************************
    898 * @brief       This method asks the core file reader to close the file
    899 *              (associated to the context) and also frees the context.
    900 * @param       pContext:       (IN) File reader context.
    901 * @return      M4NO_ERROR: there is no error
    902 * @return      M4ERR_BAD_CONTEXT       provided context is not a valid one.
    903 ******************************************************************************
    904 */
    905 M4OSA_ERR M4OSA_fileReadClose_optim(M4OSA_Context pContext)
    906 {
    907     M4OSA_FileReader_Context_optim* apContext = (M4OSA_FileReader_Context_optim*) pContext;
    908 
    909     M4OSA_ERR err = M4NO_ERROR;
    910 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    911     M4OSA_ERR errno = M4NO_ERROR;
    912 #else
    913     M4OSA_UInt16 errno;
    914 #endif
    915 
    916     M4OSA_TRACE2_1("M4OSA_fileReadClose_optim p = 0x%p", pContext );
    917 
    918     /* Check input parameters */
    919     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext);
    920 
    921     if (apContext->IsOpened != M4OSA_TRUE)
    922     {
    923         return M4ERR_BAD_CONTEXT;       /**< The context can not be correct */
    924     }
    925 
    926     /* buffer */
    927     M4OSA_FileReader_BufferFree(apContext);
    928 
    929     /* Close the file */
    930 #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
    931     errno = apContext->FS->closeRead(apContext->aFileDesc);
    932 
    933     if (M4NO_ERROR != errno)
    934     {
    935         /* converts the error to PSW format*/
    936         err = errno;
    937         M4OSA_TRACE2_1("M4OSA_fileReadClose_optim ERR1 = 0x%x", err);
    938     }
    939 #else
    940     aRet_Val = apContext->FS->pFctPtr_Close(apContext->aFileDesc, &errno);
    941 
    942     if (aRet_Val != 0)
    943     {
    944         /* converts the error to PSW format*/
    945         err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno);
    946         M4OSA_TRACE2_1("M4OSA_fileReadClose_optim ERR1 = 0x%x", err);
    947     }
    948 #endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/
    949 
    950     apContext->IsOpened = M4OSA_FALSE;
    951 
    952     //>>>> GLM20090212 : set the low level function statically
    953     if (apContext->FS != M4OSA_NULL)
    954     {
    955         free( apContext->FS);
    956     }
    957     //<<<< GLM20090212 : set the low level function statically
    958 
    959     /* Free the context */
    960     free(apContext);
    961 
    962     /* Return without error */
    963     return err;
    964 }
    965 
    966 /**
    967 ******************************************************************************
    968 * @brief       This is a dummy function required to maintain function pointer
    969 *              structure.
    970 * @note        This is a dummy function required to maintain function pointer
    971 *              structure.
    972 * @param       pContext:       (IN) Execution context.
    973 * @param       OptionId :      (IN) Id of the option to set.
    974 * @param       OptionValue :   (IN) Value of the option.
    975 * @return      M4NO_ERROR: there is no error
    976 ******************************************************************************
    977 */
    978 M4OSA_ERR M4OSA_fileReadSetOption_optim(M4OSA_Context pContext,
    979                                         M4OSA_FileReadOptionID OptionID,
    980                                         M4OSA_DataOption OptionValue)
    981 {
    982     M4OSA_ERR err = M4NO_ERROR;
    983     return err;
    984 }
    985 
    986 /**
    987 ******************************************************************************
    988 * @brief       This method asks the core file reader to return the value associated
    989 *              with the optionID.The caller is responsible for allocating/de-allocating
    990 *              the memory of the value field.
    991 * @note        The options handled by the component depend on the implementation
    992 *                                                               of the component.
    993 * @param       pContext:       (IN) Execution context.
    994 * @param       OptionId :      (IN) Id of the option to set.
    995 * @param       pOptionValue :  (OUT) Value of the option.
    996 * @return      M4NO_ERROR: there is no error
    997 * @return      M4ERR_BAD_CONTEXT       pContext is NULL
    998 * @return      M4ERR_BAD_OPTION_ID the option id is not valid.
    999 * @return      M4ERR_NOT_IMPLEMENTED The option is not implemented yet.
   1000 ******************************************************************************
   1001 */
   1002 M4OSA_ERR M4OSA_fileReadGetOption_optim(M4OSA_Context pContext,
   1003                                         M4OSA_FileReadOptionID OptionID,
   1004                                         M4OSA_DataOption* pOptionValue)
   1005 {
   1006     M4OSA_FileReader_Context_optim* apContext = (M4OSA_FileReader_Context_optim*) pContext;
   1007     M4OSA_ERR err = M4NO_ERROR;
   1008 
   1009     /*  Check input parameters */
   1010     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext);
   1011 
   1012     if (apContext->IsOpened != M4OSA_TRUE)
   1013     {
   1014         return M4ERR_BAD_CONTEXT;       /**< The context can not be correct */
   1015     }
   1016 
   1017     /* Get the desired option if it is avalaible */
   1018     switch(OptionID)
   1019     {
   1020         /* Get File Size */
   1021         case M4OSA_kFileReadGetFileSize:/**< Get size of the file, limited to 32 bit size */
   1022 
   1023             (*(M4OSA_UInt32 *)pOptionValue) = apContext->fileSize;
   1024             break;
   1025 
   1026         /* Check End of file Occurs */
   1027         case M4OSA_kFileReadIsEOF :     /**< See if we are at the end of the file */
   1028 
   1029             (*(M4OSA_Bool *)pOptionValue) = (apContext->absolutePos >= apContext->fileSize) ? M4OSA_TRUE : M4OSA_FALSE;
   1030             break;
   1031 
   1032         /* Get File Position */
   1033         case M4OSA_kFileReadGetFilePosition :   /**< Get file position */
   1034 
   1035             *(M4OSA_FilePosition *)pOptionValue = apContext->absolutePos;
   1036             break;
   1037 
   1038         /* Get Attribute */
   1039         case M4OSA_kFileReadGetFileAttribute :  /**< Get the file attribute = access mode */
   1040 
   1041             (*(M4OSA_FileAttribute *)pOptionValue).modeAccess = apContext->FileAttribute.modeAccess;
   1042             break;
   1043 
   1044         default:
   1045             /**< Bad option ID */
   1046             err = M4ERR_BAD_OPTION_ID;
   1047             break;
   1048     }
   1049 
   1050     /*Return without error */
   1051     return err;
   1052 }
   1053