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