/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** ****************************************************************************** * @file M4OSA_FileReader_optim.c * @brief * @note This file implements functions to manipulate filesystem access ****************************************************************************** */ /** Addition of Trace ID **/ #include "M4OSA_CoreID.h" #include "M4OSA_Error.h" #ifdef M4TRACE_ID #undef M4TRACE_ID #endif #define M4TRACE_ID M4OSA_FILE_READER #include "M4OSA_FileCommon.h" #include "M4OSA_FileReader.h" #include "M4OSA_FileWriter.h" #include "M4OSA_Memory.h" #include "M4OSA_Debug.h" #include "LVOSA_FileReader_optim.h" #define M4OSA_READER_OPTIM_USE_OSAL_IF #ifndef M4OSA_READER_OPTIM_USE_OSAL_IF #include "M4OSA_FileAccess.h" #endif #define M4ERR_CHECK_NULL_RETURN_VALUE(retval, pointer) if ((pointer) == M4OSA_NULL) return (retval); /** ****************************************************************************** * File reader cache buffers parameters (size, number of buffers, etc) ****************************************************************************** */ #define M4OSA_READBUFFER_SIZE 1024*16 #define M4OSA_READBUFFER_NB 2 #define M4OSA_READBUFFER_NONE -1 #define M4OSA_EOF -1 #define MAX_FILLS_SINCE_LAST_ACCESS M4OSA_READBUFFER_NB*2 /** ****************************************************************************** * structure M4OSA_FileReader_Buffer * @brief This structure defines the File reader Buffers context (private) ****************************************************************************** */ typedef struct { M4OSA_MemAddr8 data; /**< buffer data */ M4OSA_FilePosition size; /**< size of the buffer */ M4OSA_FilePosition filepos; /**< position in the file where the buffer starts */ M4OSA_FilePosition remain; /**< data amount not already copied from buffer */ M4OSA_UInt32 nbFillSinceLastAcess; /**< To know since how many time we didn't use this buffer */ } M4OSA_FileReader_Buffer_optim; /** ****************************************************************************** * structure M4OSA_FileReader_Context * @brief This structure defines the File reader context (private) * @note This structure is used for all File Reader calls to store the context ****************************************************************************** */ typedef struct { M4OSA_Bool IsOpened; /**< Micro state machine */ M4OSA_FileAttribute FileAttribute; /**< Opening mode */ M4OSA_FilePosition readFilePos; /**< Effective position of the GFL read pointer */ M4OSA_FilePosition absolutePos; /**< Virtual position for next reading */ M4OSA_FilePosition fileSize; /**< Size of the file */ M4OSA_FileReader_Buffer_optim buffer[M4OSA_READBUFFER_NB]; /**< Read buffers */ M4OSA_Void* aFileDesc; /**< File descriptor */ #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF M4OSA_FileReadPointer* FS; /**< Filesystem interface */ #else M4OSA_FileSystem_FctPtr *FS; /**< Filesystem interface */ #endif } M4OSA_FileReader_Context_optim; /* __________________________________________________________ */ /*| |*/ /*| Global function for handling low level read access |*/ /*|__________________________________________________________|*/ static M4OSA_FileReadPointer* gv_NXPSW_READOPT_lowLevelFunctions; M4OSA_ERR NXPSW_FileReaderOptim_init(M4OSA_Void *lowLevel_functionPointers, M4OSA_Void *optimized_functionPointers) { M4OSA_FileReadPointer* lowLevel_fp = (M4OSA_FileReadPointer*) lowLevel_functionPointers; M4OSA_FileReadPointer* optimized_fp = (M4OSA_FileReadPointer*) optimized_functionPointers; //Set the optimized functions, to be called by the user optimized_fp->openRead = M4OSA_fileReadOpen_optim; optimized_fp->readData = M4OSA_fileReadData_optim; optimized_fp->seek = M4OSA_fileReadSeek_optim; optimized_fp->closeRead = M4OSA_fileReadClose_optim; optimized_fp->setOption = M4OSA_fileReadSetOption_optim; optimized_fp->getOption = M4OSA_fileReadGetOption_optim; return M4NO_ERROR; } M4OSA_ERR NXPSW_FileReaderOptim_cleanUp() { gv_NXPSW_READOPT_lowLevelFunctions = M4OSA_NULL; return M4NO_ERROR; } M4OSA_ERR NXPSW_FileReaderOptim_getLowLevelFunctions(M4OSA_Void **FS) { M4OSA_FileReadPointer** pFunctionsPointer = (M4OSA_FileReadPointer**) FS; *pFunctionsPointer = gv_NXPSW_READOPT_lowLevelFunctions; return M4NO_ERROR; } /* __________________________________________________________ */ /*| |*/ /*| Buffer handling functions for Read access |*/ /*|__________________________________________________________|*/ /**************************************************************/ M4OSA_ERR M4OSA_FileReader_BufferInit(M4OSA_FileReader_Context_optim* apContext) /**************************************************************/ { M4OSA_UInt8 i; for(i=0; i<M4OSA_READBUFFER_NB; i++) { apContext->buffer[i].data = M4OSA_NULL; apContext->buffer[i].size = 0; apContext->buffer[i].filepos = 0; apContext->buffer[i].remain = 0; } for(i=0; i<M4OSA_READBUFFER_NB; i++) { apContext->buffer[i].data = (M4OSA_MemAddr8) M4OSA_32bitAlignedMalloc(M4OSA_READBUFFER_SIZE, M4OSA_FILE_READER, (M4OSA_Char *)"M4OSA_FileReader_BufferInit"); M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_ALLOC, apContext->buffer[i].data); } return M4NO_ERROR; } /**************************************************************/ M4OSA_Void M4OSA_FileReader_BufferFree(M4OSA_FileReader_Context_optim* apContext) /**************************************************************/ { M4OSA_Int8 i; for(i=0; i<M4OSA_READBUFFER_NB; i++) if(apContext->buffer[i].data != M4OSA_NULL) free(apContext->buffer[i].data); } /**************************************************************/ M4OSA_FilePosition M4OSA_FileReader_BufferCopy(M4OSA_FileReader_Context_optim* apContext, M4OSA_Int8 i, M4OSA_FilePosition pos, M4OSA_FilePosition size, M4OSA_MemAddr8 pData) /**************************************************************/ { M4OSA_FilePosition copysize; M4OSA_FilePosition offset; if(apContext->buffer[i].size == M4OSA_EOF) return M4OSA_EOF; if( (pos < apContext->buffer[i].filepos) || (pos > (apContext->buffer[i].filepos + apContext->buffer[i].size - 1)) ) { return 0; /* nothing copied */ } offset = pos - apContext->buffer[i].filepos; copysize = apContext->buffer[i].size - offset; copysize = (size < copysize) ? size : copysize; memcpy((void *)pData, (void *)(apContext->buffer[i].data + offset), copysize); apContext->buffer[i].remain -= copysize; apContext->buffer[i].nbFillSinceLastAcess = 0; return copysize; } /**************************************************************/ M4OSA_ERR M4OSA_FileReader_BufferFill(M4OSA_FileReader_Context_optim* apContext, M4OSA_Int8 i, M4OSA_FilePosition pos) /**************************************************************/ { M4OSA_FilePosition gridPos; M4OSA_FilePosition tempPos; M4OSA_UInt32 bufferSize; M4OSA_FilePosition diff; M4OSA_FilePosition size; M4OSA_ERR err = M4NO_ERROR; #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF M4OSA_ERR errno = M4NO_ERROR; M4OSA_UInt32 fileReadSize = 0; M4OSA_FilePosition fileSeekPosition = 0; #else M4OSA_Int32 ret_val; M4OSA_UInt16 errno; #endif M4OSA_TRACE3_4("BufferFill i = %d pos = %ld read = %ld old = %ld", i, pos, apContext->readFilePos, apContext->buffer[i].filepos); /* Avoid cycling statement because of EOF */ if(pos >= apContext->fileSize) return M4WAR_NO_MORE_AU; /* Relocate to absolute postion if necessary */ bufferSize = M4OSA_READBUFFER_SIZE; tempPos = (M4OSA_FilePosition) (pos / bufferSize); gridPos = tempPos * M4OSA_READBUFFER_SIZE; diff = gridPos - apContext->readFilePos; if(diff != 0) { #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF fileSeekPosition = diff; errno = apContext->FS->seek(apContext->aFileDesc, M4OSA_kFileSeekCurrent, &fileSeekPosition); apContext->readFilePos = gridPos; if(M4NO_ERROR != errno) { err = errno; M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR1 = 0x%x", err); return err; } #else ret_val = apContext->FS->pFctPtr_Seek(apContext->aFileDesc, diff, M4OSA_kFileSeekCurrent, &errno); apContext->readFilePos = gridPos; if(ret_val != 0) { err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno); M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR1 = 0x%x", err); return err; } #endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/ } apContext->buffer[i].filepos = apContext->readFilePos; /* Read Data */ #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF fileReadSize = M4OSA_READBUFFER_SIZE; errno = apContext->FS->readData(apContext->aFileDesc, (M4OSA_MemAddr8)apContext->buffer[i].data, &fileReadSize); size = (M4OSA_FilePosition)fileReadSize; if ((M4NO_ERROR != errno)&&(M4WAR_NO_DATA_YET != errno)) { apContext->buffer[i].size = M4OSA_EOF; apContext->buffer[i].remain = 0; err = errno; M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR2 = 0x%x", err); return err; } #else size = apContext->FS->pFctPtr_Read(apContext->aFileDesc, (M4OSA_UInt8 *)apContext->buffer[i].data, M4OSA_READBUFFER_SIZE, &errno); if(size == -1) { apContext->buffer[i].size = M4OSA_EOF; apContext->buffer[i].remain = 0; err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno); M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR2 = 0x%x", err); return err; } #endif apContext->buffer[i].size = size; apContext->buffer[i].remain = size; apContext->buffer[i].nbFillSinceLastAcess = 0; /* Retrieve current position */ #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF errno = apContext->FS->getOption(apContext->aFileDesc, M4OSA_kFileReadGetFilePosition, (M4OSA_DataOption*) &apContext->readFilePos); if (M4NO_ERROR != errno) { err = errno; M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR3 = 0x%x", err); } else if( (apContext->buffer[i].size >= 0) && (apContext->buffer[i].size < M4OSA_READBUFFER_SIZE) ) { err = M4WAR_NO_DATA_YET; M4OSA_TRACE2_0("M4OSA_FileReader_BufferFill returns NO DATA YET"); return err; } #else apContext->readFilePos = apContext->FS->pFctPtr_Tell(apContext->aFileDesc, &errno); if( (apContext->buffer[i].size >= 0) && (apContext->buffer[i].size < M4OSA_READBUFFER_SIZE) ) { err = M4WAR_NO_DATA_YET; M4OSA_TRACE1_1("M4OSA_FileReader_BufferFill ERR3 = 0x%x", err); return err; } #endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/ /* Return without error */ return M4NO_ERROR; } /**************************************************************/ M4OSA_Int8 M4OSA_FileReader_BufferMatch(M4OSA_FileReader_Context_optim* apContext, M4OSA_FilePosition pos) /**************************************************************/ { M4OSA_Int8 i; /* Select the buffer which matches with given pos */ for(i=0; i<M4OSA_READBUFFER_NB; i++) { if( (pos >= apContext->buffer[i].filepos) && (pos < (apContext->buffer[i].filepos + apContext->buffer[i].size)) ) { return i; } } return M4OSA_READBUFFER_NONE; } /**************************************************************/ M4OSA_Int8 M4OSA_FileReader_BufferSelect(M4OSA_FileReader_Context_optim* apContext, M4OSA_Int8 current_i) /**************************************************************/ { M4OSA_Int8 i,j; M4OSA_FilePosition min_amount,max_amount; M4OSA_Int8 min_i,max_count; /* update nbFillSinceLastAcess field */ for(i=0; i<M4OSA_READBUFFER_NB; i++) { apContext->buffer[i].nbFillSinceLastAcess ++; } /* Plan A : Scan for empty buffer */ for(i=0; i<M4OSA_READBUFFER_NB; i++) { if(apContext->buffer[i].remain == 0) { return i; } } max_count = M4OSA_READBUFFER_NB; max_amount = MAX_FILLS_SINCE_LAST_ACCESS; /* Plan B : Scan for dead buffer */ for(i=0; i<M4OSA_READBUFFER_NB; i++) { if(apContext->buffer[i].nbFillSinceLastAcess >= (M4OSA_UInt32) max_amount) { max_amount = apContext->buffer[i].nbFillSinceLastAcess; max_count = i; } } if(max_count<M4OSA_READBUFFER_NB) { M4OSA_TRACE2_2("DEAD BUFFER: %d, %d",max_count,apContext->buffer[max_count].nbFillSinceLastAcess); return max_count; } min_i = current_i; min_amount = M4OSA_READBUFFER_SIZE; /* Select the buffer which is the most "empty" */ for(i=0; i<M4OSA_READBUFFER_NB; i++) { j = (i+current_i)%M4OSA_READBUFFER_NB; if(apContext->buffer[j].remain < min_amount) { min_amount = apContext->buffer[j].remain; min_i = j; } } return min_i; } /**************************************************************/ M4OSA_ERR M4OSA_FileReader_CalculateSize(M4OSA_FileReader_Context_optim* apContext) /**************************************************************/ { M4OSA_ERR err = M4NO_ERROR; #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF M4OSA_ERR errno = M4NO_ERROR; #else M4OSA_Int32 ret_val; M4OSA_UInt16 errno; #endif /* go to the end of file*/ #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF errno = apContext->FS->getOption(apContext->aFileDesc, M4OSA_kFileReadGetFileSize, (M4OSA_DataOption*) &apContext->fileSize); if (M4NO_ERROR != errno) { err = errno; M4OSA_TRACE1_1("M4OSA_FileReader_CalculateSize ERR = 0x%x", err); } #else ret_val = apContext->FS->pFctPtr_Seek(apContext->aFileDesc, 0, M4OSA_kFileSeekEnd, &errno); if (ret_val != 0) { apContext->readFilePos = M4OSA_EOF; err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno); M4OSA_TRACE1_1("M4OSA_FileReader_CalculateSize ERR = 0x%x", err); } else { /* Retrieve size of the file */ apContext->fileSize = apContext->FS->pFctPtr_Tell(apContext->aFileDesc, &errno); apContext->readFilePos = apContext->fileSize; } #endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/ return err; } /* __________________________________________________________ */ /*| |*/ /*| OSAL filesystem API |*/ /*|__________________________________________________________|*/ /** ****************************************************************************** * @brief This method opens the provided fileDescriptor and returns its context. * @param pContext: (OUT) File reader context. * @param pFileDescriptor : (IN) File Descriptor of the input file. * @param FileModeAccess : (IN) File mode access. * @return M4NO_ERROR: there is no error * @return M4ERR_PARAMETER pContext or fileDescriptor is NULL * @return M4ERR_ALLOC there is no more memory available * @return M4ERR_FILE_BAD_MODE_ACCESS the file mode access is not correct (it must be either isTextMode or read) * @return M4ERR_FILE_NOT_FOUND The file can not be opened. ****************************************************************************** */ #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF M4OSA_ERR M4OSA_fileReadOpen_optim(M4OSA_Context* pContext, M4OSA_Void* pFileDescriptor, M4OSA_UInt32 FileModeAccess) #else M4OSA_ERR M4OSA_fileReadOpen_optim(M4OSA_Context* pContext, M4OSA_Void* pFileDescriptor, M4OSA_UInt32 FileModeAccess, M4OSA_FileSystem_FctPtr *FS) #endif { M4OSA_FileReader_Context_optim* apContext = M4OSA_NULL; M4OSA_ERR err = M4NO_ERROR; M4OSA_Void* aFileDesc = M4OSA_NULL; M4OSA_Bool buffers_allocated = M4OSA_FALSE; #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF M4OSA_ERR errno = M4NO_ERROR; #else M4OSA_UInt16 errno; #endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/ M4OSA_TRACE2_3("M4OSA_fileReadOpen_optim p = 0x%p fd = %s mode = %lu", pContext, pFileDescriptor, FileModeAccess); /* Check input parameters */ M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pContext); M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pFileDescriptor); *pContext = M4OSA_NULL; /* Allocate memory for the File reader context. */ apContext = (M4OSA_FileReader_Context_optim *)M4OSA_32bitAlignedMalloc(sizeof(M4OSA_FileReader_Context_optim), M4OSA_FILE_READER, (M4OSA_Char *)"M4OSA_FileReader_Context_optim"); M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_ALLOC, apContext); /* Set filesystem interface */ #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF /*Set the optimized functions, to be called by the user*/ apContext->FS = (M4OSA_FileReadPointer*) M4OSA_32bitAlignedMalloc(sizeof(M4OSA_FileReadPointer), M4OSA_FILE_READER, (M4OSA_Char *)"M4OSA_FileReaderOptim_init"); if (M4OSA_NULL==apContext->FS) { M4OSA_TRACE1_0("M4OSA_FileReaderOptim_init - ERROR : allocation failed"); return M4ERR_ALLOC; } apContext->FS->openRead = M4OSA_fileReadOpen; apContext->FS->readData = M4OSA_fileReadData; apContext->FS->seek = M4OSA_fileReadSeek; apContext->FS->closeRead = M4OSA_fileReadClose; apContext->FS->setOption = M4OSA_fileReadSetOption; apContext->FS->getOption = M4OSA_fileReadGetOption; #else apContext->FS = FS; #endif /* Verify access mode */ if ( ((FileModeAccess & M4OSA_kFileAppend) != 0) || ((FileModeAccess & M4OSA_kFileRead) == 0)) { err = M4ERR_FILE_BAD_MODE_ACCESS; goto cleanup; } /* Open file in read mode */ if((FileModeAccess & M4OSA_kFileCreate) != 0) { err = M4ERR_FILE_BAD_MODE_ACCESS; } else { if ((FileModeAccess & M4OSA_kFileRead)) { /* File is opened in read only*/ #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF errno = apContext->FS->openRead(&aFileDesc, pFileDescriptor, FileModeAccess); if ((aFileDesc == M4OSA_NULL)||(M4NO_ERROR != errno)) { /* converts the error to PSW format*/ err = errno; M4OSA_TRACE2_1("M4OSA_fileReadOpen_optim ERR1 = 0x%x", err); apContext->IsOpened = M4OSA_FALSE; } #else aFileDesc = apContext->FS->pFctPtr_Open(pFileDescriptor, FileModeAccess, &errno); if (aFileDesc == M4OSA_NULL) { /* converts the error to PSW format*/ err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno); M4OSA_TRACE2_1("M4OSA_fileReadOpen_optim ERR1 = 0x%x", err); apContext->IsOpened = M4OSA_FALSE; } #endif else { apContext->IsOpened = M4OSA_TRUE; } } else { err = M4ERR_FILE_BAD_MODE_ACCESS; } } if (M4NO_ERROR != err) goto cleanup; /* Allocate buffers */ err = M4OSA_FileReader_BufferInit(apContext); buffers_allocated = M4OSA_TRUE; if (M4NO_ERROR != err) goto cleanup; /* Initialize parameters */ apContext->fileSize = 0; apContext->absolutePos = 0; apContext->readFilePos = 0; /* Retrieve the File Descriptor*/ apContext->aFileDesc = aFileDesc; /* Retrieve the File mode Access */ apContext->FileAttribute.modeAccess = (M4OSA_FileModeAccess) FileModeAccess; /*Retrieve the File reader context */ *pContext= (M4OSA_Context)apContext; /* Compute file size */ err = M4OSA_FileReader_CalculateSize(apContext); if (M4NO_ERROR != err) goto cleanup; return M4NO_ERROR; cleanup: /* free context */ if (M4OSA_NULL != apContext) { if(buffers_allocated == M4OSA_TRUE) { M4OSA_FileReader_BufferFree(apContext); } free( apContext); *pContext = M4OSA_NULL; } M4OSA_TRACE2_1 ("M4OSA_fileReadOpen_optim: returns error 0x%0x", err) return err; } /** ****************************************************************************** * @brief This method reads the 'size' bytes in the core file reader (selected by its 'context') * and writes the data to the 'data' pointer. If 'size' byte can not be read in the core file reader, * 'size' parameter is updated to match the correct number of read bytes. * @param pContext: (IN) File reader context. * @param pData : (OUT) Data pointer of the read data. * @param pSize : (INOUT) Size of the data to read (in byte). * @return M4NO_ERROR: there is no error * @return M4ERR_PARAMETER pSize, fileDescriptor or pData is NULL * @return M4ERR_ALLOC there is no more memory available * @return M4ERR_BAD_CONTEXT provided context is not a valid one. ****************************************************************************** */ M4OSA_ERR M4OSA_fileReadData_optim(M4OSA_Context pContext,M4OSA_MemAddr8 pData, M4OSA_UInt32* pSize) { M4OSA_FileReader_Context_optim* apContext = (M4OSA_FileReader_Context_optim*) pContext; M4OSA_ERR err; M4OSA_FilePosition aSize; M4OSA_FilePosition copiedSize; M4OSA_Int8 selected_buffer, current_buffer; M4OSA_TRACE3_3("M4OSA_fileReadData_optim p = 0x%p d = 0x%p s = %lu", pContext, pData, *pSize); /* Check input parameters */ M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext); M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pData); M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pSize); if (apContext->IsOpened != M4OSA_TRUE) { return M4ERR_BAD_CONTEXT; } /* Prevent reading beyond EOF */ if((*pSize > 0) && (apContext->absolutePos >= apContext->fileSize)) { copiedSize = 0; err = M4WAR_NO_MORE_AU; goto cleanup; } /* Check if data can be read from a buffer */ /* If not, fill one according to quantized positions */ copiedSize = 0; err = M4NO_ERROR; selected_buffer = M4OSA_FileReader_BufferMatch(apContext, apContext->absolutePos); if(selected_buffer == M4OSA_READBUFFER_NONE) { selected_buffer = M4OSA_FileReader_BufferSelect(apContext, 0); err = M4OSA_FileReader_BufferFill(apContext, selected_buffer, apContext->absolutePos); } if(err != M4NO_ERROR) { if(err == M4WAR_NO_DATA_YET) { if (*pSize <= (M4OSA_UInt32)apContext->buffer[selected_buffer].size) { err = M4NO_ERROR; } else { copiedSize = (M4OSA_UInt32)apContext->buffer[selected_buffer].size; /*copy the content into pData*/ M4OSA_FileReader_BufferCopy(apContext, selected_buffer, apContext->absolutePos, copiedSize, pData); goto cleanup; } } else { goto cleanup; } } M4OSA_TRACE3_3("read size = %lu buffer = %d pos = %ld", *pSize, selected_buffer, apContext->absolutePos); /* Copy buffer into pData */ while(((M4OSA_UInt32)copiedSize < *pSize) && (err == M4NO_ERROR)) { aSize = M4OSA_FileReader_BufferCopy(apContext, selected_buffer, apContext->absolutePos+copiedSize, *pSize-copiedSize, pData+copiedSize); copiedSize += aSize; if(aSize == 0) { err = M4WAR_NO_DATA_YET; } else { if((M4OSA_UInt32)copiedSize < *pSize) { current_buffer = selected_buffer; selected_buffer = M4OSA_FileReader_BufferMatch(apContext, apContext->absolutePos+copiedSize); if(selected_buffer == M4OSA_READBUFFER_NONE) { selected_buffer = M4OSA_FileReader_BufferSelect(apContext, current_buffer); err = M4OSA_FileReader_BufferFill(apContext, selected_buffer, apContext->absolutePos+copiedSize); if(err != M4NO_ERROR) { if(err == M4WAR_NO_DATA_YET) { /*If we got all the data that we wanted, we should return no error*/ if ((*pSize-copiedSize) <= (M4OSA_UInt32)apContext->buffer[selected_buffer].size) { err = M4NO_ERROR; } /*If we did not get enough data, we will return NO_DATA_YET*/ /*copy the data read*/ aSize = M4OSA_FileReader_BufferCopy(apContext, selected_buffer, apContext->absolutePos+copiedSize, *pSize-copiedSize, pData+copiedSize); copiedSize += aSize; /*we reached end of file, so stop trying to read*/ goto cleanup; } if (err == M4WAR_NO_MORE_AU) { err = M4WAR_NO_DATA_YET; /*copy the data read*/ aSize = M4OSA_FileReader_BufferCopy(apContext, selected_buffer, apContext->absolutePos+copiedSize, *pSize-copiedSize, pData+copiedSize); copiedSize += aSize; /*we reached end of file, so stop trying to read*/ goto cleanup; } else { goto cleanup; } } } } } } cleanup : /* Update the new position of the pointer */ apContext->absolutePos = apContext->absolutePos + copiedSize; if((err != M4NO_ERROR)&&(err!=M4WAR_NO_DATA_YET)) { M4OSA_TRACE2_3("M4OSA_fileReadData_optim size = %ld copied = %ld err = 0x%x", *pSize, copiedSize, err); } /* Effective copied size must be returned */ *pSize = copiedSize; /* Read is done */ return err; } /** ****************************************************************************** * @brief This method seeks at the provided position in the core file reader (selected by its 'context'). * The position is related to the seekMode parameter it can be either : * From the beginning (position MUST be positive) : end position = position * From the end (position MUST be negative) : end position = file size + position * From the current position (signed offset) : end position = current position + position. * @param pContext: (IN) File reader context. * @param SeekMode : (IN) Seek access mode. * @param pPosition : (IN) Position in the file. * @return M4NO_ERROR: there is no error * @return M4ERR_PARAMETER Seekmode or fileDescriptor is NULL * @return M4ERR_ALLOC there is no more memory available * @return M4ERR_BAD_CONTEXT provided context is not a valid one. * @return M4ERR_FILE_INVALID_POSITION the position cannot be reached. ****************************************************************************** */ M4OSA_ERR M4OSA_fileReadSeek_optim( M4OSA_Context pContext, M4OSA_FileSeekAccessMode SeekMode, M4OSA_FilePosition* pPosition) { M4OSA_FileReader_Context_optim* apContext = (M4OSA_FileReader_Context_optim*) pContext; M4OSA_ERR err = M4NO_ERROR; M4OSA_TRACE3_3("M4OSA_fileReadSeek_optim p = 0x%p mode = %d pos = %d", pContext, SeekMode, *pPosition); /* Check input parameters */ M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext); M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pPosition); M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, SeekMode); if (apContext->IsOpened != M4OSA_TRUE) { return M4ERR_BAD_CONTEXT; /*< The context can not be correct */ } /* Go to the desired position */ switch(SeekMode) { case M4OSA_kFileSeekBeginning : if(*pPosition < 0) { return M4ERR_PARAMETER; /**< Bad SeekAcess mode */ } apContext->absolutePos = *pPosition; *pPosition = apContext->absolutePos; break; case M4OSA_kFileSeekEnd : if(*pPosition > 0) { return M4ERR_PARAMETER; /**< Bad SeekAcess mode */ } apContext->absolutePos = apContext->fileSize + *pPosition; *pPosition = apContext->absolutePos; break; case M4OSA_kFileSeekCurrent : if(((apContext->absolutePos + *pPosition) > apContext->fileSize) || ((apContext->absolutePos + *pPosition) < 0)){ return M4ERR_PARAMETER; /**< Bad SeekAcess mode */ } apContext->absolutePos = apContext->absolutePos + *pPosition; *pPosition = apContext->absolutePos; break; default : err = M4ERR_PARAMETER; /**< Bad SeekAcess mode */ break; } /* Return without error */ return err; } /** ****************************************************************************** * @brief This method asks the core file reader to close the file * (associated to the context) and also frees the context. * @param pContext: (IN) File reader context. * @return M4NO_ERROR: there is no error * @return M4ERR_BAD_CONTEXT provided context is not a valid one. ****************************************************************************** */ M4OSA_ERR M4OSA_fileReadClose_optim(M4OSA_Context pContext) { M4OSA_FileReader_Context_optim* apContext = (M4OSA_FileReader_Context_optim*) pContext; M4OSA_ERR err = M4NO_ERROR; #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF M4OSA_ERR errno = M4NO_ERROR; #else M4OSA_UInt16 errno; #endif M4OSA_TRACE2_1("M4OSA_fileReadClose_optim p = 0x%p", pContext ); /* Check input parameters */ M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext); if (apContext->IsOpened != M4OSA_TRUE) { return M4ERR_BAD_CONTEXT; /**< The context can not be correct */ } /* buffer */ M4OSA_FileReader_BufferFree(apContext); /* Close the file */ #ifdef M4OSA_READER_OPTIM_USE_OSAL_IF errno = apContext->FS->closeRead(apContext->aFileDesc); if (M4NO_ERROR != errno) { /* converts the error to PSW format*/ err = errno; M4OSA_TRACE2_1("M4OSA_fileReadClose_optim ERR1 = 0x%x", err); } #else aRet_Val = apContext->FS->pFctPtr_Close(apContext->aFileDesc, &errno); if (aRet_Val != 0) { /* converts the error to PSW format*/ err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errno); M4OSA_TRACE2_1("M4OSA_fileReadClose_optim ERR1 = 0x%x", err); } #endif /*M4OSA_READER_OPTIM_USE_OSAL_IF*/ apContext->IsOpened = M4OSA_FALSE; //>>>> GLM20090212 : set the low level function statically if (apContext->FS != M4OSA_NULL) { free( apContext->FS); } //<<<< GLM20090212 : set the low level function statically /* Free the context */ free(apContext); /* Return without error */ return err; } /** ****************************************************************************** * @brief This is a dummy function required to maintain function pointer * structure. * @note This is a dummy function required to maintain function pointer * structure. * @param pContext: (IN) Execution context. * @param OptionId : (IN) Id of the option to set. * @param OptionValue : (IN) Value of the option. * @return M4NO_ERROR: there is no error ****************************************************************************** */ M4OSA_ERR M4OSA_fileReadSetOption_optim(M4OSA_Context pContext, M4OSA_FileReadOptionID OptionID, M4OSA_DataOption OptionValue) { M4OSA_ERR err = M4NO_ERROR; return err; } /** ****************************************************************************** * @brief This method asks the core file reader to return the value associated * with the optionID.The caller is responsible for allocating/de-allocating * the memory of the value field. * @note The options handled by the component depend on the implementation * of the component. * @param pContext: (IN) Execution context. * @param OptionId : (IN) Id of the option to set. * @param pOptionValue : (OUT) Value of the option. * @return M4NO_ERROR: there is no error * @return M4ERR_BAD_CONTEXT pContext is NULL * @return M4ERR_BAD_OPTION_ID the option id is not valid. * @return M4ERR_NOT_IMPLEMENTED The option is not implemented yet. ****************************************************************************** */ M4OSA_ERR M4OSA_fileReadGetOption_optim(M4OSA_Context pContext, M4OSA_FileReadOptionID OptionID, M4OSA_DataOption* pOptionValue) { M4OSA_FileReader_Context_optim* apContext = (M4OSA_FileReader_Context_optim*) pContext; M4OSA_ERR err = M4NO_ERROR; /* Check input parameters */ M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext); if (apContext->IsOpened != M4OSA_TRUE) { return M4ERR_BAD_CONTEXT; /**< The context can not be correct */ } /* Get the desired option if it is avalaible */ switch(OptionID) { /* Get File Size */ case M4OSA_kFileReadGetFileSize:/**< Get size of the file, limited to 32 bit size */ (*(M4OSA_UInt32 *)pOptionValue) = apContext->fileSize; break; /* Check End of file Occurs */ case M4OSA_kFileReadIsEOF : /**< See if we are at the end of the file */ (*(M4OSA_Bool *)pOptionValue) = (apContext->absolutePos >= apContext->fileSize) ? M4OSA_TRUE : M4OSA_FALSE; break; /* Get File Position */ case M4OSA_kFileReadGetFilePosition : /**< Get file position */ *(M4OSA_FilePosition *)pOptionValue = apContext->absolutePos; break; /* Get Attribute */ case M4OSA_kFileReadGetFileAttribute : /**< Get the file attribute = access mode */ (*(M4OSA_FileAttribute *)pOptionValue).modeAccess = apContext->FileAttribute.modeAccess; break; default: /**< Bad option ID */ err = M4ERR_BAD_OPTION_ID; break; } /*Return without error */ return err; }