LVOSA_FileReader_optim.c revision 855ec7c4be7ad642721909d5837a8d25a117c22f
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_malloc(M4OSA_READBUFFER_SIZE, M4OSA_FILE_READER, "M4OSA_FileReader_BufferInit");
171        M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_ALLOC, apContext->buffer[i].data);
172    }
173
174    return M4NO_ERROR;
175}
176
177/**************************************************************/
178M4OSA_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            M4OSA_free((M4OSA_MemAddr32)apContext->buffer[i].data);
186}
187
188/**************************************************************/
189M4OSA_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    M4OSA_memcpy(pData, 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/**************************************************************/
219M4OSA_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/**************************************************************/
351M4OSA_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/**************************************************************/
371M4OSA_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/**************************************************************/
432M4OSA_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#if 0
453    fileSeekPosition = 0;
454    errno = apContext->FS->seek(apContext->aFileDesc, M4OSA_kFileSeekEnd, &fileSeekPosition);
455
456    if (M4NO_ERROR != errno)
457    {
458        apContext->readFilePos = M4OSA_EOF;
459        err = errno;
460        M4OSA_TRACE1_1("M4OSA_FileReader_CalculateSize ERR1 = 0x%x", err);
461    }
462    else
463    {
464        /* Retrieve size of the file */
465        errno = apContext->FS->getOption(apContext->aFileDesc,
466                                         M4OSA_kFileReadGetFilePosition,
467                                         (M4OSA_DataOption*) &apContext->fileSize);
468        if (M4NO_ERROR != errno)
469        {
470            err = errno;
471            M4OSA_TRACE1_1("M4OSA_FileReader_CalculateSize ERR2 = 0x%x", err);
472        }
473        apContext->readFilePos = apContext->fileSize;
474    }
475#endif
476#else
477    ret_val = apContext->FS->pFctPtr_Seek(apContext->aFileDesc, 0, M4OSA_kFileSeekEnd, &errno);
478
479    if (ret_val != 0)
480    {
481        apContext->readFilePos = M4OSA_EOF;
482        err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno);
483        M4OSA_TRACE1_1("M4OSA_FileReader_CalculateSize ERR = 0x%x", err);
484    }
485    else
486    {
487        /* Retrieve size of the file */
488        apContext->fileSize = apContext->FS->pFctPtr_Tell(apContext->aFileDesc, &errno);
489        apContext->readFilePos = apContext->fileSize;
490    }
491#endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/
492
493    return err;
494}
495
496
497/* __________________________________________________________ */
498/*|                                                          |*/
499/*|                   OSAL filesystem API                    |*/
500/*|__________________________________________________________|*/
501
502/**
503******************************************************************************
504* @brief       This method opens the provided fileDescriptor and returns its context.
505* @param       pContext:       (OUT) File reader context.
506* @param       pFileDescriptor :       (IN) File Descriptor of the input file.
507* @param       FileModeAccess :        (IN) File mode access.
508* @return      M4NO_ERROR: there is no error
509* @return      M4ERR_PARAMETER pContext or fileDescriptor is NULL
510* @return      M4ERR_ALLOC     there is no more memory available
511* @return      M4ERR_FILE_BAD_MODE_ACCESS      the file mode access is not correct (it must be either isTextMode or read)
512* @return      M4ERR_FILE_NOT_FOUND The file can not be opened.
513******************************************************************************
514*/
515#ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
516    M4OSA_ERR M4OSA_fileReadOpen_optim(M4OSA_Context* pContext,
517                                       M4OSA_Void* pFileDescriptor,
518                                       M4OSA_UInt32 FileModeAccess)
519#else
520    M4OSA_ERR M4OSA_fileReadOpen_optim(M4OSA_Context* pContext,
521                                       M4OSA_Void* pFileDescriptor,
522                                       M4OSA_UInt32 FileModeAccess,
523                                       M4OSA_FileSystem_FctPtr *FS)
524#endif
525{
526    M4OSA_FileReader_Context_optim* apContext = M4OSA_NULL;
527
528    M4OSA_ERR   err       = M4NO_ERROR;
529    M4OSA_Void* aFileDesc = M4OSA_NULL;
530    M4OSA_Bool  buffers_allocated = M4OSA_FALSE;
531#ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
532    M4OSA_ERR errno = M4NO_ERROR;
533#else
534    M4OSA_UInt16 errno;
535#endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/
536
537    M4OSA_TRACE2_3("M4OSA_fileReadOpen_optim p = 0x%p fd = %s mode = %lu", pContext,
538                                                   pFileDescriptor, FileModeAccess);
539
540    /*      Check input parameters */
541    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pContext);
542    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pFileDescriptor);
543
544    *pContext = M4OSA_NULL;
545
546    /*      Allocate memory for the File reader context. */
547    apContext = (M4OSA_FileReader_Context_optim *)M4OSA_malloc(sizeof(M4OSA_FileReader_Context_optim),
548                                      M4OSA_FILE_READER, "M4OSA_FileReader_Context_optim");
549
550    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_ALLOC, apContext);
551
552    /* Set filesystem interface */
553#ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
554
555    /*Set the optimized functions, to be called by the user*/
556
557    apContext->FS = (M4OSA_FileReadPointer*) M4OSA_malloc(sizeof(M4OSA_FileReadPointer),
558                                       M4OSA_FILE_READER, "NXPSW_FileReaderOptim_init");
559    if (M4OSA_NULL==apContext->FS)
560    {
561        M4OSA_TRACE1_0("NXPSW_FileReaderOptim_init - ERROR : allocation failed");
562        return M4ERR_ALLOC;
563    }
564    apContext->FS->openRead  = M4OSA_fileReadOpen;
565    apContext->FS->readData  = M4OSA_fileReadData;
566    apContext->FS->seek      = M4OSA_fileReadSeek;
567    apContext->FS->closeRead = M4OSA_fileReadClose;
568    apContext->FS->setOption = M4OSA_fileReadSetOption;
569    apContext->FS->getOption = M4OSA_fileReadGetOption;
570   #else
571    apContext->FS = FS;
572#endif
573
574    /* Verify access mode */
575    if (   ((FileModeAccess & M4OSA_kFileAppend) != 0)
576        || ((FileModeAccess & M4OSA_kFileRead) == 0))
577    {
578        err = M4ERR_FILE_BAD_MODE_ACCESS;
579        goto cleanup;
580    }
581
582    /* Open file in read mode */
583    if((FileModeAccess & M4OSA_kFileCreate) != 0)
584    {
585        err = M4ERR_FILE_BAD_MODE_ACCESS;
586    }
587    else
588    {
589        if ((FileModeAccess & M4OSA_kFileRead))
590        {
591            /* File is opened in read only*/
592#ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
593            errno = apContext->FS->openRead(&aFileDesc, pFileDescriptor, FileModeAccess);
594
595            if ((aFileDesc == M4OSA_NULL)||(M4NO_ERROR != errno))
596            {
597                /* converts the error to PSW format*/
598                err = errno;
599                M4OSA_TRACE2_1("M4OSA_fileReadOpen_optim ERR1 = 0x%x", err);
600                apContext->IsOpened = M4OSA_FALSE;
601            }
602#else
603            aFileDesc = apContext->FS->pFctPtr_Open(pFileDescriptor, FileModeAccess, &errno);
604
605            if (aFileDesc == M4OSA_NULL)
606            {
607                /* converts the error to PSW format*/
608                err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno);
609                M4OSA_TRACE2_1("M4OSA_fileReadOpen_optim ERR1 = 0x%x", err);
610                apContext->IsOpened = M4OSA_FALSE;
611            }
612#endif
613
614            else
615            {
616                apContext->IsOpened = M4OSA_TRUE;
617            }
618        }
619        else
620        {
621            err = M4ERR_FILE_BAD_MODE_ACCESS;
622        }
623    }
624
625    if (M4NO_ERROR != err) goto cleanup;
626
627    /* Allocate buffers */
628    err = M4OSA_FileReader_BufferInit(apContext);
629    buffers_allocated = M4OSA_TRUE;
630
631    if (M4NO_ERROR != err) goto cleanup;
632
633    /* Initialize parameters */
634    apContext->fileSize = 0;
635    apContext->absolutePos = 0;
636    apContext->readFilePos = 0;
637
638    /* Retrieve the File Descriptor*/
639    apContext->aFileDesc = aFileDesc;
640
641    /* Retrieve the File mode Access */
642    apContext->FileAttribute.modeAccess = (M4OSA_FileModeAccess) FileModeAccess;
643
644    /*Retrieve the File reader context */
645    *pContext= (M4OSA_Context)apContext;
646
647    /* Compute file size */
648    err = M4OSA_FileReader_CalculateSize(apContext);
649
650    if (M4NO_ERROR != err) goto cleanup;
651
652    return M4NO_ERROR;
653
654cleanup:
655
656    /* free context */
657    if (M4OSA_NULL != apContext)
658    {
659        if(buffers_allocated == M4OSA_TRUE)
660        {
661            M4OSA_FileReader_BufferFree(apContext);
662        }
663
664        M4OSA_free((M4OSA_MemAddr32) apContext);
665        *pContext = M4OSA_NULL;
666    }
667
668    M4OSA_TRACE2_1 ("M4OSA_fileReadOpen_optim: returns error 0x%0x", err)
669    return err;
670}
671
672/**
673******************************************************************************
674* @brief       This method reads the 'size' bytes in the core file reader (selected by its 'context')
675*                      and writes the data to the 'data' pointer. If 'size' byte can not be read in the core file reader,
676*                      'size' parameter is updated to match the correct number of read bytes.
677* @param       pContext:       (IN) File reader context.
678* @param       pData : (OUT) Data pointer of the read data.
679* @param       pSize : (INOUT) Size of the data to read (in byte).
680* @return      M4NO_ERROR: there is no error
681* @return      M4ERR_PARAMETER pSize, fileDescriptor or pData is NULL
682* @return      M4ERR_ALLOC     there is no more memory available
683* @return      M4ERR_BAD_CONTEXT       provided context is not a valid one.
684******************************************************************************
685*/
686M4OSA_ERR M4OSA_fileReadData_optim(M4OSA_Context pContext,M4OSA_MemAddr8 pData,
687                                                            M4OSA_UInt32* pSize)
688{
689    M4OSA_FileReader_Context_optim* apContext =
690                                     (M4OSA_FileReader_Context_optim*) pContext;
691
692    M4OSA_ERR err;
693    M4OSA_FilePosition aSize;
694    M4OSA_FilePosition copiedSize;
695    M4OSA_Int8 selected_buffer, current_buffer;
696
697    M4OSA_TRACE3_3("M4OSA_fileReadData_optim p = 0x%p  d = 0x%p  s = %lu",
698                                                       pContext, pData, *pSize);
699
700    /* Check input parameters */
701    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext);
702    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pData);
703    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pSize);
704
705    if (apContext->IsOpened != M4OSA_TRUE)
706    {
707        return M4ERR_BAD_CONTEXT;
708    }
709
710    /* Prevent reading beyond EOF */
711    if((*pSize > 0) && (apContext->absolutePos >= apContext->fileSize))
712    {
713        copiedSize = 0;
714        err = M4WAR_NO_MORE_AU;
715        goto cleanup;
716    }
717
718    /* Check if data can be read from a buffer */
719    /* If not, fill one according to quantized positions */
720    copiedSize = 0;
721    err = M4NO_ERROR;
722
723    selected_buffer = M4OSA_FileReader_BufferMatch(apContext, apContext->absolutePos);
724
725    if(selected_buffer == M4OSA_READBUFFER_NONE)
726    {
727        selected_buffer = M4OSA_FileReader_BufferSelect(apContext, 0);
728        err = M4OSA_FileReader_BufferFill(apContext, selected_buffer,
729                                                        apContext->absolutePos);
730    }
731
732    if(err != M4NO_ERROR)
733    {
734        if(err == M4WAR_NO_DATA_YET)
735        {
736            if (*pSize <= (M4OSA_UInt32)apContext->buffer[selected_buffer].size)
737            {
738                err = M4NO_ERROR;
739            }
740            else
741            {
742                copiedSize = (M4OSA_UInt32)apContext->buffer[selected_buffer].size;
743                /*copy the content into pData*/
744                M4OSA_FileReader_BufferCopy(apContext, selected_buffer,
745                                     apContext->absolutePos, copiedSize, pData);
746                goto cleanup;
747            }
748        }
749        else
750        {
751            goto cleanup;
752        }
753    }
754
755    M4OSA_TRACE3_3("read  size = %lu  buffer = %d  pos = %ld", *pSize,
756                                       selected_buffer, apContext->absolutePos);
757
758    /* Copy buffer into pData */
759    while(((M4OSA_UInt32)copiedSize < *pSize) && (err == M4NO_ERROR))
760    {
761        aSize = M4OSA_FileReader_BufferCopy(apContext, selected_buffer,
762                                            apContext->absolutePos+copiedSize,
763                                            *pSize-copiedSize, pData+copiedSize);
764        copiedSize += aSize;
765
766        if(aSize == 0)
767        {
768            err = M4WAR_NO_DATA_YET;
769        }
770        else
771        {
772            if((M4OSA_UInt32)copiedSize < *pSize)
773            {
774                current_buffer = selected_buffer;
775                selected_buffer = M4OSA_FileReader_BufferMatch(apContext,
776                                             apContext->absolutePos+copiedSize);
777
778                if(selected_buffer == M4OSA_READBUFFER_NONE)
779                {
780                    selected_buffer = M4OSA_FileReader_BufferSelect(apContext,
781                                                                current_buffer);
782                    err = M4OSA_FileReader_BufferFill(apContext, selected_buffer,
783                                             apContext->absolutePos+copiedSize);
784
785                    if(err != M4NO_ERROR)
786                    {
787                        if(err == M4WAR_NO_DATA_YET)
788                        {
789                            /*If we got all the data that we wanted, we should return no error*/
790                            if ((*pSize-copiedSize) <= (M4OSA_UInt32)apContext->buffer[selected_buffer].size)
791                            {
792                                err = M4NO_ERROR;
793                            }
794                            /*If we did not get enough data, we will return NO_DATA_YET*/
795
796                            /*copy the data read*/
797                            aSize = M4OSA_FileReader_BufferCopy(apContext, selected_buffer,
798                                                               apContext->absolutePos+copiedSize,
799                                                               *pSize-copiedSize, pData+copiedSize);
800                            copiedSize += aSize;
801
802                            /*we reached end of file, so stop trying to read*/
803                            goto cleanup;
804                        }
805                        if (err == M4WAR_NO_MORE_AU)
806                        {
807                            err = M4WAR_NO_DATA_YET;
808
809                            /*copy the data read*/
810                            aSize = M4OSA_FileReader_BufferCopy(apContext, selected_buffer,
811                                                             apContext->absolutePos+copiedSize,
812                                                             *pSize-copiedSize, pData+copiedSize);
813                            copiedSize += aSize;
814
815                            /*we reached end of file, so stop trying to read*/
816                            goto cleanup;
817
818                        }
819                        else
820                        {
821                            goto cleanup;
822                        }
823                    }
824                }
825            }
826        }
827    }
828
829cleanup :
830
831    /* Update the new position of the pointer */
832    apContext->absolutePos = apContext->absolutePos + copiedSize;
833
834    if((err != M4NO_ERROR)&&(err!=M4WAR_NO_DATA_YET))
835    {
836        M4OSA_TRACE2_3("M4OSA_fileReadData_optim size = %ld  copied = %ld  err = 0x%x",
837                                                           *pSize, copiedSize, err);
838    }
839
840    /* Effective copied size must be returned */
841    *pSize = copiedSize;
842
843
844    /* Read is done */
845    return err;
846}
847
848/**
849******************************************************************************
850* @brief       This method seeks at the provided position in the core file reader (selected by its 'context').
851*              The position is related to the seekMode parameter it can be either :
852*              From the beginning (position MUST be positive) : end position = position
853*              From the end (position MUST be negative) : end position = file size + position
854*              From the current position (signed offset) : end position = current position + position.
855* @param       pContext:       (IN) File reader context.
856* @param       SeekMode :      (IN) Seek access mode.
857* @param       pPosition :     (IN) Position in the file.
858* @return      M4NO_ERROR: there is no error
859* @return      M4ERR_PARAMETER Seekmode or fileDescriptor is NULL
860* @return      M4ERR_ALLOC     there is no more memory available
861* @return      M4ERR_BAD_CONTEXT       provided context is not a valid one.
862* @return      M4ERR_FILE_INVALID_POSITION the position cannot be reached.
863******************************************************************************
864*/
865M4OSA_ERR M4OSA_fileReadSeek_optim( M4OSA_Context pContext, M4OSA_FileSeekAccessMode SeekMode,
866                                                              M4OSA_FilePosition* pPosition)
867{
868    M4OSA_FileReader_Context_optim* apContext = (M4OSA_FileReader_Context_optim*) pContext;
869    M4OSA_ERR err = M4NO_ERROR;
870    M4OSA_TRACE3_3("M4OSA_fileReadSeek_optim p = 0x%p mode = %d pos = %d", pContext,
871                                                             SeekMode, *pPosition);
872
873    /* Check input parameters */
874    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext);
875    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pPosition);
876    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, SeekMode);
877
878    if (apContext->IsOpened != M4OSA_TRUE)
879    {
880        return M4ERR_BAD_CONTEXT;       /*< The context can not be correct */
881    }
882
883    /* Go to the desired position */
884    switch(SeekMode)
885    {
886        case M4OSA_kFileSeekBeginning :
887            if(*pPosition < 0) {
888                return M4ERR_PARAMETER; /**< Bad SeekAcess mode */
889            }
890            apContext->absolutePos = *pPosition;
891            *pPosition = apContext->absolutePos;
892            break;
893
894        case M4OSA_kFileSeekEnd :
895            if(*pPosition > 0) {
896                return M4ERR_PARAMETER; /**< Bad SeekAcess mode */
897            }
898            apContext->absolutePos = apContext->fileSize + *pPosition;
899            *pPosition = apContext->absolutePos;
900            break;
901
902        case M4OSA_kFileSeekCurrent :
903            if(((apContext->absolutePos + *pPosition) > apContext->fileSize) ||
904                ((apContext->absolutePos + *pPosition) < 0)){
905                return M4ERR_PARAMETER; /**< Bad SeekAcess mode */
906            }
907            apContext->absolutePos = apContext->absolutePos + *pPosition;
908            *pPosition = apContext->absolutePos;
909            break;
910
911        default :
912            err = M4ERR_PARAMETER; /**< Bad SeekAcess mode */
913            break;
914    }
915
916    /* Return without error */
917    return err;
918}
919
920/**
921******************************************************************************
922* @brief       This method asks the core file reader to close the file
923*              (associated to the context) and also frees the context.
924* @param       pContext:       (IN) File reader context.
925* @return      M4NO_ERROR: there is no error
926* @return      M4ERR_BAD_CONTEXT       provided context is not a valid one.
927******************************************************************************
928*/
929M4OSA_ERR M4OSA_fileReadClose_optim(M4OSA_Context pContext)
930{
931    M4OSA_FileReader_Context_optim* apContext = (M4OSA_FileReader_Context_optim*) pContext;
932
933    M4OSA_ERR err = M4NO_ERROR;
934#ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
935    M4OSA_ERR errno = M4NO_ERROR;
936#else
937    M4OSA_UInt16 errno;
938#endif
939
940    M4OSA_TRACE2_1("M4OSA_fileReadClose_optim p = 0x%p", pContext );
941
942    /* Check input parameters */
943    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext);
944
945    if (apContext->IsOpened != M4OSA_TRUE)
946    {
947        return M4ERR_BAD_CONTEXT;       /**< The context can not be correct */
948    }
949
950    /* buffer */
951    M4OSA_FileReader_BufferFree(apContext);
952
953    /* Close the file */
954#ifdef M4OSA_READER_OPTIM_USE_OSAL_IF
955    errno = apContext->FS->closeRead(apContext->aFileDesc);
956
957    if (M4NO_ERROR != errno)
958    {
959        /* converts the error to PSW format*/
960        err = errno;
961        M4OSA_TRACE2_1("M4OSA_fileReadClose_optim ERR1 = 0x%x", err);
962    }
963#else
964    aRet_Val = apContext->FS->pFctPtr_Close(apContext->aFileDesc, &errno);
965
966    if (aRet_Val != 0)
967    {
968        /* converts the error to PSW format*/
969        err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno);
970        M4OSA_TRACE2_1("M4OSA_fileReadClose_optim ERR1 = 0x%x", err);
971    }
972#endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/
973
974    apContext->IsOpened = M4OSA_FALSE;
975
976    //>>>> GLM20090212 : set the low level function statically
977    if (apContext->FS != M4OSA_NULL)
978    {
979        M4OSA_free((M4OSA_MemAddr32) apContext->FS);
980    }
981    //<<<< GLM20090212 : set the low level function statically
982
983    /* Free the context */
984    M4OSA_free((M4OSA_MemAddr32)apContext);
985
986    /* Return without error */
987    return err;
988}
989
990/**
991******************************************************************************
992* @brief       This is a dummy function required to maintain function pointer
993*              structure.
994* @note        This is a dummy function required to maintain function pointer
995*              structure.
996* @param       pContext:       (IN) Execution context.
997* @param       OptionId :      (IN) Id of the option to set.
998* @param       OptionValue :   (IN) Value of the option.
999* @return      M4NO_ERROR: there is no error
1000******************************************************************************
1001*/
1002M4OSA_ERR M4OSA_fileReadSetOption_optim(M4OSA_Context pContext,
1003                                        M4OSA_FileReadOptionID OptionID,
1004                                        M4OSA_DataOption OptionValue)
1005{
1006    M4OSA_ERR err = M4NO_ERROR;
1007    return err;
1008}
1009
1010/**
1011******************************************************************************
1012* @brief       This method asks the core file reader to return the value associated
1013*              with the optionID.The caller is responsible for allocating/de-allocating
1014*              the memory of the value field.
1015* @note        The options handled by the component depend on the implementation
1016*                                                               of the component.
1017* @param       pContext:       (IN) Execution context.
1018* @param       OptionId :      (IN) Id of the option to set.
1019* @param       pOptionValue :  (OUT) Value of the option.
1020* @return      M4NO_ERROR: there is no error
1021* @return      M4ERR_BAD_CONTEXT       pContext is NULL
1022* @return      M4ERR_BAD_OPTION_ID the option id is not valid.
1023* @return      M4ERR_NOT_IMPLEMENTED The option is not implemented yet.
1024******************************************************************************
1025*/
1026M4OSA_ERR M4OSA_fileReadGetOption_optim(M4OSA_Context pContext,
1027                                        M4OSA_FileReadOptionID OptionID,
1028                                        M4OSA_DataOption* pOptionValue)
1029{
1030    M4OSA_FileReader_Context_optim* apContext = (M4OSA_FileReader_Context_optim*) pContext;
1031    M4OSA_ERR err = M4NO_ERROR;
1032
1033    /*  Check input parameters */
1034    M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext);
1035
1036    if (apContext->IsOpened != M4OSA_TRUE)
1037    {
1038        return M4ERR_BAD_CONTEXT;       /**< The context can not be correct */
1039    }
1040
1041    /* Get the desired option if it is avalaible */
1042    switch(OptionID)
1043    {
1044        /* Get File Size */
1045        case M4OSA_kFileReadGetFileSize:/**< Get size of the file, limited to 32 bit size */
1046
1047            (*(M4OSA_UInt32 *)pOptionValue) = apContext->fileSize;
1048            break;
1049
1050        /* Check End of file Occurs */
1051        case M4OSA_kFileReadIsEOF :     /**< See if we are at the end of the file */
1052
1053            (*(M4OSA_Bool *)pOptionValue) = (apContext->absolutePos >= apContext->fileSize) ? M4OSA_TRUE : M4OSA_FALSE;
1054            break;
1055
1056        /* Get File Position */
1057        case M4OSA_kFileReadGetFilePosition :   /**< Get file position */
1058
1059            *(M4OSA_FilePosition *)pOptionValue = apContext->absolutePos;
1060            break;
1061
1062        /* Get Attribute */
1063        case M4OSA_kFileReadGetFileAttribute :  /**< Get the file attribute = access mode */
1064
1065            (*(M4OSA_FileAttribute *)pOptionValue).modeAccess = apContext->FileAttribute.modeAccess;
1066            break;
1067
1068        default:
1069            /**< Bad option ID */
1070            err = M4ERR_BAD_OPTION_ID;
1071            break;
1072    }
1073
1074    /*Return without error */
1075    return err;
1076}
1077