diff options
author | Dharmaray Kundargi <dharmaray@google.com> | 2011-01-16 16:05:58 -0800 |
---|---|---|
committer | Dharmaray Kundargi <dharmaray@google.com> | 2011-01-16 16:05:58 -0800 |
commit | 855ec7c4be7ad642721909d5837a8d25a117c22f (patch) | |
tree | 13617dd1d9ab643fd311825cb7a973dab89f9681 /libvideoeditor/osal/src | |
parent | 5358e878396e1c451e9f9ef07237c2e6ab662d49 (diff) | |
download | frameworks_av-855ec7c4be7ad642721909d5837a8d25a117c22f.zip frameworks_av-855ec7c4be7ad642721909d5837a8d25a117c22f.tar.gz frameworks_av-855ec7c4be7ad642721909d5837a8d25a117c22f.tar.bz2 |
videoeditor osal files check in on honeycomb
Change-Id: Id6c5f9f8819158ebffa9fd4dbbf5979a0e5f5808
Diffstat (limited to 'libvideoeditor/osal/src')
20 files changed, 14563 insertions, 0 deletions
diff --git a/libvideoeditor/osal/src/Android.mk b/libvideoeditor/osal/src/Android.mk new file mode 100755 index 0000000..bfb440b --- /dev/null +++ b/libvideoeditor/osal/src/Android.mk @@ -0,0 +1,81 @@ +#
+# Copyright (C) 2011 NXP Software
+# 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+#
+# libvideoeditor_osal
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libvideoeditor_osal
+
+LOCAL_SRC_FILES:= \
+ M4OSA_CharStar.c \
+ M4OSA_Clock.c \
+ M4OSA_FileCache.c \
+ M4OSA_FileCommon.c \
+ M4OSA_FileExtra.c \
+ M4OSA_FileReader.c \
+ M4OSA_FileReader_RAM.c \
+ M4OSA_FileWriter.c \
+ M4OSA_FileWriter_RAM.c \
+ M4OSA_Mutex.c \
+ M4OSA_Random.c \
+ M4OSA_Semaphore.c \
+ M4OSA_String.c \
+ M4OSA_String_priv.c \
+ M4OSA_Thread.c \
+ M4PSW_DebugTrace.c \
+ M4PSW_MemoryInterface.c \
+ M4PSW_Trace.c \
+ LVOSA_FileReader_optim.c
+
+LOCAL_MODULE_TAGS := development
+
+LOCAL_SHARED_LIBRARIES := libcutils libutils
+
+LOCAL_C_INCLUDES += \
+ $(TOP)/frameworks/media/libvideoeditor/osal/inc \
+
+ifeq ($(TARGET_SIMULATOR),true)
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+# All of the shared libraries we link against.
+LOCAL_LDLIBS := \
+ -lpthread -ldl
+
+LOCAL_CFLAGS += -Wno-multichar \
+ -D__ANDROID__ \
+ -DM4OSA_FILE_BLOCK_WITH_SEMAPHORE \
+ -DUSE_STAGEFRIGHT_CODECS \
+ -DUSE_STAGEFRIGHT_AUDIODEC \
+ -DUSE_STAGEFRIGHT_VIDEODEC \
+ -DUSE_STAGEFRIGHT_AUDIOENC \
+ -DUSE_STAGEFRIGHT_VIDEOENC \
+ -DUSE_STAGEFRIGHT_READERS \
+ -DUSE_STAGEFRIGHT_3GPP_READER
+
+# Don't prelink this library. For more efficient code, you may want
+# to add this library to the prelink map and set this to true.
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_STATIC_LIBRARY)
+
diff --git a/libvideoeditor/osal/src/LVOSA_FileReader_optim.c b/libvideoeditor/osal/src/LVOSA_FileReader_optim.c new file mode 100755 index 0000000..36541f0 --- /dev/null +++ b/libvideoeditor/osal/src/LVOSA_FileReader_optim.c @@ -0,0 +1,1076 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_malloc(M4OSA_READBUFFER_SIZE, M4OSA_FILE_READER, "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) + M4OSA_free((M4OSA_MemAddr32)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; + + M4OSA_memcpy(pData, 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); + } +#if 0 + fileSeekPosition = 0; + errno = apContext->FS->seek(apContext->aFileDesc, M4OSA_kFileSeekEnd, &fileSeekPosition); + + if (M4NO_ERROR != errno) + { + apContext->readFilePos = M4OSA_EOF; + err = errno; + M4OSA_TRACE1_1("M4OSA_FileReader_CalculateSize ERR1 = 0x%x", err); + } + else + { + /* Retrieve size of the file */ + errno = apContext->FS->getOption(apContext->aFileDesc, + M4OSA_kFileReadGetFilePosition, + (M4OSA_DataOption*) &apContext->fileSize); + if (M4NO_ERROR != errno) + { + err = errno; + M4OSA_TRACE1_1("M4OSA_FileReader_CalculateSize ERR2 = 0x%x", err); + } + apContext->readFilePos = apContext->fileSize; + } +#endif +#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_malloc(sizeof(M4OSA_FileReader_Context_optim), + M4OSA_FILE_READER, "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_malloc(sizeof(M4OSA_FileReadPointer), + M4OSA_FILE_READER, "NXPSW_FileReaderOptim_init"); + if (M4OSA_NULL==apContext->FS) + { + M4OSA_TRACE1_0("NXPSW_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); + } + + M4OSA_free((M4OSA_MemAddr32) 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) + { + M4OSA_free((M4OSA_MemAddr32) apContext->FS); + } + //<<<< GLM20090212 : set the low level function statically + + /* Free the context */ + M4OSA_free((M4OSA_MemAddr32)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; +} diff --git a/libvideoeditor/osal/src/M4OSA_CharStar.c b/libvideoeditor/osal/src/M4OSA_CharStar.c new file mode 100755 index 0000000..4a865c1 --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_CharStar.c @@ -0,0 +1,1602 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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 M4DPAK_CharStar.c + * @ingroup + * @brief definition of the Char Star set of functions. + * @note This file defines the Char Star set of functions. + * + ************************************************************************ +*/ + + +#include "M4OSA_CharStar.h" +#include "M4OSA_Memory.h" +#include "M4OSA_Debug.h" + +/* WARNING: Specific Android */ +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> + + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strncpy(). + * @note It copies exactly len2Copy characters from pStrIn to pStrOut, + * truncating pStrIn or adding null characters to pStrOut if + * necessary. + * - If len2Copy is less than or equal to the length of pStrIn, + * a null character is appended automatically to the copied + * string. + * - If len2Copy is greater than the length of pStrIn, pStrOut is + * padded with null characters up to length len2Copy. + * - pStrOut and pStrIn MUST NOT OVERLAP (this is NOT CHECKED). + * @param pStrOut: (OUT) Destination character string. + * @param pStrIn: (IN) Source character string. + * @param len2Copy: (IN) Maximum number of characters from pStrIn to copy. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pStrOut is M4OSA_NULL. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrNCopy(M4OSA_Char* pStrOut, M4OSA_Char *pStrIn, M4OSA_UInt32 len2Copy) +{ + M4OSA_TRACE1_3("M4OSA_chrNCopy\t(M4OSA_Char* %x,M4OSA_Char* %x,M4OSA_UInt32 %ld)", + pStrOut,pStrIn,len2Copy); + M4OSA_DEBUG_IF2((M4OSA_NULL == pStrOut),M4ERR_PARAMETER, + "M4OSA_chrNCopy:\tpStrOut is M4OSA_NULL"); + M4OSA_DEBUG_IF2((M4OSA_NULL == pStrIn),M4ERR_PARAMETER, + "M4OSA_chrNCopy:\tpStrIn is M4OSA_NULL"); + + strncpy((char *)pStrOut, (const char *)pStrIn, (size_t)len2Copy); + if(len2Copy <= (M4OSA_UInt32)strlen((const char *)pStrIn)) + { + pStrOut[len2Copy] = '\0'; + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strncat(). + * @note It appends at most len2Append characters from pStrIn to the end + * of pStrOut. The initial character of pStrIn overrides the null + * character at the end of pStrOut. THIS LAST NULL CHARACTER IN + * pStrOut MUST BE PRESENT. + * - If a null character appears in pStrIn before len2Append + * characters are appended, the function appends all characters + * from pStrIn, up to this M4OSA_NULL character. + * - If len2Append is greater than the length of pStrIn, the length + * of pStrIn is used in place of len2Append. The resulting string + * is terminated with a null character. + * - pStrOut and pStrIn MUST NOT OVERLAP (this is NOT CHECKED). + * @param pStrOut: (OUT) Destination character string. + * @param pStrIn: (IN) character string to append. + * @param len2Append: (IN) Max number of characters from pStrIn to append. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pStrOut is M4OSA_NULL. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrNCat(M4OSA_Char* pStrOut, M4OSA_Char* pStrIn, + M4OSA_UInt32 len2Append) +{ + M4OSA_TRACE1_3("M4OSA_chrNCat\t(M4OSA_Char* %x,M4OSA_Char* %x,M4OSA_UInt32 %ld)", + pStrOut,pStrIn,len2Append); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrOut, M4ERR_PARAMETER, + "M4OSA_chrNCat:\tpStrOut is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn,M4ERR_PARAMETER, + "M4OSA_chrNCat:\tpStrIn is M4OSA_NULL"); + + strncat((char *)pStrOut, (const char*)pStrIn, (size_t)len2Append); + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strcmp(). + * @note It compares pStrIn1 and pStrIn2 lexicographically. + * The value returned in cmpResult is greater than, equal to, or + * less than 0, if the string pointed to by pStrIn1 is greater than, + * equal to, or less than the string pointed to by pStrIn2 + * respectively. The sign of a non-zero return value is determined + * by the sign of the difference between the values of the first + * pair of bytes that differ in the strings being compared. + * @param pStrIn1: (IN) First character string. + * @param pStrIn2: (IN) Second character string. + * @param cmpResult: (OUT) Comparison result. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn1 pStrIn2 or cmpResult is M4OSA_NULL. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrCompare(M4OSA_Char* pStrIn1, M4OSA_Char* pStrIn2, + M4OSA_Int32* pCmpResult) +{ + M4OSA_TRACE1_3("M4OSA_chrCompare\t(M4OSA_Char* %x,M4OSA_Char* %x,M4OSA_Int32* %x)", + pStrIn1,pStrIn2,pCmpResult); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn1, M4ERR_PARAMETER, + "M4OSA_chrCompare:\tstrIn1 is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn2, M4ERR_PARAMETER, + "M4OSA_chrCompare:\tstrIn2 is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pCmpResult, M4ERR_PARAMETER, + "M4OSA_chrCompare:\tcmpResult is M4OSA_NULL"); + + *pCmpResult = (M4OSA_Int32)strcmp((const char *)pStrIn1, (const char *)pStrIn2); + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strncmp(). + * @note It lexicographically compares at most the first len2Comp + * characters in pStrIn1 and pStrIn2. + * The value returned in cmpResult is greater than, equal to, or + * less than 0, if the first len2Comp characters of the string + * pointed to by pStrIn1 is greater than, equal to, or less than the + * first len2Comp characters of the string pointed to by pStrIn2 + * respectively. The sign of a non-zero return value is determined + * by the sign of the difference between the values of the first + * pair of bytes that differ in the strings being compared. + * @param pStrIn1: (IN) First character string. + * @param pStrIn2: (IN) Second character string. + * @param len2Comp: (IN) Length used for the comparison. + * @param cmpResult: (OUT) Comparison result. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn1 pStrIn2 or cmpResult is M4OSA_NULL. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrNCompare(M4OSA_Char* pStrIn1,M4OSA_Char* pStrIn2, + M4OSA_UInt32 len2Comp, M4OSA_Int32* pCmpResult) +{ + M4OSA_TRACE1_4("M4OSA_chrNCompare\t(M4OSA_Char* %x,M4OSA_Char* %x," + "M4OSA_Int32 %ld, M4OSA_Int32* %x)",pStrIn1,pStrIn2,len2Comp,pCmpResult); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn1,M4ERR_PARAMETER, + "M4OSA_chrNCompare:\tpStrIn1 is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn2,M4ERR_PARAMETER, + "M4OSA_chrNCompare:\tpStrIn2 is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pCmpResult,M4ERR_PARAMETER, + "M4OSA_chrNCompare:\tpCmpResult is M4OSA_NULL"); + + *pCmpResult = (M4OSA_Int32)strncmp((const char*)pStrIn1, (const char*)pStrIn2, + (size_t)len2Comp); + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function returns the boolean comparison of pStrIn1 and pStrIn2. + * @note The value returned in result is M4OSA_TRUE if the string + * pointed to by pStrIn1 is strictly identical to the string pointed + * to by pStrIn2, and M4OSA_FALSE otherwise. + * @param pStrIn1: (IN) First character string. + * @param pStrIn2: (IN) Second character string. + * @param cmpResult: (OUT) Comparison result. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn1 pStrIn2 or cmpResult is M4OSA_NULL. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrAreIdentical(M4OSA_Char* pStrIn1, M4OSA_Char* pStrIn2, + M4OSA_Bool* pResult) +{ + M4OSA_UInt32 i32,len32; + M4OSA_TRACE1_3("M4OSA_chrAreIdentical\t(M4OSA_Char* %x,M4OSA_Char* %x," + "M4OSA_Int32* %x)",pStrIn1,pStrIn2,pResult); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn1, M4ERR_PARAMETER, + "M4OSA_chrAreIdentical:\tpStrIn1 is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn2, M4ERR_PARAMETER, + "M4OSA_chrAreIdentical:\tpStrIn2 is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pResult, M4ERR_PARAMETER, + "M4OSA_chrAreIdentical:\tpResult is M4OSA_NULL"); + + len32 = (M4OSA_UInt32)strlen((const char *)pStrIn1); + if(len32 != (M4OSA_UInt32)strlen((const char *)pStrIn2)) + { + *pResult = M4OSA_FALSE; + return M4NO_ERROR; + } + + for(i32=0;i32<len32;i32++) + { + if(pStrIn1[i32] != pStrIn2[i32]) + { + *pResult = M4OSA_FALSE; + return M4NO_ERROR; + } + } + + *pResult = M4OSA_TRUE; + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strchr(). + * @note It finds the first occurrence (i.e. starting from the beginning + * of the string) of c in pStrIn and set *pPointerInStr to this + * position. + * If no occurrence is found, *pPointerInStr is set to M4OSA_NULL. + * @param pStrIn: (IN) Character string where to search. + * @param c: (IN) Character to search. + * @param pPointerInStr: (OUT) pointer on the first occurrence of c. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pPointerInStr is M4OSA_NULL. + * @return M4WAR_CHR_NOT_FOUND: no occurrence of c found. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrFindChar (M4OSA_Char* pStrIn, M4OSA_Char c, + M4OSA_Char** pInStr) +{ + M4OSA_TRACE1_3("M4OSA_chrFindChar\t(M4OSA_Char* %x, M4OSA_Char %c" + "M4OSA_Char** %x)",pStrIn,c,pInStr); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn,M4ERR_PARAMETER, + "M4OSA_chrFindChar:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pInStr,M4ERR_PARAMETER, + "M4OSA_chrFindChar:\tpInStr is M4OSA_NULL"); + + *pInStr = (M4OSA_Char*)strchr((const char *)pStrIn,(int)c); + if(M4OSA_NULL == *pInStr) + { + return M4WAR_CHR_NOT_FOUND; + } + else + { + return M4NO_ERROR; + } +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strrchr(). + * @note It finds the last occurrence (i.e. starting from the end of the + * string, backward) of c in pStrIn and set *pPointerInStr to this + * position. + * If no occurrence is found, *pPointerInStr is set to M4OSA_NULL. + * @param pStrIn: (IN) Character string where to search. + * @param c: (IN) Character to search. + * @param pPointerInStr: (OUT) pointer on the first occurrence of c. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pPointerInStr is M4OSA_NULL. + * @return M4WAR_CHR_NOT_FOUND: no occurrence of c found. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrReverseFindChar(M4OSA_Char* pStrIn, M4OSA_Char c,M4OSA_Char** pInStr) +{ + M4OSA_TRACE1_3("M4OSA_chrReverseFindChar\t(M4OSA_Char* %x, M4OSA_Char %c" + "M4OSA_Char** %x)",pStrIn,c,pInStr); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrReverseFindChar:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pInStr, M4ERR_PARAMETER, + "M4OSA_chrReverseFindChar:\tpInStr is M4OSA_NULL"); + + *pInStr = (M4OSA_Char*)strrchr((const char *)pStrIn,(int)c); + if(M4OSA_NULL == *pInStr) + { + return M4WAR_CHR_NOT_FOUND; + } + else + { + return M4NO_ERROR; + } +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strspn(). + * @note It returns the length of the initial segment of string pStrIn + * that consists entirely of characters from string pDelimiters + * (it "spans" this set of characters). + * If no occurrence of any character present in pDelimiters is found + * at the beginning of pStrIn, *pPosInStr is M4OSA_NULL. + * @param pStrIn: (IN) Character string where to search. + * @param pDelimiters: (IN) Character string containing the set of + * characters to search. + * @param pPosInStr: (OUT) Length of the initial segment. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn, pDelimiters or pPosInStr is M4OSA_NULL. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrSpan(M4OSA_Char* pStrIn,M4OSA_Char* pDelimiters, + M4OSA_UInt32* pPosInStr) +{ + M4OSA_TRACE1_3("M4OSA_chrSpan\t(M4OSA_Char* %x,M4OSA_Char* %x" + "M4OSA_UInt32* %x)",pStrIn,pDelimiters,pPosInStr); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrSpan:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pDelimiters, M4ERR_PARAMETER, + "M4OSA_chrSpan:\tpDelimiters is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pPosInStr, M4ERR_PARAMETER, + "M4OSA_chrSpan:\tpPosInStr is M4OSA_NULL"); + + *pPosInStr = (M4OSA_UInt32)strspn((const char *)pStrIn, + (const char *)pDelimiters); + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strcspn(). + * @note It returns the length of the initial segment of string pStrIn + * that consists entirely of characters NOT from string delimiters + * (it spans the complement of this set of characters). + * If no occurrence of any character present in delimiters is found + * in pStrIn, *pPosInStr is set to the length of pStrIn. + * @param pStrIn: (IN) Character string where to search. + * @param delimiters: (IN) Character string containing the set of + * characters to search. + * @param pPosInStr: (OUT) Length of the initial segment. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn, delimiters or pPosInStr is M4OSA_NULL. + * @return M4WAR_CHR_NOT_FOUND: no occurrence of any character present in + * delimiters has been found in pStrIn. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrSpanComplement (M4OSA_Char* pStrIn, M4OSA_Char* pDelimiters, + M4OSA_UInt32* pPosInStr) +{ + M4OSA_TRACE1_3("M4OSA_chrSpanComplement\t(M4OSA_Char* %x,M4OSA_Char* %x" + "M4OSA_UInt32* %x)",pStrIn,pDelimiters,pPosInStr); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn,M4ERR_PARAMETER, + "M4OSA_chrSpanComplement:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pDelimiters,M4ERR_PARAMETER, + "M4OSA_chrSpanComplement:\tpDelimiters is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pPosInStr,M4ERR_PARAMETER, + "M4OSA_chrSpanComplement:\tpPosInStr is M4OSA_NULL"); + + *pPosInStr = (M4OSA_UInt32)strcspn((const char *)pStrIn, + (const char *)pDelimiters); + if(*pPosInStr < (M4OSA_UInt32)strlen((const char *)pStrIn)) + { + return M4NO_ERROR; + } + else + { + return M4WAR_CHR_NOT_FOUND; + } +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strpbrk(). + * @note It returns a pointer to the first occurrence in string pStrIn + * of any character from string pDelimiters, or a null pointer if + * no character from pDelimiters exists in pStrIn. In the latter + * case, WAR_NO_FOUND is returned. + * @param pStrIn: (IN) Character string where to search. + * @param pDelimiters: (IN) Character string containing the set of + * characters to search. + * @param pPointerInStr: (OUT) Pointer on the first character belonging to + * pDelimiters. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn, pDelimiters or pPosInStr is M4OSA_NULL. + * @return M4WAR_CHR_NOT_FOUND: no occurrence of any character present in + * pDelimiters has been found in pStrIn. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrPbrk(M4OSA_Char* pStrIn, M4OSA_Char* pDelimiters, + M4OSA_Char **pPointerInStr) +{ + M4OSA_TRACE1_3("M4OSA_chrPbrk\t(M4OSA_Char* %x,M4OSA_Char* %x" + "M4OSA_Char** %x)",pStrIn,pDelimiters,pPointerInStr); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn,M4ERR_PARAMETER, + "M4OSA_chrSpanComplement:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pDelimiters,M4ERR_PARAMETER, + "M4OSA_chrSpanComplement:\tpDelimiters is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pPointerInStr,M4ERR_PARAMETER, + "M4OSA_chrSpanComplement:\tpPointerInStr is M4OSA_NULL"); + + *pPointerInStr = (M4OSA_Char*)strpbrk((const char *)pStrIn, + (const char *)pDelimiters); + if(M4OSA_NULL == *pPointerInStr) + { + return M4WAR_CHR_NOT_FOUND; + } + else + { + return M4NO_ERROR; + } +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strstr(). + * @note It locates the first occurrence of the string pStrIn2 (excluding + * the terminating null character) in string pStrIn1 and set + * pPointerInStr1 to the located string, or to a null pointer if the + * string is not found, in which case M4WAR_CHR_NOT_FOUND is + * returned. If pStrIn2 points to a string with zero length (that + * is, the string ""), the function returns pStrIn1. + * @param pStrIn1: (IN) Character string where to search. + * @param pStrIn2: (IN) Character string to search. + * @param pPointerInStr1: (OUT) Pointer on the first character of pStrIn2 + * in pStrIn1. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn1, pStrIn2 or pPointerInStr1 is M4OSA_NULL. + * @return M4WAR_CHR_NOT_FOUND: no occurrence of pStrIn2 has been found in + * pStrIn1. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrFindPattern(M4OSA_Char* pStrIn1, M4OSA_Char* pStrIn2, + M4OSA_Char** pPointerInStr1) +{ + M4OSA_TRACE1_3("M4OSA_chrFindPattern\t(M4OSA_Char* %x,M4OSA_Char* %x" + "M4OSA_Char** %x)",pStrIn1,pStrIn2,pPointerInStr1); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn1,M4ERR_PARAMETER, + "M4OSA_chrFindPattern:\tpStrIn1 is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn2,M4ERR_PARAMETER, + "M4OSA_chrFindPattern:\tpStrIn2 is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pPointerInStr1,M4ERR_PARAMETER, + "M4OSA_chrFindPattern:\tpPointerInStr1 is M4OSA_NULL"); + + *pPointerInStr1 = (M4OSA_Char*)strstr((const char *)pStrIn1, + (const char *)pStrIn2); + if(M4OSA_NULL == *pPointerInStr1) + { + return M4WAR_CHR_NOT_FOUND; + } + else + { + return M4NO_ERROR; + } +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's strlen(). + * @note It returns the number of characters in pStrIn, not including + * the terminating null character. + * This function have no return code. It does not check that pStrIn + * does not point to null, nor is a valid character string (i.e. + * null-terminated). + * @param pStrIn: (IN) Character string. + * @return number of characters in pStrIn. + ************************************************************************ +*/ +M4OSA_UInt32 M4OSA_chrLength(M4OSA_Char* pStrIn) +{ + M4OSA_TRACE1_1("M4OSA_chrLength\t(M4OSA_Char* %x)",pStrIn); + return (M4OSA_UInt32)strlen((const char *)pStrIn); +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's tolower(). + * @note It converts the character to lower case, if possible and + * appropriate, and returns it. + * @param cIn: (IN) Input character to convert. + * @return converted character. + ************************************************************************ +*/ +M4OSA_Char M4OSA_chrToLower (M4OSA_Char cIn) +{ + M4OSA_TRACE1_1("M4OSA_chrToLower\t(M4OSA_Char %c)",cIn); + return (M4OSA_Char)tolower((int)cIn); +} + +/** + ************************************************************************ + * @brief This function mimics the functionality of the libc's toupper(). + * @note It converts the character to upper case, if possible and + * appropriate, and returns it. + * @param cIn: (IN) Input character to convert. + * @return converted character. + ************************************************************************ +*/ +M4OSA_Char M4OSA_chrToUpper(M4OSA_Char cIn) +{ + M4OSA_TRACE1_1("M4OSA_chrToUpper\t(M4OSA_Char %c)",cIn); + return (M4OSA_Char)toupper((int)cIn); +} + + +M4OSA_ERR M4OSA_chrGetWord(M4OSA_Char* pStrIn, + M4OSA_Char* pBeginDelimiters, + M4OSA_Char* pEndDelimiters, + M4OSA_Char* pStrOut, + M4OSA_UInt32*pStrOutMaxLen, + M4OSA_Char** pOutputPointer) +{ + M4OSA_Char *pTemp; + M4OSA_UInt32 pos; + M4OSA_ERR errorCode; + + M4OSA_TRACE1_4("M4OSA_chrGetWord\t(M4OSA_Char* %x,...,...,M4OSA_Char* %x," + "M4OSA_UInt32* %x,M4OSA_Char** %x)", + pStrIn,pStrOut,pStrOutMaxLen,pOutputPointer); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrGetWord:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pBeginDelimiters, M4ERR_PARAMETER, + "M4OSA_chrGetWord:\tbeginDelimiters is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pEndDelimiters, M4ERR_PARAMETER, + "M4OSA_chrGetWord:\tendDelimiters is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrOut, M4ERR_PARAMETER, + "M4OSA_chrGetWord:\tpStrOut is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrOutMaxLen, M4ERR_PARAMETER, + "M4OSA_chrGetWord:\tstrOutMaxLen is M4OSA_NULL"); + + errorCode = M4OSA_chrSpan(pStrIn, pBeginDelimiters, &pos); + pTemp = pStrIn + pos; + errorCode = M4OSA_chrSpanComplement(pTemp, pEndDelimiters, &pos); + if(pos > *pStrOutMaxLen) + { + *pStrOutMaxLen = pos; + return M4ERR_CHR_STR_OVERFLOW; + } + if(pos) + { + M4OSA_memcpy((M4OSA_MemAddr8)pStrOut,(M4OSA_MemAddr8)pTemp, pos); + } + pStrOut[pos] = '\0'; + if(M4OSA_NULL != pOutputPointer) + { + *pOutputPointer = pTemp + pos; + } + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function gets a M4OSA_UInt32 from string. + * @note This function converts the first set of non-whitespace + * characters of pStrIn to a M4OSA_UInt32 value pVal, assuming a + * representation in base provided by the parameter base. pStrOut is + * set to the first character of the string following the last + * character of the number that has been converted. + * - in case of a failure during the conversion, pStrOut is not + * updated, and pVal is set to null. + * - in case of negative number, pStrOut is not updated, and pVal is + * set to null. + * - in case of numerical overflow, pVal is set to M4OSA_UINT32_MAX. + * - if pStrOut is not to be used, it can be set to M4OSA_NULL. + * @param pStrIn: (IN) Character string. + * @param pVal: (OUT) read value. + * @param pStrOut: (OUT) Output character string. + * @param base: (IN) Base of the character string representation. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL. + * @return M4ERR_CHR_CONV_FAILED: conversion failure. + * @return M4WAR_CHR_NUM_RANGE: the character string represents a number + * greater than M4OSA_UINT32_MAX. + * @return M4WAR_CHR_NEGATIVE: the character string represents a negative + * number. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrGetUInt32(M4OSA_Char* pStrIn, + M4OSA_UInt32* pVal, + M4OSA_Char** pStrOut, + M4OSA_chrNumBase base) +{ + M4OSA_UInt32 ul; + char* pTemp; + + M4OSA_TRACE1_4("M4OSA_chrGetUInt32\t(M4OSA_Char* %x, M4OSA_UInt32* %x" + "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut,base); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrGetUInt32:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER, + "M4OSA_chrGetUInt32:\tpVal is M4OSA_NULL"); + + errno = 0; + switch(base) + { + case M4OSA_kchrDec: + ul = strtoul((const char *)pStrIn, &pTemp, 10); + break; + case M4OSA_kchrHexa: + ul = strtoul((const char *)pStrIn, &pTemp,16); + break; + case M4OSA_kchrOct: + ul = strtoul((const char *)pStrIn, &pTemp,8); + break; + default: + return M4ERR_PARAMETER; + } + + /* has conversion failed ? */ + if((M4OSA_Char*)pTemp == pStrIn) + { + *pVal = 0; + return M4ERR_CHR_CONV_FAILED; + } + + /* was the number negative ? */ + if(*(pStrIn+strspn((const char *)pStrIn," \t")) == '-') + { + *pVal = 0; + return M4WAR_CHR_NEGATIVE; + } + + /* has an overflow occured ? */ + if(errno == ERANGE) + { + *pVal = M4OSA_UINT32_MAX; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* nominal case */ + *pVal = (M4OSA_UInt32)ul; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function gets a M4OSA_UInt16 from string. + * @note This function converts the first set of non-whitespace + * characters of pStrIn to a M4OSA_UInt16 value pVal, assuming a + * representation in base provided by the parameter base. pStrOut is + * set to the first character of the string following the last + * character of the number that has been converted. + * - in case of a failure during the conversion, pStrOut is not + * updated, and pVal is set to null. + * - in case of negative number, pStrOut is not updated, and pVal is + * set to null. + * - in case of numerical overflow, pVal is set to M4OSA_UINT16_MAX. + * - if pStrOut is not to be used, it can be set to M4OSA_NULL. + * @param pStrIn: (IN) Character string. + * @param pVal: (OUT) read value. + * @param pStrOut: (OUT) Output character string. + * @param base: (IN) Base of the character string representation. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL. + * @return M4ERR_CHR_CONV_FAILED: conversion failure. + * @return M4WAR_CHR_NUM_RANGE: the character string represents a number + * greater than M4OSA_UINT16_MAX. + * @return M4WAR_CHR_NEGATIVE: the character string represents a negative + * number. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrGetUInt16 (M4OSA_Char* pStrIn, M4OSA_UInt16 *pVal, + M4OSA_Char** pStrOut, M4OSA_chrNumBase base) +{ + M4OSA_UInt32 ul; + char* pTemp; + + M4OSA_TRACE1_4("M4OSA_chrGetUInt16\t(M4OSA_Char* %x, M4OSA_UInt16* %x" + "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut,base); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn,M4ERR_PARAMETER, + "M4OSA_chrGetUInt16:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER, + "M4OSA_chrGetUInt16:\tpVal is M4OSA_NULL"); + + switch(base) + { + case M4OSA_kchrDec: + ul = strtoul((const char *)pStrIn, &pTemp,10); + break; + case M4OSA_kchrHexa: + ul = strtoul((const char *)pStrIn, &pTemp,16); + break; + case M4OSA_kchrOct: + ul = strtoul((const char *)pStrIn, &pTemp,8); + break; + default: + return M4ERR_PARAMETER; + } + + /* has conversion failed ? */ + if((M4OSA_Char*)pTemp == pStrIn) + { + *pVal = 0; + return M4ERR_CHR_CONV_FAILED; + } + + /* was the number negative ? */ + if(*(pStrIn+strspn((const char *)pStrIn," \t")) == '-') + { + *pVal = 0; + return M4WAR_CHR_NEGATIVE; + } + + /* has an overflow occured ? */ + if(ul>M4OSA_UINT16_MAX) + { + *pVal = M4OSA_UINT16_MAX; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* nominal case */ + *pVal = (M4OSA_UInt16)ul; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function gets a M4OSA_UInt8 from string. + * @note This function converts the first set of non-whitespace + * characters of pStrIn to a M4OSA_UInt8 value pVal, assuming a + * representation in base provided by the parameter base. pStrOut is + * set to the first character of the string following the last + * character of the number that has been converted. + * - in case of a failure during the conversion, pStrOut is not + * updated, and pVal is set to null. + * - in case of negative number, pStrOut is not updated, and pVal is + * set to null. + * - in case of numerical overflow, pVal is set to M4OSA_UINT8_MAX. + * - if pStrOut is not to be used, it can be set to M4OSA_NULL. + * @param pStrIn: (IN) Character string. + * @param pVal: (OUT) read value. + * @param pStrOut: (OUT) Output character string. + * @param base: (IN) Base of the character string representation. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL. + * @return M4ERR_CHR_CONV_FAILED: conversion failure. + * @return M4WAR_CHR_NUM_RANGE: the character string represents a number + * greater than M4OSA_UINT8_MAX. + * @return M4WAR_CHR_NEGATIVE: the character string represents a negative + * number. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrGetUInt8(M4OSA_Char* pStrIn, + M4OSA_UInt8* pVal, + M4OSA_Char** pStrOut, + M4OSA_chrNumBase base) +{ + M4OSA_UInt32 ul; + char* pTemp; + + M4OSA_TRACE1_4("M4OSA_chrGetUInt8\t(M4OSA_Char* %x, M4OSA_UInt8* %x" + "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut,base); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrGetUInt8:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER, + "M4OSA_chrGetUInt8:\tpVal is M4OSA_NULL"); + + switch(base) + { + case M4OSA_kchrDec: + ul = strtoul((const char *)pStrIn, &pTemp, 10); + break; + case M4OSA_kchrHexa: + ul = strtoul((const char *)pStrIn, &pTemp, 16); + break; + case M4OSA_kchrOct: + ul = strtoul((const char *)pStrIn, &pTemp, 8); + break; + default: + return M4ERR_PARAMETER; + } + + /* has conversion failed ? */ + if((M4OSA_Char*)pTemp == pStrIn) + { + *pVal = 0; + return M4ERR_CHR_CONV_FAILED; + } + + /* was the number negative ? */ + if(*(pStrIn+strspn((const char *)pStrIn," \t")) == '-') + { + *pVal = 0; + return M4WAR_CHR_NEGATIVE; + } + + /* has an overflow occured ? */ + if(ul>M4OSA_UINT8_MAX) + { + *pVal = M4OSA_UINT8_MAX; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* nominal case */ + *pVal = (M4OSA_UInt8)ul; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function gets a M4OSA_Int64 from string. + * @note This function converts the first set of non-whitespace + * characters of pStrIn to a M4OSA_Int64 value pVal, assuming a + * decimal representation. pStrOut is set to the first character of + * the string following the last character of the number that has + * been converted. + * - in case of a failure during the conversion, pStrOut is not + * updated, and pVal is set to null. + * - in case of numerical overflow or underflow, pVal is set to + * M4OSA_INT64_MAX or M4OSA_INT64_MIN respectively. + * - if pStrOut is not to be used, it can be set to M4OSA_NULL. + * @param pStrIn: (IN) Character string. + * @param pVal: (OUT) read value. + * @param pStrOut: (OUT) Output character string. + * @param base: (IN) Base of the character string representation. + * FOR THE MOMENT, ONLY DECIMAL REPRESENTATION IS HANDLED. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL. + * @return M4ERR_CHR_CONV_FAILED: conversion failure. + * @return M4WAR_CHR_NUM_RANGE: the character string represents a number + * greater than M4OSA_INT64_MAX or less than M4OSA_INT64_MIN + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrGetInt64(M4OSA_Char* pStrIn, M4OSA_Int64* pVal, + M4OSA_Char** pStrOut, M4OSA_chrNumBase base) +{ +#ifdef M4OSA_64BITS_SUPPORTED + M4OSA_Int64 maxVal = M4OSA_INT64_MAX; /* this is 2^63-1 */ + M4OSA_Int64 minVal = M4OSA_INT64_MIN; /* this is -2^63+1 */ + M4OSA_Char maxStr[] = "9223372036854775807"; + M4OSA_Char* beginNum; + M4OSA_UInt32 maxLen = strlen((const char *)maxStr); + M4OSA_UInt32 chrCount = 0; + M4OSA_UInt8 negative = 0; + + M4OSA_TRACE1_4((M4OSA_Char *)"M4OSA_chrGetInt64\t(M4OSA_Char* %x, M4OSA_UInt64* %x" + "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut,base); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrGetInt64:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER, + "M4OSA_chrGetInt64:\tpVal is M4OSA_NULL"); + + switch(base) + { + case M4OSA_kchrDec: + break; + case M4OSA_kchrOct: + return M4ERR_NOT_IMPLEMENTED; + case M4OSA_kchrHexa: + return M4ERR_NOT_IMPLEMENTED; + default: + return M4ERR_PARAMETER; + } + + /* trim blank characters */ + while (*pStrIn == ' ' || *pStrIn == '\t') pStrIn++; + + /* get the sign */ + if (*pStrIn == '+') pStrIn++; + else if (*pStrIn == '-') + { + negative = 1; + pStrIn++; + } + beginNum = pStrIn; + + /* get the length of the numerical part */ + while((*pStrIn >= '0') && (*pStrIn <= '9')) + { + pStrIn++; + chrCount++; + } + + /* has conversion failed ? */ + if(!chrCount) + { + *pVal = 0; + return M4ERR_CHR_CONV_FAILED; + } + + /* has overflow (or underflow) occured ? */ + if((chrCount > maxLen) /* obvious overflow (or underflow) */ + || + ((chrCount == maxLen) && (strncmp((const char *)beginNum, + (const char *)maxStr, maxLen) > 0))) + /* less obvious overflow (or underflow) */ + { + if(negative) + { + *pVal = minVal; + } + else + { + *pVal = maxVal; + } + if(M4OSA_NULL != pStrOut) + { + *pStrOut = beginNum+chrCount; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* nominal case */ + pStrIn = beginNum; + *pVal = 0; + while((*pStrIn >= '0') && (*pStrIn <= '9')) + { + *pVal = (*pVal)*10 + (*pStrIn++ - '0'); + } + if(negative) + { + *pVal = -*pVal; + } + if(M4OSA_NULL != pStrOut) + { + *pStrOut = pStrIn; + } + return M4NO_ERROR; +#elif defined M4OSA_64BITS_NOT_SUPPORTED + return(M4OSA_chrGetInt32(pStrIn, (M4OSA_Int32*) pVal, pStrOut, M4OSA_kchrDec)); +#else + return(M4ERR_NOT_IMPLEMENTED); +#endif + + } + +/** + ************************************************************************ + * @brief This function gets a M4OSA_Int32 from string. + * @note This function converts the first set of non-whitespace + * characters of pStrIn to a M4OSA_Int32 value pVal, assuming a + * representation in base provided by the parameter base. pStrOut is + * set to the first character of the string following the last + * character of the number that has been converted. + * - in case of a failure during the conversion, pStrOut is not + * updated, and pVal is set to null. + * - in case of numerical overflow or underflow, pVal is set to + * M4OSA_INT32_MAX or M4OSA_INT32_MIN respectively. + * - if pStrOut is not to be used, it can be set to M4OSA_NULL. + * @param pStrIn: (IN) Character string. + * @param pVal: (OUT) read value. + * @param pStrOut: (OUT) Output character string. + * @param base: (IN) Base of the character string representation. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL. + * @return M4ERR_CHR_CONV_FAILED: conversion failure. + * @return M4WAR_CHR_NUM_RANGE: the character string represents a number + * greater than M4OSA_INT32_MAX or less than M4OSA_INT32_MIN + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrGetInt32(M4OSA_Char* pStrIn, + M4OSA_Int32* pVal, + M4OSA_Char** pStrOut, + M4OSA_chrNumBase base) +{ + M4OSA_Int32 l; + char* pTemp; + + M4OSA_TRACE1_4("M4OSA_chrGetInt32\t(M4OSA_Char* %x, M4OSA_Int32* %x" + "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut,base); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn,M4ERR_PARAMETER, + "M4OSA_chrGetInt32:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pVal,M4ERR_PARAMETER, + "M4OSA_chrGetInt32:\tpVal is M4OSA_NULL"); + + errno = 0; + switch(base) + { + case M4OSA_kchrDec: + l = strtol((const char *)pStrIn, &pTemp, 10); + break; + case M4OSA_kchrHexa: + l = strtol((const char *)pStrIn, &pTemp, 16); + break; + case M4OSA_kchrOct: + l = strtol((const char *)pStrIn, &pTemp, 8); + break; + default: + return M4ERR_PARAMETER; + } + + /* has conversion failed ? */ + if((M4OSA_Char*)pTemp == pStrIn) + { + *pVal = 0; + return M4ERR_CHR_CONV_FAILED; + } + + /* has an overflow occured ? */ + if((errno == ERANGE) && (l == M4OSA_INT32_MAX)) + { + *pVal = M4OSA_INT32_MAX; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* has an underflow occured ? */ + if((errno == ERANGE) && (l == M4OSA_INT32_MIN)) + { + *pVal = M4OSA_INT32_MIN; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* nominal case */ + *pVal = (M4OSA_Int32)l; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function gets a M4OSA_Int16 from string. + * @note This function converts the first set of non-whitespace + * characters of pStrIn to a M4OSA_Int16 value pVal, assuming a + * representation in base provided by the parameter base. pStrOut is + * set to the first character of the string following the last + * character of the number that has been converted. + * - in case of a failure during the conversion, pStrOut is not + * updated, and pVal is set to null. + * - in case of numerical overflow or underflow, pVal is set to + * M4OSA_INT16_MAX or M4OSA_INT16_MIN respectively. + * - if pStrOut is not to be used, it can be set to M4OSA_NULL. + * @param pStrIn: (IN) Character string. + * @param pVal: (OUT) read value. + * @param pStrOut: (OUT) Output character string. + * @param base: (IN) Base of the character string representation. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL. + * @return M4ERR_CHR_CONV_FAILED: conversion failure. + * @return M4WAR_CHR_NUM_RANGE: the character string represents a number + * greater than M4OSA_INT16_MAX or less than M4OSA_INT16_MIN + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrGetInt16(M4OSA_Char* pStrIn, + M4OSA_Int16* pVal, + M4OSA_Char** pStrOut, + M4OSA_chrNumBase base) +{ + M4OSA_Int32 l; + char* pTemp; + + M4OSA_TRACE1_4("M4OSA_chrGetInt16\t(M4OSA_Char* %x, M4OSA_Int16* %x" + "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut,base); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrGetInt16:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER, + "M4OSA_chrGetInt16:\tpVal is M4OSA_NULL"); + + switch(base) + { + case M4OSA_kchrDec: + l = strtol((const char *)pStrIn, &pTemp, 10); + break; + case M4OSA_kchrHexa: + l = strtol((const char *)pStrIn, &pTemp, 16); + break; + case M4OSA_kchrOct: + l = strtol((const char *)pStrIn, &pTemp, 8); + break; + default: + return M4ERR_PARAMETER; + } + + /* has conversion failed ? */ + if((M4OSA_Char*)pTemp == pStrIn) + { + *pVal = 0; + return M4ERR_CHR_CONV_FAILED; + } + + /* has an overflow occured ? */ + if(l>M4OSA_INT16_MAX) + { + *pVal = M4OSA_INT16_MAX; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* has an underflow occured ? */ + if(l<M4OSA_INT16_MIN) + { + *pVal = M4OSA_INT16_MIN; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* nominal case */ + *pVal = (M4OSA_UInt16)l; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function gets a M4OSA_Int8 from string. + * @note This function converts the first set of non-whitespace + * characters of pStrIn to a M4OSA_Int8 value pVal, assuming a + * representation in base provided by the parameter base. pStrOut is + * set to the first character of the string following the last + * character of the number that has been converted. + * - in case of a failure during the conversion, pStrOut is not + * updated, and pVal is set to null. + * - in case of numerical overflow or underflow, pVal is set to + * M4OSA_INT8_MAX or M4OSA_INT8_MIN respectively. + * - if pStrOut is not to be used, it can be set to M4OSA_NULL. + * @param pStrIn: (IN) Character string. + * @param pVal: (OUT) read value. + * @param pStrOut: (OUT) Output character string. + * @param base: (IN) Base of the character string representation. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL. + * @return M4ERR_CHR_CONV_FAILED: conversion failure. + * @return M4WAR_CHR_NUM_RANGE: the character string represents a number + * greater than M4OSA_INT8_MAX or less than M4OSA_INT8_MIN + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrGetInt8(M4OSA_Char* pStrIn, + M4OSA_Int8* pVal, + M4OSA_Char** pStrOut, + M4OSA_chrNumBase base) +{ + M4OSA_Int32 l; + char* pTemp; + + M4OSA_TRACE1_4("M4OSA_chrGetInt8\t(M4OSA_Char* %x, M4OSA_Int8* %x" + "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut, + base); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrGetInt8:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER, + "M4OSA_chrGetInt8:\tpVal is M4OSA_NULL"); + + switch(base) + { + case M4OSA_kchrDec: + l = strtol((const char *)pStrIn, &pTemp, 10); + break; + case M4OSA_kchrHexa: + l = strtol((const char *)pStrIn, &pTemp, 16); + break; + case M4OSA_kchrOct: + l = strtol((const char *)pStrIn, &pTemp, 8); + break; + default: + return M4ERR_PARAMETER; + } + + /* has conversion failed ? */ + if((M4OSA_Char*)pTemp == pStrIn) + { + *pVal = 0; + return M4ERR_CHR_CONV_FAILED; + } + + /* has an overflow occured ? */ + if(l>M4OSA_INT8_MAX) + { + *pVal = M4OSA_INT8_MAX; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* has an underflow occured ? */ + if(l<M4OSA_INT8_MIN) + { + *pVal = M4OSA_INT8_MIN; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* nominal case */ + *pVal = (M4OSA_UInt8)l; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function gets a M4OSA_Double from string. + * @note This function converts the first set of non-whitespace + * characters of pStrIn to a M4OSA_Double value pVal. pStrOut is set + * to the first character of the string following the last + * character of the number that has been converted. + * - in case of a failure during the conversion, pStrOut is not + * updated, and pVal is set to null. + * - in case of numerical overflow or underflow, pVal is set to null + * - if pStrOut is not to be used, it can be set to M4OSA_NULL. + * @param pStrIn: (IN) Character string. + * @param pVal: (OUT) read value. + * @param pStrOut: (OUT) Output character string. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL. + * @return M4ERR_CHR_CONV_FAILED: conversion failure. + * @return M4WAR_CHR_NUM_RANGE: an underflow or overflow occurs during the + * conversion. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrGetDouble(M4OSA_Char* pStrIn, + M4OSA_Double* pVal, + M4OSA_Char** pStrOut) +{ + M4OSA_Double d; + char* pTemp; + + M4OSA_TRACE1_3("M4OSA_chrGetDouble\t(M4OSA_Char* %x, M4OSA_Double* %x" + "M4OSA_Char** %x)",pStrIn,pVal,pStrOut); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrGetDouble:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER, + "M4OSA_chrGetDouble:\tpVal is M4OSA_NULL"); + + errno = 0; + d = strtod((const char *)pStrIn, &pTemp); + + /* has conversion failed ? */ + if((M4OSA_Char*)pTemp == pStrIn) + { + *pVal = 0.0; + return M4ERR_CHR_CONV_FAILED; + } + + /* has an overflow or underflow occured ? */ + if(errno == ERANGE) + { + *pVal = 0.0; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + return M4WAR_CHR_NUM_RANGE; + } + + /* nominal case */ + *pVal = (M4OSA_Double)d; + if(M4OSA_NULL != pStrOut) + { + *pStrOut = (M4OSA_Char*)pTemp; + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function gets a M4OSA_Time from string. + * @note Since, M4OSA_Time is defined as M4OSA_Int64, it calls + * M4OSA_chrGetInt64(). + * @param pStrIn: (IN) Character string. + * @param pVal: (OUT) read value. + * @param pStrOut: (OUT) Output character string. + * @param base: (IN) Base of the character string representation. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL. + * @return M4ERR_CHR_CONV_FAILED: conversion failure. + * @return M4WAR_CHR_NUM_RANGE: the character string represents a number + * out of range. + ************************************************************************ +*/ +M4OSA_ERR M4OSA_chrGetTime(M4OSA_Char* pStrIn, + M4OSA_Time* pVal, + M4OSA_Char** pStrOut, + M4OSA_chrNumBase base) +{ + M4OSA_TRACE1_4("M4OSA_chrGetTime\t(M4OSA_Char* %x, M4OSA_Time* %x" + "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut,base); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrGetTime:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER, + "M4OSA_chrGetTime:\tpVal is M4OSA_NULL"); + + return M4OSA_chrGetInt64(pStrIn,(M4OSA_Int64*)pVal,pStrOut,base); +} + +/** + ************************************************************************ + * @brief This function gets a M4OSA_FilePosition from string. + * @note Depending on the M4OSA_FilePosition definition, this function + * calls the correspoding underlying type. + * @param pStrIn: (IN) Character string. + * @param pVal: (OUT) read value. + * @param pStrOut: (OUT) Output character string. + * @param base: (IN) Base of the character string representation. + * @return M4NO_ERROR: there is no error. + * @return M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL. + * @return M4ERR_CHR_CONV_FAILED: conversion failure. + * @return M4WAR_CHR_NUM_RANGE: the character string represents a number + * out of range. + ****************************************************************************** +*/ +M4OSA_ERR M4OSA_chrGetFilePosition(M4OSA_Char* pStrIn, + M4OSA_FilePosition* pVal, + M4OSA_Char** pStrOut, + M4OSA_chrNumBase base) +{ + M4OSA_TRACE1_4("M4OSA_chrGetFilePosition\t(M4OSA_Char* %x, M4OSA_FilePosition* %x" + "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut,base); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER, + "M4OSA_chrGetFilePosition:\tpStrIn is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER, + "M4OSA_chrGetFilePosition:\tpVal is M4OSA_NULL"); + +#ifdef M4OSA_FILE_POS_64_BITS_SUPPORTED + return M4OSA_chrGetInt64(pStrIn,(M4OSA_Int64*)pVal,pStrOut,base); +#else + return M4OSA_chrGetInt32(pStrIn,(M4OSA_Int32*)pVal,pStrOut,base); +#endif + +} + +M4OSA_ERR M4OSA_chrSPrintf(M4OSA_Char *pStrOut, M4OSA_UInt32 strOutMaxLen, + M4OSA_Char *format, ...) +{ + va_list marker; + M4OSA_Char *pTemp; + M4OSA_Char *percentPointer; + M4OSA_Char *newFormat; + M4OSA_Int32 newFormatLength=0; + M4OSA_UInt32 count_ll = 0; + M4OSA_UInt32 count_tm = 0; + M4OSA_UInt32 count_aa = 0; + M4OSA_UInt32 count; + M4OSA_UInt32 nbChar; + M4OSA_Int32 err; + M4OSA_Char flagChar[] = "'-+ #0"; + M4OSA_Char widthOrPrecisionChar[] = "*0123456789"; + M4OSA_Char otherPrefixChar[] = "hlL"; + M4OSA_Char conversionChar[] = "diouxXnfeEgGcCsSp%"; + + M4OSA_TRACE1_3("M4OSA_chrSPrintf\t(M4OSA_Char* %x, M4OSA_UInt32 %ld" + "M4OSA_Char* %x)",pStrOut,strOutMaxLen,format); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrOut, M4ERR_PARAMETER, + "M4OSA_chrSPrintf:\tpStrOut is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == format, M4ERR_PARAMETER, + "M4OSA_chrSPrintf:\tformat is M4OSA_NULL"); + + va_start(marker,format); + + /* count the number of %[flags][width][.precision]ll[conversion] */ + pTemp = format; + while(*pTemp) + { + percentPointer = (M4OSA_Char *)strchr((const char *)pTemp,'%'); /* get the next percent character */ + if(!percentPointer) + break; /* "This is the End", (c) J. Morrisson */ + pTemp = percentPointer+1; /* span it */ + if(!*pTemp) + break; /* "This is the End", (c) J. Morrisson */ + pTemp += strspn((const char *)pTemp,(const char *)flagChar); /* span the optional flags */ + if(!*pTemp) + break; /* "This is the End", (c) J. Morrisson */ + pTemp += strspn((const char *)pTemp,(const char *)widthOrPrecisionChar); /* span the optional width */ + if(!*pTemp) + break; /* "This is the End", (c) J. Morrisson */ + if(*pTemp=='.') + { + pTemp++; + pTemp += strspn((const char *)pTemp, (const char *)widthOrPrecisionChar); /* span the optional precision */ + } + if(!*pTemp) + break; /* "This is the End", (c) J. Morrisson */ + if(strlen((const char *)pTemp)>=2) + { + if(!strncmp((const char *)pTemp,"ll",2)) + { + count_ll++; /* I got ONE */ + pTemp +=2; /* span the "ll" prefix */ + } + else if(!strncmp((const char *)pTemp,"tm",2)) + { + count_tm++; + pTemp +=2; + } + else if(!strncmp((const char *)pTemp,"aa",2)) + { + count_aa++; + pTemp +=2; + } + } + pTemp += strspn((const char *)pTemp, (const char *)otherPrefixChar); /* span the other optional prefix */ + if(!*pTemp) + break; /* "This is the End", (c) J. Morrisson */ + pTemp += strspn((const char *)pTemp, (const char *)conversionChar); + if(!*pTemp) + break; /* "This is the End", (c) J. Morrisson */ + } + + count = count_ll + count_tm + count_aa; + + if(!count) + { + err= vsnprintf((char *)pStrOut, (size_t)strOutMaxLen + 1, (const char *)format, marker); + va_end(marker); + if ((err<0) || ((M4OSA_UInt32)err>strOutMaxLen)) + { + pStrOut[strOutMaxLen] = '\0'; + return M4ERR_CHR_STR_OVERFLOW; + } + else + { + return M4NO_ERROR; + } + } + + + newFormatLength = strlen((const char *)format) + 1; + +#ifdef M4OSA_64BITS_SUPPORTED +#ifdef M4OSA_FILE_POS_64_BITS_SUPPORTED + newFormatLength += (count_ll+count_tm+count_aa); +#else + newFormatLength += (count_ll+count_tm-count_aa); +#endif +#elif defined M4OSA_64BITS_NOT_SUPPORTED + newFormatLength -= (count_ll+count_tm+count_aa); +#else + return M4ERR_NOT_IMPLEMENTED; +#endif + + newFormat =(M4OSA_Char*)M4OSA_malloc(newFormatLength, + M4OSA_CHARSTAR,(M4OSA_Char*)"M4OSA_chrPrintf: newFormat"); + if(M4OSA_NULL == newFormat) + return M4ERR_ALLOC; + newFormat[newFormatLength-1] = '\0'; + pTemp = newFormat; + + /* copy format to newFormat, replacing %[flags][width][.precision]ll[conversion] + * by %[flags][width][.precision]I64[conversion] */ + while(*format) + { + nbChar = strcspn((const char *)format, "%"); + if(nbChar) + { + strncpy((char *)pTemp, (const char *)format, nbChar); /* copy characters before the % character */ + format +=nbChar; + pTemp +=nbChar; + } + if(!*format) break; + *pTemp++ = *format++; /* copy the % character */ + nbChar = strspn((const char *)format, (const char *)flagChar); + if(nbChar) + { + strncpy((char *)pTemp, (const char *)format, nbChar); /* copy the flag characters */ + format +=nbChar; + pTemp +=nbChar; + } + if(!*format) break; + nbChar = strspn((const char *)format, (const char *)widthOrPrecisionChar); + if(nbChar) + { + strncpy((char *)pTemp, (const char *)format, nbChar); /* copy the width characters */ + format +=nbChar; + pTemp +=nbChar; + } + if(!*format) break; + if(*format=='.') + { + *pTemp++ = *format++; /* copy the dot character */ + if(!format) break; + nbChar = strspn((const char *)format, (const char *)widthOrPrecisionChar); + if(nbChar) + { + strncpy((char *)pTemp, (const char *)format, nbChar); /* copy the width characters */ + format +=nbChar; + pTemp +=nbChar; + } + if(!format) break; + } + if(strlen((const char *)format)>=2) + { + if(!strncmp((const char *)format, "ll", 2)) + { +#ifdef M4OSA_64BITS_SUPPORTED + *pTemp++ = 'l'; /* %ll */ + *pTemp++ = 'l'; +#else + *pTemp++ = 'l'; /* %l */ +#endif + format +=2; /* span the "ll" prefix */ + } + else if(!strncmp((const char *)format, "tm", 2)) + { +#ifdef M4OSA_64BITS_SUPPORTED + *pTemp++ = 'l'; /* %ll */ + *pTemp++ = 'l'; +#else + *pTemp++ = 'l'; /* %l */ +#endif + format +=2; /* span the "tm" prefix */ + } + else if(!strncmp((const char *)format, "aa", 2)) + { +#ifdef M4OSA_64BITS_SUPPORTED +#ifdef M4OSA_FILE_POS_64_BITS_SUPPORTED + *pTemp++ = 'l'; /* %ll */ + *pTemp++ = 'l'; +#else + *pTemp++ = 'l'; +#endif +#else + *pTemp++ = 'l'; +#endif + format +=2; /* span the "aa" prefix */ + } + } + nbChar = strspn((const char *)format, (const char *)otherPrefixChar); + if(nbChar) + { + strncpy((char *)pTemp, (const char *)format, nbChar); /* copy the other Prefix */ + format +=nbChar; + pTemp +=nbChar; + } + if(!*format) break; + nbChar = strspn((const char *)format, (const char *)conversionChar); + if(nbChar) + { + strncpy((char *)pTemp, (const char *)format, nbChar); + format += nbChar; + pTemp += nbChar; + } + if(!*format) break; + } + + /* Zero terminate the format string. */ + (*pTemp) = '\0'; + + err = vsnprintf((char *)pStrOut, (size_t)strOutMaxLen + 1, (const char *)newFormat, marker); + va_end(marker); + M4OSA_free((M4OSA_MemAddr32)newFormat); + if ((err<0) || ((M4OSA_UInt32)err>strOutMaxLen)) + { + pStrOut[strOutMaxLen] = '\0'; + return M4ERR_CHR_STR_OVERFLOW; + } + else + { + return M4NO_ERROR; + } +} + diff --git a/libvideoeditor/osal/src/M4OSA_Clock.c b/libvideoeditor/osal/src/M4OSA_Clock.c new file mode 100755 index 0000000..9148fe6 --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_Clock.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_Clock.c + * @brief Clock related functions + * @note This file implements functions to manipulate clock + ************************************************************************ +*/ + +#include <sys/time.h> +#include <time.h> + +#include "M4OSA_Debug.h" +#include "M4OSA_Clock.h" +#include "M4OSA_Memory.h" +#include "M4OSA_Types.h" + + + + +/** + ************************************************************************ + * @brief This function gets an absolute time to an unknown reference with + * a high precision. + * @note It means it can only be used to get a relative time by computing + * differences between to times. + * It is to the caller to allocate time. Time is expressed in + * timescale unit. + * M4OSA_ROLLOVER_CLOCK in M4OSA_Types.h must be configured with the rollover + * offset of this function. + * @param time: (IN/OUT) time + * @param timescale: (IN) The timescale (time unit per second) + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4WAR_TIMESCALE_TOO_BIG: the precision of the system clock is + * not + * compliant with the input timescale + ************************************************************************ +*/ +M4OSA_ERR M4OSA_clockGetTime(M4OSA_Time* pTime, M4OSA_UInt32 timescale) +{ + struct timeval tv; + struct timezone tz; +#ifdef M4OSA_64BITS_NOT_SUPPORTED + M4OSA_UInt32 u32_time = 0; + M4OSA_UInt32 u32_time_hi; + M4OSA_UInt32 u32_time_lo; + M4OSA_UInt32 u32_time_lh; +#else /* M4OSA_64BITS_SUPPORTED */ + M4OSA_Int64 i64_time = 0; + M4OSA_Int64 i64_time_hi; + M4OSA_Int64 i64_time_lo; + M4OSA_Int64 i64_temp; +#endif /* M4OSA_64BITS_SUPPORTED */ + M4OSA_UInt32 factor; + + M4OSA_TRACE1_2("M4OSA_clockGetTime\t\tM4OSA_Time* 0x%x\tM4OSA_UInt32 %d", + pTime, timescale); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pTime, M4ERR_PARAMETER, + "M4OSA_clockGetTime: pTime is M4OSA_NULL"); + M4OSA_DEBUG_IF2(0 == timescale, M4ERR_PARAMETER, + "M4OSA_clockGetTime: timescale is 0"); + + factor = 1000000 / timescale; + + if(gettimeofday(&tv, &tz) == 0) + { +#ifdef M4OSA_64BITS_NOT_SUPPORTED + u32_time_lo = (tv.tv_sec & 0xFFFF) * timescale; + u32_time_hi = (((tv.tv_sec >> 16) & 0xFFFF) * timescale) + ((u32_time_lo >> 16) & 0xFFFF); + u32_time_lo &= 0xFFFF; + u32_time_lo += tv.tv_usec / factor; + u32_time_hi += ((u32_time_lo >> 16) & 0xFFFF); + u32_time_lo &= 0xFFFF; + u32_time = ((u32_time_hi & 0x7FFF) << 16) | u32_time_lo; +#else /* M4OSA_64BITS_SUPPORTED */ + tv.tv_usec /= factor; + M4OSA_INT64_FROM_INT32_UINT32(i64_time_hi, 0, tv.tv_sec); + M4OSA_INT64_FROM_INT32_UINT32(i64_time_lo, 0, tv.tv_usec); + M4OSA_INT64_SCALAR_PRODUCT(i64_temp, i64_time_hi, timescale); + M4OSA_INT64_ADD(i64_time, i64_temp, i64_time_lo); +#endif /* M4OSA_64BITS_SUPPORTED */ + } + +#ifdef M4OSA_64BITS_NOT_SUPPORTED + /* M4OSA_Time is signed, so we need to check the max value*/ + if (u32_time > M4OSA_INT32_MAX) + { + u32_time = u32_time - M4OSA_INT32_MAX; + } + + *pTime = (M4OSA_Time)u32_time; + + if( timescale > 10000 ) + { + return M4WAR_TIMESCALE_TOO_BIG; + } +#else /* M4OSA_64BITS_SUPPORTED */ + *pTime = (M4OSA_Time)i64_time; + + if( timescale > 1000000 ) + { + return M4WAR_TIMESCALE_TOO_BIG; + } +#endif /* M4OSA_64BITS_SUPPORTED */ + + return M4NO_ERROR; +} diff --git a/libvideoeditor/osal/src/M4OSA_FileCache.c b/libvideoeditor/osal/src/M4OSA_FileCache.c new file mode 100755 index 0000000..a804123 --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_FileCache.c @@ -0,0 +1,2978 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_FileCache.c + * + * @brief Osal File Reader and Writer with cache + * @note This file implements functions to manipulate + * filesystem access with intermediate buffers used to + * read and to write. + ************************************************************************* +*/ + +/** + ************************************************************************* + * File cache buffers parameters (size, number of buffers, etc) + ************************************************************************* +*/ +#define M4OSA_CACHEBUFFER_SIZE (8*1024) +#define M4OSA_CACHEBUFFER_NB 6 +#define M4OSA_CACHEBUFFER_NONE -1 +#define M4OSA_CACHEBUFFER_ALL -2 +#define M4OSA_EOF -1 + +/** Strategy used by Osal File Cache to flush the buffers to disk. +Depending on the service, the strategy will have more or less success */ +//#define BUFFER_SELECT_INITIAL /** Initial implementation of Osal File Reader optim */ +//#define BUFFER_SELECT_WITH_TIME /** To flush in priority the buffers which have not been used for a certain time */ +//#define BUFFER_SELECT_WITH_SPACE /** To flush in priority the buffers which have not been used a lot of times */ +#define BUFFER_SELECT_WITH_POS /** To flush in priority the buffers which have the smallest position on the file */ + +/* to measure success of cache operations */ +//#define FILECACHE_STATS + +/* For performance measure */ +//#define M4OSA_FILE_CACHE_TIME_MEAS + +/*** To debug */ +//#define NO_STRATEGY +//#define BUFFER_DISPLAY + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS +#include "M4OSA_clock.h" + +typedef enum +{ + fileOpentime, + fileClosetime, + fileReadDatatime, + fileWriteDatatime, + fileSeektime, + fileGetOptiontime, + fileSetOptiontime, + fileExternalFlushtime, + enum_size /* for enum size */ +} M4OSA_filetimeType; + +typedef M4OSA_Time TabFiletime[enum_size+1]; + +void M4OSA_FileCache_initTimeMeas(M4OSA_Context pContext); +void M4OSA_FileCache_displayTimeMeas(M4OSA_Context pContext); + +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + +/* ANSI C*/ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/stat.h> +/* End: ANSI C includes */ + +#include "M4OSA_FileCommon.h" +#include "M4OSA_FileReader.h" +#include "M4OSA_FileWriter.h" + +#include "M4OSA_FileCache.h" + +#include "M4OSA_Memory.h" +#include "M4OSA_Debug.h" +#include "M4OSA_CharStar.h" +#include "M4OSA_Mutex.h" + + +#define LOCK \ + M4OSA_mutexLock(apContext->m_mutex, M4OSA_WAIT_FOREVER); + +#define UNLOCK \ + M4OSA_mutexUnlock(apContext->m_mutex); + +typedef struct +{ + M4OSA_Void* FileDesc; +} M4OSA_FileSystem_FFS_t_cache; + +typedef struct +{ + M4OSA_Void* (*pFctPtr_Open)( M4OSA_Void* fd, + M4OSA_UInt32 FileModeAccess, + M4OSA_UInt16* errno_ffs ); + M4OSA_FilePosition (*pFctPtr_Read)( M4OSA_Void* fd, + M4OSA_UInt8* data, + M4OSA_FilePosition size, + M4OSA_UInt16* errno_ffs ); + M4OSA_FilePosition (*pFctPtr_Write)( M4OSA_Void* fd, + M4OSA_UInt8* data, + M4OSA_FilePosition size, + M4OSA_UInt16* errno_ffs ); + M4OSA_FilePosition (*pFctPtr_Seek)( M4OSA_Void* fd, + M4OSA_FilePosition pos, + M4OSA_FileSeekAccessMode mode, + M4OSA_UInt16* errno_ffs ); + M4OSA_FilePosition (*pFctPtr_Tell)( M4OSA_Void* fd, + M4OSA_UInt16* errno_ffs ); + M4OSA_Int32 (*pFctPtr_Close)( M4OSA_Void* fd, + M4OSA_UInt16* errno_ffs ); + M4OSA_Void (*pFctPtr_AccessType)( M4OSA_UInt32 FileModeAccess_In, + M4OSA_Void* FileModeAccess_Out ); + +} M4OSA_FileSystem_FctPtr_cache; + +M4OSA_Void* M4OSA_FileSystem_FFS_Open_cache( M4OSA_Void* pFileDescriptor, + M4OSA_UInt32 FileModeAccess, + M4OSA_UInt16* errno_ffs ); +M4OSA_Int32 M4OSA_FileSystem_FFS_Close_cache( M4OSA_Void* pContext, + M4OSA_UInt16* errno_ffs ); +M4OSA_FilePosition M4OSA_FileSystem_FFS_Read_cache( M4OSA_Void* pContext, + M4OSA_UInt8* data, + M4OSA_FilePosition size, + M4OSA_UInt16* errno_ffs ); +M4OSA_FilePosition M4OSA_FileSystem_FFS_Write_cache( M4OSA_Void* pContext, + M4OSA_UInt8* data, + M4OSA_FilePosition size, + M4OSA_UInt16* errno_ ); +M4OSA_Int32 M4OSA_FileSystem_FFS_Seek_cache( M4OSA_Void* pContext, + M4OSA_FilePosition pos, + M4OSA_FileSeekAccessMode mode, + M4OSA_UInt16* errno_ffs ); +M4OSA_FilePosition M4OSA_FileSystem_FFS_Tell_cache( M4OSA_Void* pContext, + M4OSA_UInt16* errno_ffs ); + +M4OSA_ERR M4OSA_fileOpen_cache_internal(M4OSA_Context* pContext, + M4OSA_Void* pFileDescriptor, + M4OSA_UInt32 FileModeAccess, + M4OSA_FileSystem_FctPtr_cache *FS); + +/* +------------------User-------------------- + ^ + | +-------- -------- ---------- +|Filled| |Copied| |Modified| +-------- -------- ---------- + ^ + | +------------------Disk-------------------- + +Atomic states for a buffer: + +0x00 initialized or flushed (When it is initialized again, it is flushed if necessary) +0x01 Filled from disk +0x03 Filled and Copied to user + +0x80 Modified and newly created (does not exist on disk) => must be flushed +0x83 Modified after having been read from disk => must be flushed + +*/ + +typedef enum +{ + M4OSA_kInitialized = 0, + M4OSA_kFilled = 0x1, + M4OSA_kCopied = 0x2, + M4OSA_kModified = 0x80 +} M4OSA_FileCacheStateAtomic; + + +/** + ****************************************************************************** + * structure M4OSA_FileCache_Buffer + * @brief This structure defines the File Buffers context (private) + ****************************************************************************** +*/ +typedef struct +{ + M4OSA_MemAddr8 data; /**< buffer data */ + M4OSA_FilePosition size; /**< size of the buffer */ + M4OSA_FilePosition filepos; /**< position in the file of the buffer's first octet */ + 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. to detect dead buffers */ + + M4OSA_UInt32 nbAccessed; /**< nb of times the buffer has been accessed without being reinitialized */ + M4OSA_Time timeAccessed; /**< last time at which the buffer has been accessed without being reinitialized */ + + M4OSA_UInt8 state; +} M4OSA_FileCache_Buffer; + +/** + ****************************************************************************** + * structure M4OSA_FileCache_Context + * @brief This structure defines the File context (private) + * @note This structure is used for all File 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 file pointer */ + M4OSA_FilePosition absolutePos; /**< Virtual position for next reading */ + M4OSA_FilePosition absoluteWritePos; /**< Virtual position for next writing */ + M4OSA_FilePosition fileSize; /**< Size of the file */ + M4OSA_FilePosition virtualFileSize; /**< Size of the file */ + + M4OSA_FileCache_Buffer buffer[M4OSA_CACHEBUFFER_NB]; /**< buffers */ + + M4OSA_Void* aFileDesc; /**< File descriptor */ + M4OSA_FileSystem_FctPtr_cache *FS; /**< Filesystem interface */ + +#ifdef FILECACHE_STATS + M4OSA_UInt32 cacheSuccessRead; + M4OSA_UInt32 cacheSuccessWrite; + M4OSA_UInt32 nbReadCache; + M4OSA_UInt32 nbWriteCache; + + M4OSA_UInt32 nbReadFFS; + M4OSA_UInt32 nbWriteFFS; +#endif /* FILECACHE_STATS */ + M4OSA_Context m_mutex; + + M4OSA_Time chrono; + M4OSA_Char m_filename[256]; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + TabFiletime gMyPerfFileTab; +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + +} M4OSA_FileCache_Context; + + +#define M4ERR_CHECK_NULL_RETURN_VALUE(retval, pointer) if ((pointer) == M4OSA_NULL) return (retval); + +/* used to detect dead buffers */ +#define MAX_FILLS_SINCE_LAST_ACCESS M4OSA_CACHEBUFFER_NB*2 + + +/* __________________________________________________________ */ +/*| |*/ +/*| Quick Sort function (private) |*/ +/*|__________________________________________________________|*/ + +M4OSA_Void M4OSA_FileCache_internalQuicksort(M4OSA_Int32* const table, + const M4OSA_Int32 first , const M4OSA_Int32 last) + { + M4OSA_Int32 startIndex; + M4OSA_Int32 endIndex; + M4OSA_Int32 begin; + M4OSA_Int32 end; + M4OSA_Int32 pivot; + M4OSA_Int32 temp; + M4OSA_Int32 index=0; + M4OSA_Int32 size=0; + M4OSA_Int32 capacity = M4OSA_CACHEBUFFER_NB * 5; + //allocation of the fifo + M4OSA_Int32* queue = M4OSA_NULL; + M4OSA_Int32* cursor; + M4OSA_Int32* indexc; + + queue = (M4OSA_Int32*)M4OSA_malloc(capacity*sizeof(M4OSA_Int32), 0, + (M4OSA_Char*) "quicksort FIFO of FileCache"); + + if(queue == M4OSA_NULL) + return; + cursor = queue; + indexc = queue; + *(cursor++) = first; //remember the array first element + *(cursor++) = last; //remember the array end + index = 0; + size = 2; + do + { + startIndex = *(indexc++); + endIndex = *(indexc++); + index+=2; + if(startIndex < endIndex) + { + begin = startIndex; + end = endIndex; + pivot = table[endIndex]; + do + { + while ( (begin < endIndex) && (table[begin]<=pivot) ) + begin++; + while ( (end > begin) && (table[end]>=pivot) ) + end--; + if (begin < end) + { + temp = table[end]; + table[end] = table[begin]; + table[begin] = temp; + } + }while(begin < end); + + temp = table[endIndex]; + table[endIndex] = table[begin]; + table[begin] = temp; + *(cursor++) = startIndex; + *(cursor++) = begin-1; + *(cursor++) = begin+1; + *(cursor++) = endIndex; + size+=4; + if(size==capacity) + { + M4OSA_TRACE1_0("Overflow in quickSort. increase capacity size"); + return; + } + } + } + while(index<size); + cursor = NULL; + indexc = NULL; + M4OSA_free(queue); +} + +M4OSA_Void M4OSA_FileCache_internalQuicksort64(M4OSA_Int64* const table, + const M4OSA_Int32 first , const M4OSA_Int32 last) + { + M4OSA_Int32 startIndex; + M4OSA_Int32 endIndex; + M4OSA_Int32 begin; + M4OSA_Int32 end; + M4OSA_Int64 pivot; + M4OSA_Int64 temp; + M4OSA_Int32 index=0; + M4OSA_Int32 size=0; + M4OSA_Int32 capacity = M4OSA_CACHEBUFFER_NB * 5; + //allocation of the fifo + M4OSA_Int32* queue = M4OSA_NULL; + M4OSA_Int32* cursor; + M4OSA_Int32* indexc; + + queue = (M4OSA_Int32*)M4OSA_malloc(capacity*sizeof(M4OSA_Int32), 0, + (M4OSA_Char*) "quicksort FIFO of FileCache"); + + if(queue == M4OSA_NULL) + return; + cursor = queue; + indexc = queue; + *(cursor++) = first; //remember the array first element + *(cursor++) = last; //remember the array end + index = 0; + size = 2; + do + { + startIndex = *(indexc++); + endIndex = *(indexc++); + index+=2; + if(startIndex < endIndex) + { + begin = startIndex; + end = endIndex; + pivot = table[endIndex]; + do + { + while ( (begin < endIndex) && (table[begin]<=pivot) ) + begin++; + while ( (end > begin) && (table[end]>=pivot) ) + end--; + if (begin < end) + { + temp = table[end]; + table[end] = table[begin]; + table[begin] = temp; + } + }while(begin < end); + + temp = table[endIndex]; + table[endIndex] = table[begin]; + table[begin] = temp; + *(cursor++) = startIndex; + *(cursor++) = begin-1; + *(cursor++) = begin+1; + *(cursor++) = endIndex; + size+=4; + if(size==capacity) + { + M4OSA_TRACE1_0("Overflow in quickSort. increase capacity size"); + return; + } + } + } + while(index<size); + cursor = NULL; + indexc = NULL; + M4OSA_free(queue); +} + +/* Sorts an array of size size */ +M4OSA_Void M4OSA_FileCache_QS_quickSort (M4OSA_FilePosition array[], + M4OSA_UInt32 size) +{ + if (size==1 || size==0) + { + M4OSA_TRACE3_0("Sort not necessary"); + return; + } + + M4OSA_FileCache_internalQuicksort(array,0,size-1); +} + +M4OSA_Void M4OSA_FileCache_QS_quickSort64 (M4OSA_Time array[], M4OSA_UInt32 size) +{ + if (size==1 || size==0) + { + M4OSA_TRACE3_0("Sort not necessary"); + return; + } + + M4OSA_FileCache_internalQuicksort64(array,0,size-1); +} + +/* __________________________________________________________ */ +/*| |*/ +/*| Buffer handling functions for RW access (private) |*/ +/*|__________________________________________________________|*/ + +/**************************************************************/ +M4OSA_ERR M4OSA_FileCache_BuffersInit(M4OSA_FileCache_Context* apContext) +/**************************************************************/ +{ + M4OSA_UInt8 i; + + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + apContext->buffer[i].state = M4OSA_kInitialized; + M4OSA_memset((M4OSA_MemAddr8)&(apContext->buffer[i]), + sizeof(M4OSA_FileCache_Buffer) , 0); + } + + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + apContext->buffer[i].data = (M4OSA_MemAddr8) M4OSA_malloc(M4OSA_CACHEBUFFER_SIZE, + M4OSA_FILE_READER, (M4OSA_Char*)"M4OSA_FileCache_BufferInit"); + M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_ALLOC, apContext->buffer[i].data); + apContext->buffer[i].filepos = M4OSA_EOF; + + } + + return M4NO_ERROR; +} + +/**************************************************************/ +M4OSA_Void M4OSA_FileCache_BuffersFree(M4OSA_FileCache_Context* apContext) +/**************************************************************/ +{ + M4OSA_UInt8 i; + + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if(apContext->buffer[i].data != M4OSA_NULL) + { + M4OSA_free((M4OSA_MemAddr32)apContext->buffer[i].data); + apContext->buffer[i].data = M4OSA_NULL; + } + } +} + +#ifdef BUFFER_DISPLAY +M4OSA_Void M4OSA_FileCache_BufferDisplay(M4OSA_FileCache_Context* apContext) +{ + M4OSA_UInt32 i; + + M4OSA_TRACE1_0("------ Buffers display "); + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + M4OSA_TRACE1_5("------ Buf%d : FilePos=%d state=0x%x nbAccessed=%d -- timeAccessed=%d", + i, apContext->buffer[i].filepos, + apContext->buffer[i].state, + apContext->buffer[i].nbAccessed, + apContext->buffer[i].timeAccessed); + } + M4OSA_TRACE1_0("---------------------- "); +} +#endif + + +/* reads from an existing buffer (number i) at absolute position pos and fills pData. it reads maximum one bloc */ +/**************************************************************/ +M4OSA_FilePosition M4OSA_FileCache_BufferCopy(M4OSA_FileCache_Context* apContext, + M4OSA_Int8 i, M4OSA_FilePosition pos, + M4OSA_FilePosition size, + M4OSA_MemAddr8 pData) +/**************************************************************/ +{ + M4OSA_FilePosition copysize; + M4OSA_FilePosition offset; + + M4OSA_TRACE3_2("BufferCopy of %d, pos=%d", i, pos); + + if(apContext->buffer[i].size == M4OSA_EOF) return M4OSA_EOF; + + /* verification pos is inside buffer i*/ + 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; /* offset to read from in the buffer */ + + copysize = apContext->buffer[i].size - offset; /* buffer size - offset, it is the maximum we can read from a buffer */ + copysize = (size < copysize) ? size : copysize; /* adjust in case user wants to read less than the data available in the buffer (copysize) + in that case, take the min(copysize, size)*/ + + M4OSA_memcpy(pData, apContext->buffer[i].data + offset, copysize); + + apContext->buffer[i].remain -= copysize; + apContext->buffer[i].nbFillSinceLastAcess = 0; + + + /* it is a read access */ + apContext->buffer[i].nbAccessed++; + apContext->buffer[i].timeAccessed = apContext->chrono; + apContext->chrono++; + + + apContext->buffer[i].state |= M4OSA_kCopied; + + return copysize; +} + +/* writes on cache. at absolute position pos and writes pData to the buffer. it writes maximum one bloc */ +/**************************************************************/ +M4OSA_FilePosition M4OSA_FileCache_BufferModifyContent(M4OSA_FileCache_Context* apContext, + M4OSA_Int8 i, M4OSA_FilePosition pos, + M4OSA_FilePosition size, + M4OSA_MemAddr8 pData) +/**************************************************************/ +{ + M4OSA_FilePosition copysize; + M4OSA_FilePosition offset, gridPos; + + M4OSA_TRACE3_2("BufferModify of %d, pos=%d", i, pos); + + /* Relocate to absolute postion if necessary */ + gridPos = (pos / M4OSA_CACHEBUFFER_SIZE) * M4OSA_CACHEBUFFER_SIZE; + + apContext->buffer[i].filepos = gridPos; + + /* in case of an existing block (not at eof) */ + if (apContext->buffer[i].size != 0) + { + /* test if we are already inside this buffer */ + if ( (pos < apContext->buffer[i].filepos) + || (pos > (apContext->buffer[i].filepos + M4OSA_CACHEBUFFER_SIZE)) ) + { + M4OSA_TRACE1_0("BufferModify ERR nothing copied, should never happen"); + return 0; /* nothing copied */ + } + } + + offset = pos - apContext->buffer[i].filepos; /* offset to write to, in the buffer */ + + /* buffer size - offset, it is the maximum we can write into a buffer */ + copysize = M4OSA_CACHEBUFFER_SIZE - offset; + /* adjust in case user wants to write less than the data available in the buffer (copysize) in that case, take the min(copysize, size)*/ + copysize = (copysize < size) ? copysize : size; + + M4OSA_memcpy(apContext->buffer[i].data + offset, pData, copysize); + + /* update buffer size if it is a new buffer or expanded one*/ + if (apContext->buffer[i].size < copysize+offset) + { + apContext->buffer[i].size = copysize+offset; + } + + apContext->buffer[i].remain = M4OSA_CACHEBUFFER_SIZE - apContext->buffer[i].size; /* not temporary */ + + /* mark this buffer as modified */ + apContext->buffer[i].state |= M4OSA_kModified; + + apContext->buffer[i].nbFillSinceLastAcess = 0; + apContext->buffer[i].nbAccessed++; + apContext->buffer[i].timeAccessed = apContext->chrono; + apContext->chrono++; + + return copysize; +} + + +/* writes in a buffer (number i) with the data read from disk*/ +/**************************************************************/ +M4OSA_ERR M4OSA_FileCache_BufferFill(M4OSA_FileCache_Context* apContext, + M4OSA_Int8 i, M4OSA_FilePosition pos) +/**************************************************************/ +{ + M4OSA_FilePosition gridPos; + M4OSA_FilePosition diff; + M4OSA_FilePosition size; + M4OSA_ERR err = M4NO_ERROR; + M4OSA_Int32 ret_val; + M4OSA_UInt16 errReturned; + + M4OSA_TRACE3_2("BufferFill i = %d pos = %d", i, pos); + + /* Avoid cycling statement because of EOF */ + if(pos > apContext->virtualFileSize) + return M4WAR_NO_MORE_AU; + + /* Relocate to absolute postion if necessary */ + gridPos = (pos / M4OSA_CACHEBUFFER_SIZE) * M4OSA_CACHEBUFFER_SIZE; + + /* diff is how much shall we fs_seek from current position to reach gridPos*/ + diff = gridPos - apContext->readFilePos; + + /* on some filesystems it is necessary to do a seek between an ffs read and ffs write even if it is same pos */ + ret_val = apContext->FS->pFctPtr_Seek(apContext->aFileDesc, + diff, M4OSA_kFileSeekCurrent, &errReturned); + apContext->readFilePos = gridPos; + + if(ret_val != 0) + { + err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errReturned); + M4OSA_TRACE2_1("M4OSA_FileCache_BufferFill ERR1 = 0x%x", err); + return err; + } + /* end. on some */ + +/* the buffer will be reused to be filled with another filepos so reinit counters of access */ + if (apContext->buffer[i].filepos != gridPos) + { + apContext->buffer[i].nbAccessed = 0; + apContext->buffer[i].timeAccessed = 0; + } + + /* stores the information relative to this buffer */ + apContext->buffer[i].filepos = gridPos; + + /* Read Data */ + size = apContext->FS->pFctPtr_Read(apContext->aFileDesc, + (M4OSA_UInt8*)apContext->buffer[i].data, + M4OSA_CACHEBUFFER_SIZE, &errReturned); + +#ifdef FILECACHE_STATS + apContext->nbReadFFS++; +#endif /* FILECACHE_STATS */ + + if(size == -1) + { + apContext->buffer[i].size = M4OSA_EOF; + apContext->buffer[i].remain = 0; + + err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errReturned); + M4OSA_TRACE2_1("M4OSA_FileCache_BufferFill ERR2 = 0x%x", err); + return err; + } + + apContext->buffer[i].size = size; + apContext->buffer[i].remain = size; + apContext->buffer[i].nbFillSinceLastAcess = 0; + + + /* Retrieve current position */ + apContext->readFilePos = apContext->FS->pFctPtr_Tell(apContext->aFileDesc, + &errReturned); + + if( (apContext->buffer[i].size >= 0) + && (apContext->buffer[i].size < M4OSA_CACHEBUFFER_SIZE) ) + { + err = M4WAR_NO_DATA_YET; + M4OSA_TRACE2_1("M4OSA_FileCache_BufferFill ERR3 = 0x%x", err); + return err; + } + + /* mark this buffer as modified */ + apContext->buffer[i].state |= M4OSA_kFilled; + + /* it is a write access */ + apContext->buffer[i].nbAccessed++; + apContext->buffer[i].timeAccessed = apContext->chrono; + apContext->chrono++; + + /* Return without error */ + return M4NO_ERROR; +} + +/* Reinitializes a buffer for filling it for data at end of file. fileposition is given */ +/**************************************************************/ +M4OSA_ERR M4OSA_FileCache_BufferReinitialize(M4OSA_FileCache_Context* apContext, + M4OSA_Int8 i, M4OSA_FilePosition pos) +/**************************************************************/ +{ + M4OSA_FilePosition gridPos; + M4OSA_ERR err = M4NO_ERROR; + + M4OSA_MemAddr8 saveDataAddress; + + M4OSA_TRACE3_2("BufferReinitialize i = %d pos = %d", i, pos); + + /* Relocate to absolute postion if necessary */ + if (pos != -1) + gridPos = (pos / M4OSA_CACHEBUFFER_SIZE) * M4OSA_CACHEBUFFER_SIZE; + else + gridPos = -1; + + /* RAZ the buffer, only "data address" stays*/ + saveDataAddress = apContext->buffer[i].data; + + M4OSA_memset((M4OSA_MemAddr8)&(apContext->buffer[i]), + sizeof(M4OSA_FileCache_Buffer) , 0); + + /* put again the precious "data address" previously allocated */ + apContext->buffer[i].data = saveDataAddress; + + /* initializations already done in the memset: */ + /* mark this buffer as initialized*/ + apContext->buffer[i].state= M4OSA_kInitialized; + apContext->buffer[i].nbAccessed = 0; + apContext->buffer[i].timeAccessed = 0; + + /* Relocate to absolute postion if necessary */ + apContext->buffer[i].filepos = gridPos; + + /* Return without error */ + return M4NO_ERROR; +} + + +/* flushes a buffer (number i) to the disk*/ +/**************************************************************/ +M4OSA_ERR M4OSA_FileCache_BufferFlush(M4OSA_FileCache_Context* apContext, + M4OSA_UInt8 i) +/**************************************************************/ +{ + M4OSA_FilePosition gridPos, pos; + M4OSA_FilePosition diff; + M4OSA_FilePosition size; + M4OSA_ERR err = M4NO_ERROR; + M4OSA_Int32 ret_val; + M4OSA_UInt16 errReturned; + + M4OSA_TRACE3_2("BufferFlush of buffer i=%d its pos=%d", i, + apContext->buffer[i].filepos); + + pos = apContext->buffer[i].filepos; + + /* Relocate to absolute postion if necessary */ + gridPos = (pos / M4OSA_CACHEBUFFER_SIZE) * M4OSA_CACHEBUFFER_SIZE; + + /* diff is how much shall we fs_seek from current position to reach gridPos*/ + diff = gridPos - apContext->readFilePos; + + if (pos > apContext->fileSize) + { + M4OSA_TRACE1_2("M4OSA_FileCache_BufferFlush: Error! Attempt to seek at pos=%d, whilst fileSize=%d ", + pos, apContext->fileSize); + return M4WAR_NO_MORE_AU; + } + + /* on some filesystems it is necessary to do a seek between an ffs read and ffs write even if it is same pos */ + ret_val = apContext->FS->pFctPtr_Seek(apContext->aFileDesc, diff, + M4OSA_kFileSeekCurrent, &errReturned); + apContext->readFilePos = gridPos; + + if(ret_val != 0) + { + err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errReturned); + M4OSA_TRACE1_1("M4OSA_FileCache_BufferFill ERR1 = 0x%x", err); + return err; + } + /* end: on some filesystems*/ + + /* update the read file pos after the seek */ + apContext->readFilePos = apContext->buffer[i].filepos; + + /* Write Data */ + size = apContext->FS->pFctPtr_Write(apContext->aFileDesc, + (M4OSA_UInt8*)apContext->buffer[i].data, + apContext->buffer[i].size, &errReturned); +#ifdef FILECACHE_STATS + apContext->nbWriteFFS++; +#endif /* FILECACHE_STATS */ + /* verify if all data requested to be written, has been written */ + if(size < apContext->buffer[i].size) + { + apContext->buffer[i].size = M4OSA_EOF; + apContext->buffer[i].remain = 0; + + err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errReturned); + M4OSA_TRACE1_1("M4OSA_FileCache_BufferFlush ERR2 = 0x%x", err); + return err; + } + + /* Retrieve current position */ + apContext->readFilePos = apContext->FS->pFctPtr_Tell(apContext->aFileDesc, + &errReturned); + + apContext->fileSize = (apContext->readFilePos > apContext->fileSize) ? apContext->readFilePos : apContext->fileSize; + + /* mark this buffer as not modified */ + apContext->buffer[i].state &= ~(M4OSA_kModified); + + /* Return without error */ + return M4NO_ERROR; +} + +/* flushes all modified buffers until the position of buffer i +if index is M4OSA_CACHEBUFFER_ALL then flush all*/ +/**************************************************************/ +M4OSA_ERR M4OSA_FileCache_BuffersFlushUntil(M4OSA_FileCache_Context* apContext, + M4OSA_Int8 index) +/**************************************************************/ +{ + M4OSA_UInt8 i, j, howManyToFlush; + M4OSA_FilePosition bufPos[M4OSA_CACHEBUFFER_NB]; + M4OSA_Bool flushed = M4OSA_FALSE; + M4OSA_ERR err = M4NO_ERROR; + + + i=0; + for(j=0; j<M4OSA_CACHEBUFFER_NB; j++) + { + if ( ((apContext->buffer[j].state & M4OSA_kModified) == M4OSA_kModified) ) + { + bufPos[i] = apContext->buffer[j].filepos; + i++; + } + } + howManyToFlush = i; + + if (howManyToFlush == 0) + { + M4OSA_TRACE2_0("BuffersFlush : no flush needed"); + return M4NO_ERROR; + } + else if (howManyToFlush == 1) + { + goto flushing; + } + + M4OSA_FileCache_QS_quickSort(bufPos, howManyToFlush); + +flushing: + if (index == M4OSA_CACHEBUFFER_ALL) + {/* simply flush all buffers in order of positions */ + for(j=0; j<howManyToFlush; j++) + { + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + if (apContext->buffer[i].filepos == bufPos[j] ) + { + M4OSA_TRACE2_2("M4OSA_FileCache_BuffersFlushUntil(1) : We Need to Flush buffer %d its pos=%d", + i, apContext->buffer[i].filepos); + err = M4OSA_FileCache_BufferFlush(apContext, i); + if (M4NO_ERROR!= err) + { + return err; + } + break; + } + } + } + else + { /* there is a given index to flush until it*/ + for(j=0; j<howManyToFlush; j++) + { + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if ( + apContext->buffer[i].filepos == bufPos[j] + && apContext->buffer[i].filepos <= apContext->buffer[index].filepos + && apContext->buffer[i].filepos >= apContext->fileSize - M4OSA_CACHEBUFFER_SIZE + ) + { + M4OSA_TRACE2_2("M4OSA_FileCache_BuffersFlushUntil(2) : We Need to Flush buffer %d its pos=%d", + i, apContext->buffer[i].filepos); + err = M4OSA_FileCache_BufferFlush(apContext, i); + if (M4NO_ERROR!= err) + { + return err; + } + if (i==index) + { /* the buffer with the given index has been flushed */ + flushed = M4OSA_TRUE; + } + break; + } + } + + } + + if (M4OSA_TRUE == flushed) + { + err = M4NO_ERROR; + } + else + { + M4OSA_TRACE1_1("M4OSA_FileCache_BuffersFlushUntil err=0x%x", err); + err = M4ERR_BAD_CONTEXT; + } + + } + + return err; + +} + +#ifdef BUFFER_DISPLAY +M4OSA_Void M4OSA_FileCache_BufferDisplay(M4OSA_FileCache_Context* apContext) +{ + M4OSA_UInt32 i; + + M4OSA_TRACE1_0("------ Buffers display "); + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + M4OSA_TRACE1_3("------ Buf%d : FilePos=%d state=0x%x ", + i, apContext->buffer[i].filepos, apContext->buffer[i].state); +#ifdef BUFFER_DATE + M4OSA_TRACE1_2("nbAccessed=%d - nbModified =%d", + apContext->buffer[i].nbAccessed, apContext->buffer[i].nbModified); + M4OSA_TRACE1_2("timeAccessed=%d - timeModified =%d", + apContext->buffer[i].timeAccessed, + apContext->buffer[i].timeModified); +#endif /* BUFFER_DATE */ + } + M4OSA_TRACE1_0("---------------------- "); +} +#endif + + +/* provides the buffer corresponding to a position pos +and with pos inside the read data into this buffer +else returns CACHE_BUFFER_NONE*/ +/**************************************************************/ +M4OSA_Int8 M4OSA_FileCache_BufferMatchToRead(M4OSA_FileCache_Context* apContext, + M4OSA_FilePosition pos) +/**************************************************************/ +{ + M4OSA_Int8 i; + + /* Select the buffer which matches with given pos */ + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if( (pos >= apContext->buffer[i].filepos) + && (pos < apContext->buffer[i].filepos + apContext->buffer[i].size) + && (apContext->buffer[i].filepos != M4OSA_EOF) ) + { + M4OSA_TRACE3_1("BufferMatch returns i = %d", i); + return i; + } + } + + M4OSA_TRACE3_1("BufferMatch returns N O N E !!!", i); + return M4OSA_CACHEBUFFER_NONE; +} + + +/* provides the buffer corresponding to a position pos +and with pos inside its maximum capacity +else returns CACHE_BUFFER_NONE*/ +/**************************************************************/ +M4OSA_Int8 M4OSA_FileCache_BufferMatchToWrite(M4OSA_FileCache_Context* apContext, + M4OSA_FilePosition pos) +/**************************************************************/ +{ + M4OSA_Int8 i; + + /* Select the buffer which matches with given pos */ + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if( (pos >= apContext->buffer[i].filepos) + && (pos < apContext->buffer[i].filepos + M4OSA_CACHEBUFFER_SIZE) + && (apContext->buffer[i].filepos != M4OSA_EOF) ) + { + M4OSA_TRACE3_1("BufferMatch returns i = %d", i); + return i; + } + } + + M4OSA_TRACE3_1("BufferMatch returns N O N E !!!", i); + return M4OSA_CACHEBUFFER_NONE; +} + +/* chooses a buffer by overwriting an existing one and returns i */ +/**************************************************************/ +M4OSA_Int8 M4OSA_FileCache_BufferSelectForWrite(M4OSA_FileCache_Context* apContext) +/**************************************************************/ +{ + M4OSA_Int8 i; + M4OSA_UInt8 selected = 0; + M4OSA_UInt32 j, toSort; + M4OSA_FilePosition bufPos[M4OSA_CACHEBUFFER_NB]; + M4OSA_ERR err; + + // update nbFillSinceLastAcess field + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + apContext->buffer[i].nbFillSinceLastAcess ++; + } +#ifdef NO_STRATEGY + goto end_selection; +#endif + + /*********************************************/ + /* 1/ if there is still a new buffer, use it */ + + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if(apContext->buffer[i].state == M4OSA_kInitialized) + { + selected = i; + goto end_selection; + } + } + + /*********************************************/ + /* 2/ Choose a filled and copied buffer */ + + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if( ((apContext->buffer[i].state & M4OSA_kFilled) == M4OSA_kFilled) + && ((apContext->buffer[i].state & M4OSA_kCopied) == M4OSA_kCopied) + && ((apContext->buffer[i].state & M4OSA_kModified) != M4OSA_kModified) /* bug fix modified */ + ) + { + selected = i; + goto end_selection; + } + } + + /****************************************************************/ + /* 3/ Choose a modified buffer with filepos>threshold and min */ + i=0; + + /* sort the buffers by filepos and choose the min and not < threshold*/ + for(j=0; j<M4OSA_CACHEBUFFER_NB; j++) + { + if ( + ((apContext->buffer[j].state & M4OSA_kModified) == M4OSA_kModified) + && (apContext->buffer[j].filepos > -1) /* not EOF */ + ) + { + bufPos[i] = apContext->buffer[j].filepos; + i++; + } + } + + toSort = i; + if (toSort == 0 ) + { + selected = 0; + goto end_selection; + } + else if (toSort ==1 ) + { + goto skip_sort; + } + else + { + M4OSA_FileCache_QS_quickSort(bufPos, toSort); + } + +skip_sort: + /* take the smallest filepos */ + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if (apContext->buffer[i].filepos == bufPos[0]) + { + selected = i; + goto end_selection; + } + } + +end_selection: + if (apContext->buffer[selected].filepos > apContext->fileSize ) + { + /* in case it selects a modified buffer outside real file size, + in that case, flush all buffers before this one + unless there will be a seek outside filesize*/ + M4OSA_FileCache_BuffersFlushUntil(apContext, selected); + } + else if ((apContext->buffer[selected].state & M4OSA_kModified) == M4OSA_kModified ) + { + /* in case it selects a modified buffer inside filesize, simply flush it*/ + err = M4OSA_FileCache_BufferFlush(apContext, selected); + if (M4NO_ERROR!= err) + { + return M4OSA_CACHEBUFFER_NONE; + } + } + +#ifdef NO_STRATEGY + /* selected stays 0 */ + err = M4OSA_FileCache_BuffersFlushUntil(apContext, M4OSA_CACHEBUFFER_ALL); + if (M4NO_ERROR!= err) + { + return M4OSA_FILE_CACHE_BUFFER_NONE; + } +#endif + + M4OSA_TRACE3_1("---------- BufferSelect returns i = %d", selected); + return selected; +} + + +/* chooses a buffer by overwriting an existing one and returns i */ +/**************************************************************/ +M4OSA_Int8 M4OSA_FileCache_BufferSelectWithTime(M4OSA_FileCache_Context* apContext) +/**************************************************************/ +{ + M4OSA_Int8 i; + M4OSA_UInt8 selected = 0; + M4OSA_UInt32 j, toSort; + M4OSA_Time bufTime[M4OSA_CACHEBUFFER_NB]; + M4OSA_ERR err; + + /*********************************************/ + /* 1/ if there is still a new buffer, use it */ + + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if(apContext->buffer[i].state == M4OSA_kInitialized) + { + selected = i; + goto end_selection; + } + } + + i=0; + /* sort all buffers with order of timeAccessed */ + for(j=0; j<M4OSA_CACHEBUFFER_NB; j++) + { + bufTime[i] = apContext->buffer[j].timeAccessed; + i++; + } + + toSort = i; + if (toSort == 0 ) + { + selected = 0; + goto end_selection; + } + else if (toSort ==1 ) + { + goto skip_sort; + } + else + { + M4OSA_FileCache_QS_quickSort64(bufTime, toSort); + } + +skip_sort: + /* take the smallest timeAccessed */ + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if (apContext->buffer[i].timeAccessed == bufTime[0]) + { + selected = i; + goto end_selection; + } + } + +end_selection: + if (apContext->buffer[selected].filepos > apContext->fileSize ) + { + /* in case it selects a modified buffer outside real file size, + in that case, flush all buffers before this one + unless there will be a seek outside filesize*/ + M4OSA_FileCache_BuffersFlushUntil(apContext, selected); + } + else if ((apContext->buffer[selected].state & M4OSA_kModified) == M4OSA_kModified ) + { + /* in case it selects a modified buffer inside filesize, simply flush it*/ + err = M4OSA_FileCache_BufferFlush(apContext, selected); + if (M4NO_ERROR!= err) + { + return M4OSA_CACHEBUFFER_NONE; + } + } + M4OSA_TRACE3_1("---------- BufferSelect returns i = %d", selected); + return selected; +} + +/* chooses a buffer by overwriting an existing one and returns i */ +/**************************************************************/ +M4OSA_Int8 M4OSA_FileCache_BufferSelectWithPos(M4OSA_FileCache_Context* apContext) +/**************************************************************/ +{ + M4OSA_Int8 i; + M4OSA_UInt8 selected = 0, j; + M4OSA_ERR err; + M4OSA_FilePosition minPos; + + /*********************************************/ + /* 1/ if there is still a new buffer, use it */ + + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if(apContext->buffer[i].state == M4OSA_kInitialized) + { + selected = i; + goto end_selection; + } + } + + minPos = apContext->buffer[0].filepos; + selected = 0; + for(j=1; j<M4OSA_CACHEBUFFER_NB; j++) + { + if (apContext->buffer[j].filepos < minPos) + { + minPos = apContext->buffer[j].filepos; + selected = j; + } + } + +end_selection: + if (apContext->buffer[selected].filepos > apContext->fileSize ) + { + /* in case it selects a modified buffer outside real file size, + in that case, flush all buffers before this one + unless there will be a seek outside filesize*/ + M4OSA_TRACE3_2("BufferSelectWithPos selected buffer is ouside file b.filepos=%d > fileSize=%d", + apContext->buffer[selected].filepos, + apContext->fileSize ); + M4OSA_FileCache_BuffersFlushUntil(apContext, selected); + } + else if ((apContext->buffer[selected].state & M4OSA_kModified) == M4OSA_kModified ) + { + /* in case it selects a modified buffer inside filesize, simply flush it*/ + err = M4OSA_FileCache_BufferFlush(apContext, selected); + if (M4NO_ERROR!= err) + { + return M4OSA_CACHEBUFFER_NONE; + } + } + M4OSA_TRACE3_1("---------- BufferSelectWithPos returns i = %d", selected); + return selected; +} + + +/* chooses a buffer by overwriting an existing one and returns i */ +/**************************************************************/ +M4OSA_Int8 M4OSA_FileCache_BufferSelectWithSpace(M4OSA_FileCache_Context* apContext) +/**************************************************************/ +{ + M4OSA_Int8 i; + M4OSA_UInt8 selected = 0; + M4OSA_UInt32 j, toSort; + M4OSA_FilePosition bufStat[M4OSA_CACHEBUFFER_NB]; + M4OSA_ERR err; + + /*********************************************/ + /* 1/ if there is still a new buffer, use it */ + + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if(apContext->buffer[i].state == M4OSA_kInitialized) + { + selected = i; + goto end_selection; + } + } + + i=0; + /* sort all buffers with order of nbAccessed */ + for(j=0; j<M4OSA_CACHEBUFFER_NB; j++) + { + bufStat[i] = apContext->buffer[j].nbAccessed + apContext->buffer[j].timeAccessed*2; /* try hybrid */ + i++; + } + + toSort = i; + if (toSort == 0 ) + { + selected = 0; + goto end_selection; + } + else if (toSort ==1 ) + { + goto skip_sort; + } + else + { + M4OSA_FileCache_QS_quickSort(bufStat, toSort); + } + +skip_sort: + /* take the smallest nbAccessed */ + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if ((M4OSA_Int64) apContext->buffer[i].nbAccessed + apContext->buffer[i].timeAccessed*2 == bufStat[0]) /* hybrid */ + { + selected = i; + goto end_selection; + } + } + +end_selection: + if (apContext->buffer[selected].filepos > apContext->fileSize ) + { + /* in case it selects a modified buffer outside real file size, + in that case, flush all buffers before this one + unless there will be a seek outside filesize*/ + M4OSA_FileCache_BuffersFlushUntil(apContext, selected); + } + else if ((apContext->buffer[selected].state & M4OSA_kModified) == M4OSA_kModified ) + { + /* in case it selects a modified buffer inside filesize, simply flush it*/ + err = M4OSA_FileCache_BufferFlush(apContext, selected); + if (M4NO_ERROR!= err) + { + return M4OSA_CACHEBUFFER_NONE; + } + } + M4OSA_TRACE3_1("---------- BufferSelect returns i = %d", selected); + return selected; +} + + +/**************************************************************/ +M4OSA_Int8 M4OSA_FileCache_BufferSelectForRead(M4OSA_FileCache_Context* apContext) +/**************************************************************/ +{ + M4OSA_Int8 i,j, selected; + M4OSA_FilePosition min_amount,max_amount; + M4OSA_Int8 min_i,max_count; + M4OSA_ERR err; + + /* update nbFillSinceLastAcess field */ + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + apContext->buffer[i].nbFillSinceLastAcess ++; + } + + /**************************************************/ + /* Plan A/ if there is still a new buffer, use it */ + + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if(apContext->buffer[i].state == M4OSA_kInitialized) + { + selected = i; + goto end_selection; + } + } + + max_count = M4OSA_CACHEBUFFER_NB; + max_amount = MAX_FILLS_SINCE_LAST_ACCESS; + + /* Plan B : Scan for dead buffer */ + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + if(apContext->buffer[i].nbFillSinceLastAcess >= (M4OSA_UInt32) max_amount) + { + max_amount = apContext->buffer[i].nbFillSinceLastAcess; + max_count = i; + } + } + if(max_count<M4OSA_CACHEBUFFER_NB) + { + M4OSA_TRACE3_2("DEAD BUFFER: %d, %d",max_count,apContext->buffer[max_count].nbFillSinceLastAcess); + selected = max_count; + goto end_selection; + } + + min_i = 0; + min_amount = M4OSA_CACHEBUFFER_NB; + + /* Select the buffer which is the most "empty" */ + for(i=0; i<M4OSA_CACHEBUFFER_NB; i++) + { + j = i % M4OSA_CACHEBUFFER_NB; + + if(apContext->buffer[j].remain < min_amount) + { + min_amount = apContext->buffer[j].remain; + min_i = j; + } + } + selected = min_i; + +end_selection: + if (apContext->buffer[selected].filepos > apContext->fileSize ) + { + /* in case it selects a modified buffer outside real file size, + in that case, flush all buffers before this one + unless there will be a seek outside filesize*/ + M4OSA_FileCache_BuffersFlushUntil(apContext, selected); + } + else if ((apContext->buffer[selected].state & M4OSA_kModified) == M4OSA_kModified ) + { + /* in case it selects a modified buffer inside filesize, simply flush it*/ + err = M4OSA_FileCache_BufferFlush(apContext, selected); + if (M4NO_ERROR!= err) + { + return M4OSA_CACHEBUFFER_NONE; + } + } + + return selected; +} + + +/**************************************************************/ +M4OSA_ERR M4OSA_FileCache_CalculateSize(M4OSA_FileCache_Context* apContext) +/**************************************************************/ +{ + M4OSA_ERR err = M4NO_ERROR; + M4OSA_Int32 ret_val; + M4OSA_UInt16 errReturned; + + /* go to the end of file*/ + ret_val = apContext->FS->pFctPtr_Seek(apContext->aFileDesc, 0, + M4OSA_kFileSeekEnd, + &errReturned); + + if (ret_val != 0) + { + apContext->readFilePos = M4OSA_EOF; + err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errReturned); + M4OSA_TRACE2_1("M4OSA_FileCache_CalculateSize ERR = 0x%x", err); + } + else + { + /* Retrieve size of the file */ + apContext->fileSize = apContext->FS->pFctPtr_Tell(apContext->aFileDesc, + &errReturned); + apContext->readFilePos = apContext->fileSize; + } + + return err; +} + +/* _____________________________________________________________ */ +/*| | */ +/*| OSAL filesystem functions dependent on Platform FileSystem | */ +/*|_____________________________________________________________| */ + +/** + ************************************************************************ + * @brief Opens a file + * @note + * @param pFileDescriptor : IN url of the file + * FileModeAccess : IN access mode for opening the file + * errno_ffs : OUT internal error returned by the filesystem + * @return pC : internal context + ************************************************************************ +*/ +M4OSA_Void* M4OSA_FileSystem_FFS_Open_cache( M4OSA_Void* pFileDescriptor, + M4OSA_UInt32 FileModeAccess, + M4OSA_UInt16* errno_ffs ) +{ + + M4OSA_FileSystem_FFS_t_cache *pC = M4OSA_NULL; + FILE* fp; + + M4OSA_Char mode[4] = ""; + M4OSA_Char* pReadString = (M4OSA_Char*)"r"; + M4OSA_Char* pWriteString = (M4OSA_Char*)"w"; + M4OSA_Char* pAppendString = (M4OSA_Char*)"a"; + M4OSA_Char* pBinaryString = (M4OSA_Char*)"b"; + M4OSA_Char* pPlusString = (M4OSA_Char*)"+"; + + fp = M4OSA_NULL; + *errno_ffs = 0; + + M4OSA_TRACE3_0("M4OSA_FileSystem_FFS_Open_cache : Open **** \n"); + + /************************/ + /* Verify access mode */ + /************************/ + + /* + All possible file accesses: + + r : Read only, file must exist + + w : Write only. If the file exists, it is overwritten. If it does not exist, it is created. + + a : write at end of file (append). If the file exists, it is extended. If the file does not exist, it is created. + + r+ : update (i.e. read and write). The file must exist. It is not possible to do a read after a write (or a write after a read) + unless we reposition the file pointer. + + w+ : creation, to update. If the file exists, it is overwritten. If the files does not exist, it is created. + a+ : extension and update. If the file does not exist, it is created. If the file exists, the file pointer is put at end of file. + + All possible cases for fileModeAccess parameter: + + Write(2) w + WriteRead(3) r+ // r+b Used by MM + WriteReadCreate(11) w+ // w+b Used by MM + WriteReadAppend(7) a+ + WriteCreate(10) w + WriteAppend(12) a + Read r // rb Used by MM + Error + */ + + + if ((FileModeAccess & M4OSA_kFileWrite) && (FileModeAccess & M4OSA_kFileRead) && (FileModeAccess & M4OSA_kFileCreate)) /* Used by MM */ + { + /** "w+" */ + M4OSA_chrNCat(mode, pWriteString, 1); + M4OSA_chrNCat(mode, pPlusString, 1); + } + else if ((FileModeAccess & M4OSA_kFileWrite) && (FileModeAccess & M4OSA_kFileRead) && (FileModeAccess & M4OSA_kFileAppend)) + { + /** "a+" */ + M4OSA_chrNCat(mode, pAppendString, 1); + M4OSA_chrNCat(mode, pPlusString, 1); + } + else if ((FileModeAccess & M4OSA_kFileWrite) && (FileModeAccess & M4OSA_kFileRead)) /* Used by MM */ + { + /** "r+" */ + M4OSA_chrNCat(mode, pReadString, 1); + M4OSA_chrNCat(mode, pPlusString, 1); + } + else if ((FileModeAccess & M4OSA_kFileWrite) && (FileModeAccess & M4OSA_kFileCreate)) + { + /** "w" */ + M4OSA_chrNCat(mode, pWriteString, 1); + } + else if ((FileModeAccess & M4OSA_kFileWrite) && (FileModeAccess & M4OSA_kFileAppend)) + { + /** "a" */ + M4OSA_chrNCat(mode, pAppendString, 1); + } + else if (FileModeAccess & M4OSA_kFileRead) + { + /** "r" */ + M4OSA_chrNCat(mode, pReadString, 1); + } + else if (FileModeAccess & M4OSA_kFileWrite) + { + /** "w" */ + M4OSA_chrNCat(mode, pWriteString, 1); + } + else + { + M4OSA_TRACE1_1("M4OSA_FileSystem_FFS_Open_cache : invalid FileModeAccess = %x", FileModeAccess); + *errno_ffs = (M4OSA_UInt16)M4ERR_FILE_BAD_MODE_ACCESS; + } + + /* add the b */ + M4OSA_chrNCat(mode, pBinaryString, 1); + + fp = fopen((const char *) pFileDescriptor, (const char *)mode); /* Open in rb or in r+b*/ + if( fp != NULL ) + { + pC = (M4OSA_FileSystem_FFS_t_cache *) M4OSA_malloc(sizeof * pC, M4OSA_FILE_READER, (M4OSA_Char*)"M4OSA_FileSystem_FFS_Open_cache"); + + if (pC == M4OSA_NULL) return M4OSA_NULL; /*error occured => return NULL pointer*/ + + pC->FileDesc = fp; + } + else + { + switch(errno) + { + case ENOENT: + M4OSA_DEBUG(M4ERR_FILE_NOT_FOUND, "M4OSA_fileReadOpen: No such file or directory"); + *errno_ffs=(M4OSA_UInt16)M4ERR_FILE_NOT_FOUND; + break; + + case EACCES: + M4OSA_DEBUG(M4ERR_FILE_LOCKED, "M4OSA_fileReadOpen: Permission denied"); + *errno_ffs=(M4OSA_UInt16)M4ERR_FILE_LOCKED; + break; + + case EINVAL: + M4OSA_DEBUG(M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileReadOpen: Invalid Argument"); + *errno_ffs=(M4OSA_UInt16)M4ERR_FILE_BAD_MODE_ACCESS; + break; + + case EMFILE: + case ENOSPC: + case ENOMEM: + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileReadOpen: Too many open files"); + *errno_ffs=(M4OSA_UInt16)M4ERR_ALLOC; + break; + + default: + M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_fileReadOpen"); + *errno_ffs=(M4OSA_UInt16)M4ERR_NOT_IMPLEMENTED; + + } /* end switch */ + } /* end else */ + + return (M4OSA_Void*)pC; +} + +/** + ************************************************************************ + * @brief Reads data from file + * @note + * @param pContext : IN internal context + * data : IN buffer for reading data + * size : IN amount of bytes to read + * errno_ffs : OUT internal error returned by the filesystem + * @return ret : effective amount of bytes read / -1 if an error occurs + ************************************************************************ +*/ +M4OSA_FilePosition M4OSA_FileSystem_FFS_Read_cache( M4OSA_Void* pContext, + M4OSA_UInt8* data, + M4OSA_FilePosition size, + M4OSA_UInt16* errno_ffs ) +{ + M4OSA_FileSystem_FFS_t_cache *pC = (M4OSA_FileSystem_FFS_t_cache *)pContext; + M4OSA_Int32 res; + + M4OSA_TRACE2_1("M4OSA_FileSystem_FFS_Read size = %ld", size); + + res = -1; + + res = fread(data,sizeof(M4OSA_Char), size, pC->FileDesc); + if( -1 < res ) + { + *errno_ffs = M4NO_ERROR; + } + else + { + *errno_ffs = errno; + } + + return (M4OSA_FilePosition)res; +} + + + +/** + ************************************************************************ + * @brief Writes data to file + * @note + * @param pContext : IN internal context + * data : IN buffer with data to write + * size : IN amount of bytes to read + * errno_ffs : OUT internal error returned by the filesystem + * @return ret : effective amount of bytes read / an error code if an error occurs + ************************************************************************ +*/ +M4OSA_FilePosition M4OSA_FileSystem_FFS_Write_cache( M4OSA_Void* pContext, + M4OSA_UInt8* data, + M4OSA_FilePosition size, + M4OSA_UInt16* errno_ffs ) +{ + M4OSA_FileSystem_FFS_t_cache *pC = (M4OSA_FileSystem_FFS_t_cache *)pContext; + M4OSA_Int32 res; + + M4OSA_TRACE2_1("M4OSA_FileSystem_FFS_Write size = %ld", size); + + res = 0; + + res = fwrite(data,sizeof(M4OSA_Char), size, pC->FileDesc); + if( -1 < res ) + { + *errno_ffs = M4NO_ERROR; + } + else + { + *errno_ffs = errno; + M4OSA_TRACE1_1("M4OSA_FileSystem_FFS_Write error", *errno_ffs); + } + + fflush(pC->FileDesc); + + return (M4OSA_FilePosition)res; +} + +/** + ************************************************************************ + * @brief Seeks at given position in a file + * @note + * @param pContext : IN internal context + * pos : IN amount of bytes for the move + * mode : IN kind of seek to perform + * errno_ffs : OUT internal error returned by the filesystem + * @return ret : 0 on success / any other value if an error occurs + ************************************************************************ +*/ +M4OSA_Int32 M4OSA_FileSystem_FFS_Seek_cache( M4OSA_Void* pContext, + M4OSA_FilePosition pos, + M4OSA_FileSeekAccessMode mode, + M4OSA_UInt16* errno_ffs ) +{ + M4OSA_FileSystem_FFS_t_cache *pC = (M4OSA_FileSystem_FFS_t_cache *)pContext; + + M4OSA_TRACE2_2("M4OSA_FileSystem_FFS_Seek pos = %ld mode = %d", pos, mode); + + switch(mode) + { + case M4OSA_kFileSeekBeginning : + *errno_ffs = fseek(pC->FileDesc, pos, SEEK_SET); + break; + + case M4OSA_kFileSeekCurrent : + *errno_ffs= fseek(pC->FileDesc, pos, SEEK_CUR); + break; + + case M4OSA_kFileSeekEnd : + *errno_ffs = fseek(pC->FileDesc, pos, SEEK_END); + break; + } + + return *errno_ffs; + +} + +/** + ************************************************************************ + * @brief Tells the position of the file pointer + * @note + * @param pContext : IN internal context + * errno_ffs : OUT internal error returned by the filesystem + * @return ret : position of the file pointer/ -1 if an error occurs + ************************************************************************ +*/ +M4OSA_FilePosition M4OSA_FileSystem_FFS_Tell_cache( M4OSA_Void* pContext, + M4OSA_UInt16* errno_ffs ) +{ + M4OSA_FileSystem_FFS_t_cache *pC = (M4OSA_FileSystem_FFS_t_cache *)pContext; + M4OSA_FilePosition pos; + + pos = ftell(pC->FileDesc); + + *errno_ffs = 0; + + return pos; +} + +/** + ************************************************************************ + * @brief Closes the file + * @note + * @param pContext : IN internal context + * errno_ffs : OUT internal error returned by the filesystem + * @return ret : 0 on success / any other value if an error occurs + ************************************************************************ +*/ +M4OSA_Int32 M4OSA_FileSystem_FFS_Close_cache( M4OSA_Void* pContext, + M4OSA_UInt16* errno_ffs ) +{ + M4OSA_FileSystem_FFS_t_cache *pC = (M4OSA_FileSystem_FFS_t_cache *)pContext; + + *errno_ffs = fclose(pC->FileDesc); + + return *errno_ffs; +} + +/* __________________________________________________________ */ +/*| |*/ +/*| OSAL fileCache |*/ +/*|__________________________________________________________|*/ + +/**************************************************************/ +M4OSA_ERR M4OSA_fileOpen_cache(M4OSA_Context* pContext, + M4OSA_Void* pFileDescriptor, + M4OSA_UInt32 FileModeAccess) +/**************************************************************/ +{ + M4OSA_FileSystem_FctPtr_cache *FS; + + /* Allocate memory for the File System interface */ + FS = (M4OSA_FileSystem_FctPtr_cache *)M4OSA_malloc(sizeof * FS, + M4OSA_FILE_READER,(M4OSA_Char*)"M4OSA_FileSystem_FctPtr_cache"); + + if(M4OSA_NULL == FS) + return M4ERR_ALLOC; + + FS->pFctPtr_Open = M4OSA_FileSystem_FFS_Open_cache; + FS->pFctPtr_Read = M4OSA_FileSystem_FFS_Read_cache; + FS->pFctPtr_Write = M4OSA_FileSystem_FFS_Write_cache; + FS->pFctPtr_Seek = M4OSA_FileSystem_FFS_Seek_cache; + FS->pFctPtr_Tell = M4OSA_FileSystem_FFS_Tell_cache; + FS->pFctPtr_Close = M4OSA_FileSystem_FFS_Close_cache; + + return M4OSA_fileOpen_cache_internal(pContext, pFileDescriptor, + FileModeAccess, FS); +} + +/** +****************************************************************************** +* @brief This method opens the provided fileDescriptor and returns its context. +* @param pContext: (OUT) File Cache 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 +* @return M4ERR_FILE_NOT_FOUND The file can not be opened. +****************************************************************************** +*/ +M4OSA_ERR M4OSA_fileOpen_cache_internal(M4OSA_Context* pContext, + M4OSA_Void* pFileDescriptor, + M4OSA_UInt32 FileModeAccess, + M4OSA_FileSystem_FctPtr_cache *FS) +{ + M4OSA_FileCache_Context* apContext = M4OSA_NULL; + + M4OSA_ERR err = M4NO_ERROR; + M4OSA_Void* aFileDesc = M4OSA_NULL; + M4OSA_Bool buffers_allocated = M4OSA_FALSE; + M4OSA_UInt16 errReturned = 0; + M4OSA_Int32 len,name_len; + M4OSA_Char* pCharFileDesc = (M4OSA_Char*)pFileDescriptor; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_Time time1 = 0; + M4OSA_Time time2 = 0; +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + M4OSA_TRACE2_2("M4OSA_fileOpen_cache fd = %s mode = %d", pFileDescriptor, + FileModeAccess); + + /* Check input parameters */ + M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pContext); + M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pFileDescriptor); + M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, FS); + + *pContext = M4OSA_NULL; + + /* Allocate memory for the File reader context. */ + apContext = (M4OSA_FileCache_Context *)M4OSA_malloc(sizeof(M4OSA_FileCache_Context), + M4OSA_FILE_READER, (M4OSA_Char*)"M4OSA_FileCache_Context"); + + M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_ALLOC, apContext); + + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_FileCache_initTimeMeas(apContext); + M4OSA_clockGetTime(&time1,1000); +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + /* Set filesystem interface */ + apContext->FS = FS; + + if (M4OSA_kFileWrite == FileModeAccess) + { + FileModeAccess |= M4OSA_kFileWrite | M4OSA_kFileCreate; /* for VA in case of open with only Write flag, we add the Create */ + } + + /* For VA and VES, we need to add access in read, to write the moov for example */ + /* Add the flag Read in all cases, because Osal File Cache uses read at the same time */ + FileModeAccess |= M4OSA_kFileRead; + + aFileDesc = apContext->FS->pFctPtr_Open(pFileDescriptor, FileModeAccess, + &errReturned); + + if (aFileDesc != M4OSA_NULL) + { + apContext->IsOpened = M4OSA_TRUE; + } + else + { + /* converts the error to PSW format*/ + err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errReturned); + M4OSA_TRACE1_2("M4OSA_fileOpen_cache error 0x%x for fd = %s", err, + pFileDescriptor); + apContext->IsOpened = M4OSA_FALSE; + + /*free the context and associated FS pointers*/ + if (M4OSA_NULL != apContext) /*should never be null*/ + { + if (M4OSA_NULL != apContext->FS) /*should never be null*/ + { + M4OSA_free((M4OSA_MemAddr32)apContext->FS); + } + + M4OSA_free((M4OSA_MemAddr32)apContext); + apContext = M4OSA_NULL; + } + + if (M4NO_ERROR != err) goto cleanup; + } + + /* Allocate buffers */ + err = M4OSA_FileCache_BuffersInit(apContext); + buffers_allocated = M4OSA_TRUE; + + if (M4NO_ERROR != err) goto cleanup; + + /* Initialize parameters */ + apContext->fileSize = 0; + apContext->virtualFileSize = 0; + apContext->absolutePos = 0; + apContext->absoluteWritePos = 0; + + + apContext->readFilePos = 0; + + /* Retrieve the File Descriptor*/ + apContext->aFileDesc = aFileDesc; + + /* Retrieve the File mode Access */ + apContext->FileAttribute.modeAccess = (M4OSA_FileModeAccess)FileModeAccess; + + apContext->chrono = 0; + +#ifdef FILECACHE_STATS + apContext->nbReadCache = 0; + apContext->nbWriteCache = 0; + + apContext->nbReadFFS = 0; + apContext->nbWriteFFS = 0; +#endif + + /*Retrieve the File reader context */ + *pContext= (M4OSA_Context)apContext; + + /* Compute file size */ + err = M4OSA_FileCache_CalculateSize(apContext); + + if (M4NO_ERROR != err) goto cleanup; + + apContext->virtualFileSize = apContext->fileSize; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_clockGetTime(&time2,1000); + if (time2>time1) + apContext->gMyPerfFileTab[fileOpentime] += time2-time1; +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + M4OSA_mutexOpen(&(apContext->m_mutex)); + + /* filename extraction, just for traces */ + M4OSA_memset(apContext->m_filename, 256, 0); + len=( M4OSA_chrLength(pCharFileDesc) )+1; + for( --len ; (len >= 0 && pCharFileDesc[len] != '\\' && pCharFileDesc[len] != '/') ; len-- ); + name_len=M4OSA_chrLength( &pCharFileDesc[len+1] ); + err=M4OSA_chrNCopy(apContext->m_filename, &pCharFileDesc[len+1], name_len); + + M4OSA_TRACE2_2("M4OSA_fileOpen_cache of %s has pC = 0x%x", apContext->m_filename, apContext); + + return M4NO_ERROR; + +cleanup: + + /* free context */ + if (M4OSA_NULL != apContext) + { + if(buffers_allocated == M4OSA_TRUE) + { + M4OSA_FileCache_BuffersFree(apContext); + } + + if (M4OSA_NULL != apContext) + { + M4OSA_free((M4OSA_MemAddr32)apContext); + apContext = M4OSA_NULL; + } + *pContext = M4OSA_NULL; + } + + 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_cache(M4OSA_Context pContext,M4OSA_MemAddr8 pData, + M4OSA_UInt32* pSize) +{ + M4OSA_FileCache_Context* apContext = (M4OSA_FileCache_Context*) pContext; + + M4OSA_ERR err; + M4OSA_FilePosition aSize; + M4OSA_FilePosition copiedSize; + M4OSA_Int8 selected_buffer, current_buffer; + M4OSA_Int32 castedSize; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_Time time1 = 0; + M4OSA_Time time2 = 0; + + M4OSA_clockGetTime(&time1,1000); +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + M4OSA_TRACE2_3("M4OSA_fileReadData_cache of %s size=%d at pos=%d ", + apContext->m_filename, *pSize, apContext->absolutePos); + + /* 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; + } + +LOCK + +/* 20080125 Start : if *pSize is too high, adjust it to the size left in the file. MI-958*/ + castedSize = * pSize; + if (castedSize < 0) + { + copiedSize = 0; + err = M4WAR_NO_MORE_AU; +#ifdef M4OSA_FILECACHE_MM + err = M4WAR_NO_DATA_YET; /* no_data_yet for MM */ +#endif + goto cleanup; + } +/* 20080125 End : if *pSize is too high, adjust it to the size left in the file. MI-958*/ + + /* Prevent reading beyond EOF */ + if((*pSize > 0) && (apContext->absolutePos >= apContext->virtualFileSize)) /* virtual FSize*/ + { + copiedSize = 0; + err = M4WAR_NO_MORE_AU; /* for VA and VPS */ +#ifdef M4OSA_FILECACHE_MM + err = M4WAR_NO_DATA_YET; /* no_data_yet for MM */ +#endif + goto cleanup; + } + +/* 20080125 Start : if *pSize is too high, adjust it to the size left in the file. MI-958*/ + if (*pSize > (M4OSA_UInt32)(apContext->virtualFileSize - apContext->absolutePos)) + { + M4OSA_TRACE1_0("M4OSA_fileReadData_cache : Attempted to read beyond file size, adjusted size"); + *pSize = apContext->virtualFileSize - apContext->absolutePos; + } +/* 20080125 End : if *pSize is too high, adjust it to the size left in the file. MI-958*/ + + /* 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_FileCache_BufferMatchToRead(apContext, + apContext->absolutePos); + + if(selected_buffer == M4OSA_CACHEBUFFER_NONE) + { + +#if defined(BUFFER_SELECT_INITIAL) + selected_buffer = M4OSA_FileCache_BufferSelectForRead(apContext); +#elif defined(BUFFER_SELECT_WITH_TIME) + selected_buffer = M4OSA_FileCache_BufferSelectWithTime(apContext); +#elif defined(BUFFER_SELECT_WITH_SPACE) + selected_buffer = M4OSA_FileCache_BufferSelectWithSpace(apContext); +#elif defined(BUFFER_SELECT_WITH_POS) + selected_buffer = M4OSA_FileCache_BufferSelectWithPos(apContext); +#endif + + if (M4OSA_CACHEBUFFER_NONE == selected_buffer) + { + err = M4ERR_BAD_CONTEXT; /* temporary error code */ + goto cleanup; + } + + err = M4OSA_FileCache_BufferFill(apContext, selected_buffer, + apContext->absolutePos); + } +#ifdef FILECACHE_STATS + else + { + /* bufferMatch has success in read */ + apContext->nbReadCache++; + } +#endif /* FILECACHE_STATS */ + + if(err != M4NO_ERROR) + { + if((err == M4WAR_NO_DATA_YET) && (*pSize <= (M4OSA_UInt32)apContext->buffer[selected_buffer].size)) + err = M4NO_ERROR; + else goto cleanup; + } + + M4OSA_TRACE3_3("readData size = %d buffer = %d pos = %d", + *pSize, selected_buffer, apContext->absolutePos); + + /* Copy buffer into pData */ + while(((M4OSA_UInt32)copiedSize < *pSize) && (err == M4NO_ERROR)) + { + aSize = M4OSA_FileCache_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_FileCache_BufferMatchToRead(apContext, + apContext->absolutePos+copiedSize); + + if(selected_buffer == M4OSA_CACHEBUFFER_NONE) + { +#if defined(BUFFER_SELECT_INITIAL) + selected_buffer = M4OSA_FileCache_BufferSelectForRead(apContext); +#elif defined(BUFFER_SELECT_WITH_TIME) + selected_buffer = M4OSA_FileCache_BufferSelectWithTime(apContext); +#elif defined(BUFFER_SELECT_WITH_SPACE) + selected_buffer = M4OSA_FileCache_BufferSelectWithSpace(apContext); +#elif defined(BUFFER_SELECT_WITH_POS) + selected_buffer = M4OSA_FileCache_BufferSelectWithPos(apContext); +#endif + + if (M4OSA_CACHEBUFFER_NONE == selected_buffer) + { + err = M4ERR_BAD_CONTEXT; /* temporary error code */ + goto cleanup; + } + + err = M4OSA_FileCache_BufferFill(apContext, selected_buffer, + apContext->absolutePos+copiedSize); + + if(err != M4NO_ERROR) + { + if((err == M4WAR_NO_DATA_YET) && ((*pSize-copiedSize) <= (M4OSA_UInt32)apContext->buffer[selected_buffer].size)) + err = M4NO_ERROR; + else goto cleanup; + } + } +#ifdef FILECACHE_STATS + else + { + /* bufferMatch has success in read */ + apContext->nbReadCache++; + } +#endif /* FILECACHE_STATS */ + + } + } + } + +cleanup : + + /* Update the new position of the pointer */ + apContext->absolutePos = apContext->absolutePos + copiedSize; + +#ifdef M4OSA_FILECACHE_MM + apContext->absoluteWritePos = apContext->absolutePos; +#endif /* M4OSA_FILECACHE_MM */ + + if(err != M4NO_ERROR) + { + M4OSA_TRACE1_3("M4OSA_fileReadData_cache size = %d copied = %d err = 0x%x", + *pSize, copiedSize, err); + } + + /* Effective copied size must be returned */ + *pSize = copiedSize; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_clockGetTime(&time2,1000); + if (time2>time1) + apContext->gMyPerfFileTab[fileReadDatatime] += time2-time1; +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + +UNLOCK + + /* Read is done */ + return err; +} + + +/** + ************************************************************************ + * @brief This function writes the 'size' bytes stored at 'data' memory + * in the file selected by its context. + * @note The caller is responsible for allocating/de-allocating the + * memory for 'data' parameter. + * @note Moreover the data pointer must be allocated to store at least + * 'size' bytes. + * @param pContext: (IN/OUT) Context of the core file reader + * @param pData: (IN) Data pointer of the write data + * @param size: (IN) Size of the data to write (in bytes) + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + ************************************************************************/ + +M4OSA_ERR M4OSA_fileWriteData_cache(M4OSA_Context pContext,M4OSA_MemAddr8 pData, + M4OSA_UInt32 size) +{ + M4OSA_FileCache_Context* apContext = (M4OSA_FileCache_Context*) pContext; + + M4OSA_ERR err; + M4OSA_FilePosition aSize; + M4OSA_FilePosition copiedSize; + M4OSA_Int8 selected_buffer, current_buffer; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_Time time1 = 0; + M4OSA_Time time2 = 0; + + M4OSA_clockGetTime(&time1,1000); +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + M4OSA_TRACE2_3("M4OSA_fileWriteData_cache of %s size=%d at pos=%d ", + apContext->m_filename, size, apContext->absoluteWritePos); + + /* Check input parameters */ + M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_BAD_CONTEXT, apContext); + M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pData); + + + if (apContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; + } + + /*protection*/ + if (apContext->absoluteWritePos > apContext->virtualFileSize) + { + M4OSA_TRACE1_0("M4OSA_fileWriteData_cache ERROR : attempting to write beyond EOF"); + return M4WAR_NO_DATA_YET; + } + +LOCK + + /* Check if data has been read into a buffer */ + /* If not, we should read that buffer first and then fill it */ + copiedSize = 0; + err = M4NO_ERROR; + + selected_buffer = M4OSA_FileCache_BufferMatchToWrite(apContext, + apContext->absoluteWritePos); + + if(selected_buffer == M4OSA_CACHEBUFFER_NONE) + { +#if defined(BUFFER_SELECT_INITIAL) + selected_buffer = M4OSA_FileCache_BufferSelectForWrite(apContext); +#elif defined(BUFFER_SELECT_WITH_TIME) + selected_buffer = M4OSA_FileCache_BufferSelectWithTime(apContext); +#elif defined(BUFFER_SELECT_WITH_SPACE) + selected_buffer = M4OSA_FileCache_BufferSelectWithSpace(apContext); +#elif defined(BUFFER_SELECT_WITH_POS) + selected_buffer = M4OSA_FileCache_BufferSelectWithPos(apContext); +#endif + + if (M4OSA_CACHEBUFFER_NONE == selected_buffer) + { + M4OSA_TRACE1_1("M4OSA_fileWriteData_cache ERR1 err=0x%x", err); + err = M4ERR_BAD_CONTEXT; /* temporary error code */ + goto cleanup; + } + + if (apContext->absoluteWritePos - M4OSA_CACHEBUFFER_SIZE < apContext->fileSize) /* absolutePos not readfilepo strictly < */ + { + err = M4OSA_FileCache_BufferFill(apContext, selected_buffer, + apContext->absoluteWritePos); + } + else + { + err = M4OSA_FileCache_BufferReinitialize(apContext, selected_buffer, + apContext->absoluteWritePos); + } + + } +#ifdef FILECACHE_STATS + else + { + /* bufferMatch has success in write */ + apContext->nbWriteCache++; + } +#endif /* FILECACHE_STATS */ + + if(err != M4NO_ERROR) + { + if(err == M4WAR_NO_DATA_YET) /* means the buffer is small, it is at EOF, bufferFill didn't fully fill it*/ + err = M4NO_ERROR; + else goto cleanup; + } + + M4OSA_TRACE3_3("writeData size = %d buffer = %d pos = %d", size, + selected_buffer, apContext->absoluteWritePos); + + /* Copy buffer into pData */ + while(((M4OSA_UInt32)copiedSize < size) && (err == M4NO_ERROR)) + { + aSize = M4OSA_FileCache_BufferModifyContent(apContext, selected_buffer, + apContext->absoluteWritePos+copiedSize, + size-copiedSize, pData+copiedSize); + copiedSize += aSize; + + /* update virtualFileSize in case we write at the end */ + if (apContext->absoluteWritePos+copiedSize>apContext->virtualFileSize) + { + apContext->virtualFileSize = apContext->absoluteWritePos+copiedSize; + M4OSA_TRACE3_1("virtualFileSize incremented to %d", apContext->virtualFileSize); + } + + if((M4OSA_UInt32)copiedSize < size) + { + current_buffer = selected_buffer; + selected_buffer = M4OSA_FileCache_BufferMatchToWrite(apContext, + apContext->absoluteWritePos+copiedSize); + + if(selected_buffer == M4OSA_CACHEBUFFER_NONE) + { +#if defined(BUFFER_SELECT_INITIAL) + selected_buffer = M4OSA_FileCache_BufferSelectForWrite(apContext); +#elif defined(BUFFER_SELECT_WITH_TIME) + selected_buffer = M4OSA_FileCache_BufferSelectWithTime(apContext); +#elif defined(BUFFER_SELECT_WITH_SPACE) + selected_buffer = M4OSA_FileCache_BufferSelectWithSpace(apContext); +#elif defined(BUFFER_SELECT_WITH_POS) + selected_buffer = M4OSA_FileCache_BufferSelectWithPos(apContext); +#endif + + if (M4OSA_CACHEBUFFER_NONE == selected_buffer) + { + M4OSA_TRACE1_1("M4OSA_fileWriteData_cache ERR2 err=0x%x", err); + err = M4ERR_BAD_CONTEXT; /* temporary error code */ + goto cleanup; + } + + if (apContext->absoluteWritePos+copiedSize < apContext->fileSize) /* absolutePos not readfilepo strictly < */ + { + err = M4OSA_FileCache_BufferFill(apContext, selected_buffer, + apContext->absoluteWritePos+copiedSize); + } + else + { + err = M4OSA_FileCache_BufferReinitialize(apContext, + selected_buffer, + apContext->absoluteWritePos+copiedSize); + } + + + if(err != M4NO_ERROR) + { + if((err == M4WAR_NO_DATA_YET)) + err = M4NO_ERROR; + else goto cleanup; + } + } +#ifdef FILECACHE_STATS + else /* (selected_buffer == M4OSA_CACHEBUFFER_NONE) */ + { + /* bufferMatch has success in write */ + apContext->nbWriteCache++; + } +#endif /* FILECACHE_STATS */ + + } + + } + +cleanup : + + /* Update the new position of the pointer */ + apContext->absoluteWritePos = apContext->absoluteWritePos + copiedSize; +#ifdef M4OSA_FILECACHE_MM + apContext->absolutePos = apContext->absoluteWritePos; +#endif /* M4OSA_FILECACHE_MM */ + + if(err != M4NO_ERROR) + { + M4OSA_TRACE3_3("M4OSA_fileWriteData_cache size = %d copied = %d err = 0x%x", + size, copiedSize, err); + } + + /* Effective copied size must be returned */ + size = copiedSize; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_clockGetTime(&time2,1000); + if (time2>time1) + apContext->gMyPerfFileTab[fileWriteDatatime] += time2-time1; +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + +UNLOCK + + /* 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_cache( M4OSA_Context pContext, + M4OSA_FileSeekAccessMode SeekMode, + M4OSA_FilePosition* pPosition) +{ + M4OSA_FileCache_Context* apContext = (M4OSA_FileCache_Context*) pContext; + M4OSA_ERR err = M4NO_ERROR; + M4OSA_FilePosition finalPos; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_Time time1 = 0; + M4OSA_Time time2 = 0; + + M4OSA_clockGetTime(&time1,1000); +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + M4OSA_TRACE3_2("M4OSA_fileReadSeek_cache mode = %d pos = %d", 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 */ + } + +LOCK + + /* Go to the desired position */ + switch(SeekMode) + { + case M4OSA_kFileSeekBeginning : + finalPos = *pPosition; + break; + + case M4OSA_kFileSeekEnd : + finalPos = apContext->virtualFileSize + *pPosition; + break; + + case M4OSA_kFileSeekCurrent : + finalPos = apContext->absolutePos + *pPosition; + break; + + default : + UNLOCK + return M4ERR_PARAMETER; /**< Bad SeekAcess mode */ + break; + } + + M4OSA_TRACE2_1("M4OSA_fileReadSeek_cache to absolutePos = %d ", finalPos); + +/* 20080125 Start : Protect against seek outside file. MI-958*/ + if (finalPos <= apContext->virtualFileSize && finalPos>=0) + { + apContext->absolutePos = finalPos; + *pPosition = finalPos; + } + else + { + M4OSA_TRACE1_2("M4OSA_fileReadSeek_cache: attempted to seek at %d whilst filesize=%d", + finalPos, apContext->virtualFileSize); + *pPosition = apContext->absolutePos; /* keep the previous position */ + //err = M4ERR_FILE_INVALID_POSITION; + err = M4NO_ERROR; /* for VA */ + } +/* 20080125 End : Protect against seek outside file. MI-958*/ + +#ifdef M4OSA_FILECACHE_MM + apContext->absoluteWritePos = apContext->absolutePos; +#endif /* M4OSA_FILECACHE_MM */ + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_clockGetTime(&time2,1000); + if (time2>time1) + apContext->gMyPerfFileTab[fileSeektime] += time2-time1; +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + +UNLOCK + + /* Return without error */ + 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_fileWriteSeek_cache( M4OSA_Context pContext, + M4OSA_FileSeekAccessMode SeekMode, + M4OSA_FilePosition* pPosition) +{ + M4OSA_FileCache_Context* apContext = (M4OSA_FileCache_Context*) pContext; + M4OSA_ERR err = M4NO_ERROR; + M4OSA_FilePosition finalPos; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_Time time1 = 0; + M4OSA_Time time2 = 0; + + M4OSA_clockGetTime(&time1,1000); +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + M4OSA_TRACE3_2("M4OSA_fileWriteSeek_cache mode = %d pos = %d", 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 */ + } + +LOCK + + /* Go to the desired position */ + switch(SeekMode) + { + case M4OSA_kFileSeekBeginning : + finalPos = *pPosition; + break; + + case M4OSA_kFileSeekEnd : + finalPos = apContext->virtualFileSize + *pPosition; + break; + + case M4OSA_kFileSeekCurrent : + finalPos = apContext->absoluteWritePos + *pPosition; + break; + + default : + UNLOCK + return M4ERR_PARAMETER; /**< Bad SeekAcess mode */ + break; + } + + M4OSA_TRACE2_1("M4OSA_fileWriteSeek_cache to absoluteWritePos = %d ", finalPos); + +/* 20080125 Start : Protect against seek outside file. MI-958*/ + if (finalPos <= apContext->virtualFileSize && finalPos>=0) + { + apContext->absoluteWritePos = finalPos; + *pPosition = finalPos; + } + else + { + M4OSA_TRACE1_2("M4OSA_fileWriteSeek_cache: attempted to seek at %d whilst filesize=%d ", + finalPos, apContext->virtualFileSize); + *pPosition = apContext->absoluteWritePos; /* keep the previous position */ + //err = M4ERR_FILE_INVALID_POSITION; + err = M4NO_ERROR; /* for VA */ + } +/* 20080125 End : Protect against seek outside file. MI-958*/ + +#ifdef M4OSA_FILECACHE_MM + apContext->absolutePos = apContext->absoluteWritePos; +#endif /* M4OSA_FILECACHE_MM */ + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_clockGetTime(&time2,1000); + if (time2>time1) + apContext->gMyPerfFileTab[fileSeektime] += time2-time1; +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + +UNLOCK + + /* Return without error */ + return err; +} + +M4OSA_ERR M4OSA_fileFlush_cache( M4OSA_Context pContext) +{ + /* Do nothing, M4OSA_fileCache module manages its caches by itself */ + + return M4NO_ERROR; +} +/** +****************************************************************************** +* @brief This method asks the core file reader to close the file (associated to 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_fileClose_cache(M4OSA_Context pContext) +{ + M4OSA_FileCache_Context* apContext = (M4OSA_FileCache_Context*) pContext; + + M4OSA_ERR err = M4NO_ERROR; + M4OSA_Int32 aRet_Val = 0; + M4OSA_UInt16 errReturned = 0; + + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_Time time1 = 0; + M4OSA_Time time2 = 0; + + M4OSA_clockGetTime(&time1,1000); +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + M4OSA_TRACE2_1("M4OSA_fileClose_cache pC = 0x%x", 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 */ + } + +LOCK + +#ifdef BUFFER_DISPLAY + M4OSA_FileCache_BufferDisplay(apContext); +#endif + + M4OSA_FileCache_BuffersFlushUntil(apContext, M4OSA_CACHEBUFFER_ALL); + + /* buffer */ + M4OSA_FileCache_BuffersFree(apContext); + + /* Close the file */ + aRet_Val = apContext->FS->pFctPtr_Close(apContext->aFileDesc, &errReturned); + + if (aRet_Val != 0) + { + /* converts the error to PSW format*/ + err = M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_READER, errReturned); + M4OSA_TRACE1_1("M4OSA_fileClose_cache ERR1 = 0x%x", err); + } + apContext->IsOpened = M4OSA_FALSE; + + /* Free the context */ + M4OSA_free((M4OSA_MemAddr32)apContext->FS); + M4OSA_free((M4OSA_MemAddr32)apContext->aFileDesc); + +#ifdef FILECACHE_STATS +{ + M4OSA_Int32 successRateRead, successRateWrite; + + successRateRead= (apContext->nbReadFFS + apContext->nbReadCache ==0)? (-1) : (apContext->nbReadCache)*100 / (apContext->nbReadCache + apContext->nbReadFFS); + + successRateWrite = (apContext->nbWriteFFS + apContext->nbWriteCache == 0)? (-1) : (apContext->nbWriteCache)*100 / (apContext->nbWriteCache + apContext->nbWriteFFS); + +#if defined(BUFFER_SELECT_INITIAL) + M4OSA_TRACE1_0("BUFFER_SELECT_INITIAL"); +#elif defined(BUFFER_SELECT_WITH_TIME) + M4OSA_TRACE1_0("BUFFER_SELECT_WITH_TIME"); +#elif defined(BUFFER_SELECT_WITH_SPACE) + M4OSA_TRACE1_0("BUFFER_SELECT_WITH_SPACE"); +#elif defined(BUFFER_SELECT_WITH_POS) + M4OSA_TRACE1_0("BUFFER_SELECT_WITH_POS"); +#endif + + M4OSA_TRACE1_1("Osal File Cache Stats for %s", apContext->m_filename); + M4OSA_TRACE1_2("FILECACHE_STATS: nbReadCache=%d / nbReadFFS=%d", + apContext->nbReadCache, apContext->nbReadFFS); + M4OSA_TRACE1_2("FILECACHE_STATS: nbWriteCache=%d / nbWriteFFS=%d", + apContext->nbWriteCache, apContext->nbWriteFFS); + M4OSA_TRACE1_2("FILECACHE_STATS: Success in reading : %d percent - Success in writing %d percent", + successRateRead, successRateWrite); + M4OSA_TRACE1_0("---------------------------------------------------------"); +} +#endif /* FILECACHE_STATS */ + + UNLOCK + + if (apContext->m_mutex != M4OSA_NULL) + { + M4OSA_mutexClose(apContext->m_mutex); + apContext->m_mutex = M4OSA_NULL; + } + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_clockGetTime(&time2,1000); + if (time2>time1) + apContext->gMyPerfFileTab[fileClosetime] += time2-time1; + + M4OSA_FileCache_displayTimeMeas(apContext); +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + M4OSA_memset((M4OSA_MemAddr8)apContext, sizeof(M4OSA_FileCache_Context), 0); + + M4OSA_free((M4OSA_MemAddr32)apContext); + + M4OSA_TRACE2_1("M4OSA_fileClose_cache leaving with err = 0x%x", err); + + /* Return without error */ + return err; +} + +/** +****************************************************************************** +* @brief This method asks the core file reader to set 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 OptionValue : (IN) 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_fileSetOption_cache(M4OSA_Context pContext, + M4OSA_OptionID OptionID, + M4OSA_DataOption OptionValue) +{ + M4OSA_FileCache_Context* apContext = (M4OSA_FileCache_Context*) pContext; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_Time time1 = 0; + M4OSA_Time time2 = 0; + + M4OSA_clockGetTime(&time1,1000); +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + /* 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 */ + } + + /* Set the desired option if it is avalaible */ + switch(OptionID) + { + case M4OSA_kFileReadGetFileSize : /**< Get size of the file, limited to 32 bit size */ + case M4OSA_kFileReadGetFileAttribute : /**< Get the file attribute*/ + case M4OSA_kFileReadGetURL : /**< Get the directory + name of the file */ + case M4OSA_kFileReadIsEOF : /**< See if we are at the end of the file */ + case M4OSA_kFileReadGetFilePosition : /**< Get file position */ + return M4ERR_READ_ONLY; + break; + + case M4OSA_kFileWriteDescMode: + return M4NO_ERROR; /* for MM */ + + default : /**< Bad option ID */ + return M4ERR_BAD_OPTION_ID; + break; + } + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_clockGetTime(&time2,1000); + if (time2>time1) + apContext->gMyPerfFileTab[fileSetOptiontime] += time2-time1; +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + /* Return without error */ + return M4NO_ERROR; +} + +/** +****************************************************************************** +* @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_fileGetOption_cache(M4OSA_Context pContext, + M4OSA_OptionID OptionID, + M4OSA_DataOption* pOptionValue) +{ + M4OSA_FileCache_Context* apContext = (M4OSA_FileCache_Context*) pContext; + M4OSA_ERR err = M4NO_ERROR; + M4OSA_Bool isEof; + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_Time time1 = 0; + M4OSA_Time time2 = 0; + + M4OSA_clockGetTime(&time1,1000); +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + + /* 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 */ + } + +LOCK + + /* 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_TRACE2_1("M4OSA_fileGetOption_cache ReadGetFileSize return filesize = %d ", + apContext->virtualFileSize); + (*(M4OSA_UInt32 *)pOptionValue) = apContext->virtualFileSize; /* return virtual */ + break; + + + case M4OSA_kFileWriteGetFileSize:/**< Get size of the file, limited to 32 bit size */ + M4OSA_TRACE2_1("M4OSA_fileGetOption_cache WriteGetFileSize return filesize = %d ", + apContext->virtualFileSize); + (*(M4OSA_UInt32 *)pOptionValue) = apContext->virtualFileSize; /* return virtual */ + break; + + /* Check End of file Occurs */ + case M4OSA_kFileReadIsEOF : /**< See if we are at the end of the file */ + isEof = (apContext->absolutePos >= apContext->virtualFileSize) ? M4OSA_TRUE : M4OSA_FALSE; /* virtual */ + (*(M4OSA_Bool *)pOptionValue) = isEof; + M4OSA_TRACE2_1("M4OSA_fileGetOption_cache ReadIsEOF return isEof=%d ", + isEof); + break; + + /* Get File Position */ + case M4OSA_kFileReadGetFilePosition : /**< Get file position */ + M4OSA_TRACE2_1("M4OSA_fileGetOption_cache ReadGetFilePosition return rpos=%d ", + apContext->absolutePos); + *(M4OSA_FilePosition *)pOptionValue = apContext->absolutePos; + break; + + /* Get File Position */ + case M4OSA_kFileWriteGetFilePosition : /**< Get file position */ + M4OSA_TRACE2_1("M4OSA_fileGetOption_cache WriteGetFilePosition return wpos=%d ", + apContext->absoluteWritePos); + *(M4OSA_FilePosition *)pOptionValue = apContext->absoluteWritePos; + break; + + /* Get Attribute */ + case M4OSA_kFileReadGetFileAttribute : /**< Get the file attribute = access mode */ + M4OSA_TRACE2_1("M4OSA_fileGetOption_cache ReadGetFileAttribute return mode=%d ", + apContext->FileAttribute.modeAccess); + (*(M4OSA_FileAttribute *)pOptionValue).modeAccess = apContext->FileAttribute.modeAccess; + break; + /** Get the reader context for read & write file. (M4OSA_Context*)*/ + case M4OSA_kFileWriteGetReaderContext: + M4OSA_TRACE2_1("M4OSA_fileGetOption_cache WriteGetReaderContext return c=0x%x ", + apContext); + (*(M4OSA_Context *)pOptionValue) = apContext; + break; + default: + /**< Bad option ID */ + UNLOCK + return M4ERR_BAD_OPTION_ID; + break; + } + +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + M4OSA_clockGetTime(&time2,1000); + if (time2>time1) + apContext->gMyPerfFileTab[fileGetOptiontime] += time2-time1; +#endif /* M4OSA_FILE_CACHE_TIME_MEAS */ + + UNLOCK + + + /*Return without error */ + return err; +} + +/* For VA */ +M4OSA_ERR M4OSA_fileExtrafTruncate_cache(M4OSA_Context context, M4OSA_UInt32 length) +{ + M4OSA_ERR err = M4NO_ERROR; + M4OSA_UInt16 result = M4OSA_FALSE; + M4OSA_FileCache_Context* apContext = context; + + + FILE* filedesc1 = ((M4OSA_FileSystem_FFS_t_cache*) ( apContext->aFileDesc))->FileDesc; + + result = ftruncate(filedesc1->_file, length); + + if(result != 0) + { + err = errno; + M4OSA_TRACE1_1("SetEndOfFile returns err: 0x%x\n", err); + return M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_EXTRA, err); + } + return M4NO_ERROR; +} +#ifdef M4OSA_FILE_CACHE_TIME_MEAS + +/**************************************************************/ +void M4OSA_FileCache_initTimeMeas(M4OSA_Context pContext) +/**************************************************************/ +{ + M4OSA_FileCache_Context* apContext = (M4OSA_FileCache_Context*) pContext; + M4OSA_Time time1 = 0; + + memset(apContext->gMyPerfFileTab, 0, sizeof(apContext->gMyPerfFileTab)); //Reset perf measurement array + + M4OSA_clockGetTime(&time1,1000); + apContext->gMyPerfFileTab[enum_size] = time1; //to compute total application time + +} + +/**************************************************************/ +void M4OSA_FileCache_displayTimeMeas(M4OSA_Context pContext) +/**************************************************************/ +{ + M4OSA_FileCache_Context* apContext = (M4OSA_FileCache_Context*) pContext; + + M4OSA_Time globalfileperfmeas = 0; + M4OSA_Time time2 = 0; + M4OSA_UInt32 i=0; + + M4OSA_clockGetTime(&time2,1000); + + /* Time spent in application */ + time2 = time2-apContext->gMyPerfFileTab[enum_size]; + + /* Time spent in File System procedures */ + for (i=0; i<enum_size; i++) + globalfileperfmeas += apContext->gMyPerfFileTab[i]; + + M4OSA_TRACE1_1("Osal File Cache Time measurement for %s ", + apContext->m_filename); + M4OSA_TRACE1_2("Application time =%d, fileCache total time =%d", + (M4OSA_Int32)time2, + (M4OSA_Int32)globalfileperfmeas); + M4OSA_TRACE1_4("Opentime:%d, ReadDatatime:%d, WriteDatatime: %d, Seektime:%d", + (M4OSA_Int32)apContext->gMyPerfFileTab[fileOpentime] , + (M4OSA_Int32)apContext->gMyPerfFileTab[fileReadDatatime] , + (M4OSA_Int32)apContext->gMyPerfFileTab[fileWriteDatatime] , + (M4OSA_Int32)apContext->gMyPerfFileTab[fileSeektime] ); + M4OSA_TRACE1_4("GetOptiontime:%d, SetOptiontime:%d, ExternalFlush: %d, Closetime: %d", + (M4OSA_Int32)apContext->gMyPerfFileTab[fileGetOptiontime] , + (M4OSA_Int32)apContext->gMyPerfFileTab[fileSetOptiontime], + (M4OSA_Int32)apContext->gMyPerfFileTab[fileExternalFlushtime], + (M4OSA_Int32)apContext->gMyPerfFileTab[fileClosetime]); + M4OSA_TRACE1_0("--------------------------------------------------------------------"); +} + +#endif /* M4OSA_FILE_INTERFACE_MM_TIME_MEAS */ diff --git a/libvideoeditor/osal/src/M4OSA_FileCommon.c b/libvideoeditor/osal/src/M4OSA_FileCommon.c new file mode 100755 index 0000000..25163e6 --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_FileCommon.c @@ -0,0 +1,672 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_FileCommon.c + * @brief File common for Android + * @note This file implements functions used by both the file writer + * and file reader. + ************************************************************************ +*/ + +#ifndef USE_STAGEFRIGHT_CODECS +#error "USE_STAGEFRIGHT_CODECS is not defined" +#endif USE_STAGEFRIGHT_CODECS + +#ifdef UTF_CONVERSION +#include <string.h> +#endif /*UTF_CONVERSION*/ + +#include <sys/stat.h> +#include <errno.h> + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE +#include "M4OSA_Semaphore.h" +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + +#include "M4OSA_Debug.h" +#include "M4OSA_FileCommon.h" +#include "M4OSA_FileCommon_priv.h" +#include "M4OSA_Memory.h" +#include "M4OSA_CharStar.h" + +/** + ************************************************************************ + * @brief This function opens the provided URL and returns its context. + * If an error occured, the context is set to NULL. + * @param core_id: (IN) Core ID of the caller (M4OSA_FILE_READER or M4OSA_FILE_WRITER) + * @param context: (OUT) Context of the core file reader + * @param url: (IN) URL of the input file + * @param fileModeAccess: (IN) File mode access + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + * @return M4ERR_FILE_NOT_FOUND: the file cannot be found + * @return M4ERR_FILE_LOCKED: the file is locked by an other + * application/process + * @return M4ERR_FILE_BAD_MODE_ACCESS: the file mode access is not correct + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileCommonOpen(M4OSA_UInt16 core_id, M4OSA_Context* pContext, + M4OSA_Char* pUrl, M4OSA_FileModeAccess fileModeAccess) +{ + + M4OSA_Int32 i = 0; + M4OSA_Int32 iMode = 0; + M4OSA_Int32 iSize = 0; + M4OSA_Int32 iSavePos = 0; + + M4OSA_Char mode[4] = ""; + M4OSA_Char* pReadString = (M4OSA_Char*)"r"; + M4OSA_Char* pWriteString = (M4OSA_Char*)"w"; + M4OSA_Char* pAppendString = (M4OSA_Char*)"a"; + M4OSA_Char* pBinaryString = (M4OSA_Char*)"b"; + M4OSA_Char* pPlusString = (M4OSA_Char*)"+"; + + M4OSA_ERR err = M4NO_ERROR; + + FILE* pFileHandler = M4OSA_NULL; + M4OSA_FileContext *pFileContext = M4OSA_NULL; + +#ifdef UTF_CONVERSION + /*FB: to test the UTF16->UTF8 conversion into Video Artist*/ + /*Convert the URL from UTF16 to UTF8*/ + M4OSA_Void* tempConversionBuf; + M4OSA_UInt32 tempConversionSize = 1000; + + tempConversionBuf = (M4OSA_Char*)M4OSA_malloc(tempConversionSize +1, 0, "conversion buf"); + if(tempConversionBuf == M4OSA_NULL) + { + M4OSA_TRACE1_0("Error when allocating conversion buffer\n"); + return M4ERR_PARAMETER; + } + M4OSA_ToUTF8_OSAL(pUrl, tempConversionBuf, &tempConversionSize); + ((M4OSA_Char*)tempConversionBuf)[tempConversionSize ] = '\0'; + + printf("file open %s\n", tempConversionBuf); +#endif /*UTF CONVERSION*/ + +///*tmpLSA*/M4OSA_TRACE1_2("### M4OSA_fileCommonOpen %s 0x%X", pUrl, fileModeAccess); + M4OSA_TRACE3_4("M4OSA_fileCommonOpen\t\tM4OSA_UInt16 %d\tM4OSA_Context* 0x%x\t" + "M4OSA_Char* %s\tfileModeAccess %d", core_id, pContext, pUrl, fileModeAccess); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, "M4OSA_fileCommonOpen: pContext is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pUrl, M4ERR_PARAMETER, "M4OSA_fileCommonOpen: pUrl is M4OSA_NULL"); + M4OSA_DEBUG_IF2(0 == fileModeAccess, M4ERR_PARAMETER, "M4OSA_fileCommonOpen: fileModeAccess is 0"); + + /* Read mode not set for the reader */ + M4OSA_DEBUG_IF1((M4OSA_FILE_READER == core_id) && !(fileModeAccess & M4OSA_kFileRead), + M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileRead"); + + /* Read mode not set for the reader */ + M4OSA_DEBUG_IF1((M4OSA_FILE_READER == core_id) && !(fileModeAccess & M4OSA_kFileRead), + M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileRead"); + + /* M4OSAfileReadOpen cannot be used with Write file mode access */ + M4OSA_DEBUG_IF1((M4OSA_FILE_READER == core_id) && (fileModeAccess & M4OSA_kFileWrite), + M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileWrite"); + + /* Append and Create flags cannot be used with Read */ + M4OSA_DEBUG_IF1((M4OSA_FILE_READER == core_id) && (fileModeAccess & M4OSA_kFileAppend), + M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileAppend"); + + M4OSA_DEBUG_IF1((M4OSA_FILE_READER == core_id) && (fileModeAccess & M4OSA_kFileCreate), + M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileCreate"); + + /* Write mode not set for the writer */ + M4OSA_DEBUG_IF1((M4OSA_FILE_WRITER == core_id) && !(fileModeAccess & M4OSA_kFileWrite), + M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileWrite"); + + /* Create flag necessary for opening file */ + if ((fileModeAccess & M4OSA_kFileRead) && + (fileModeAccess & M4OSA_kFileWrite)&&(fileModeAccess & M4OSA_kFileCreate)) + { + M4OSA_chrNCat(mode, pWriteString, 1); + M4OSA_chrNCat(mode, pPlusString, 1); + } + else + { + if(fileModeAccess & M4OSA_kFileAppend) + { + M4OSA_chrNCat(mode, pAppendString, 1); + } + else if(fileModeAccess & M4OSA_kFileRead) + { + M4OSA_chrNCat(mode, pReadString, 1); + } + else if(fileModeAccess & M4OSA_kFileWrite) + { + M4OSA_chrNCat(mode, pWriteString, 1); + } + + if((fileModeAccess & M4OSA_kFileRead)&&(fileModeAccess & M4OSA_kFileWrite)) + { + M4OSA_chrNCat(mode,pPlusString, 1); + } + } + + if(!(fileModeAccess & M4OSA_kFileIsTextMode)) + { + M4OSA_chrNCat(mode, pBinaryString, 1); + } + + /*Open the file*/ + +#ifdef UTF_CONVERSION + /*Open the converted path*/ + pFileHandler = fopen((const char *)tempConversionBuf, (const char *)mode); + /*Free the temporary decoded buffer*/ + M4OSA_free((M4OSA_MemAddr32)tempConversionBuf); +#else + pFileHandler = fopen((const char *)pUrl, (const char *)mode); +#endif /* UTF_CONVERSION */ + + if (M4OSA_NULL == pFileHandler) + { + switch(errno) + { + case ENOENT: + { + M4OSA_DEBUG(M4ERR_FILE_NOT_FOUND, "M4OSA_fileCommonOpen: No such file or directory"); + M4OSA_TRACE1_1("File not found: %s", pUrl); + return M4ERR_FILE_NOT_FOUND; + } + case EACCES: + { + M4OSA_DEBUG(M4ERR_FILE_LOCKED, "M4OSA_fileCommonOpen: Permission denied"); + return M4ERR_FILE_LOCKED; + } + case EINVAL: + { + M4OSA_DEBUG(M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: Invalid Argument"); + return M4ERR_FILE_BAD_MODE_ACCESS; + } + case EMFILE: + case ENOSPC: + case ENOMEM: + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileCommonOpen: Too many open files"); + return M4ERR_ALLOC; + } + default: + { + M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_fileCommonOpen"); + return M4ERR_NOT_IMPLEMENTED; + } + } + } + + /* Allocate the file context */ + pFileContext = (M4OSA_FileContext*) M4OSA_malloc(sizeof(M4OSA_FileContext), + core_id, (M4OSA_Char*)"M4OSA_fileCommonOpen: file context"); + if (M4OSA_NULL == pFileContext) + { + fclose(pFileHandler); + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileCommonOpen"); + return M4ERR_ALLOC; + } + + pFileContext->file_desc = pFileHandler; + pFileContext->access_mode = fileModeAccess; + pFileContext->current_seek = SeekNone; + pFileContext->b_is_end_of_file = M4OSA_FALSE; + + /** + * Note: Never use this expression "i = (value1 == value2) ? x: y;" + * because that doens't compile on other platforms (ADS for example) + * Use: if(value1 == value2) + * { i= x; ..etc + */ + pFileContext->coreID_write = 0; + pFileContext->coreID_read = 0; + pFileContext->m_DescrModeAccess = M4OSA_kDescNoneAccess; + + if (M4OSA_FILE_READER == core_id) + { + pFileContext->coreID_read = core_id; + pFileContext->m_DescrModeAccess = M4OSA_kDescReadAccess; + } + else if (M4OSA_FILE_WRITER == core_id) + { + pFileContext->coreID_write = core_id; + pFileContext->m_DescrModeAccess = M4OSA_kDescWriteAccess; + } + + M4OSA_INT_TO_FILE_POSITION(0, pFileContext->read_position); + M4OSA_INT_TO_FILE_POSITION(0, pFileContext->write_position); + + /* Allocate the memory to store the URL string */ + pFileContext->url_name = (M4OSA_Char*) M4OSA_malloc(M4OSA_chrLength(pUrl)+1, + core_id, (M4OSA_Char*)"M4OSA_fileCommonOpen: URL name"); + if (M4OSA_NULL == pFileContext->url_name) + { + fclose(pFileHandler); + M4OSA_free((M4OSA_MemAddr32)pFileContext); + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileCommonOpen"); + return M4ERR_ALLOC; + } + M4OSA_chrNCopy(pFileContext->url_name, pUrl, M4OSA_chrLength(pUrl)+1); + + /* Get the file name */ + err = M4OSA_fileCommonGetFilename(pUrl, &pFileContext->file_name); + if(M4NO_ERROR != err) + { + fclose(pFileHandler); + M4OSA_free((M4OSA_MemAddr32)pFileContext->url_name); + M4OSA_free((M4OSA_MemAddr32)pFileContext); + M4OSA_DEBUG(err, "M4OSA_fileCommonOpen"); + return err; + } + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreOpen(&(pFileContext->semaphore_context), 1); /* Allocate the semaphore */ +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + + +#ifdef USE_STAGEFRIGHT_CODECS + // Workaround for file system bug on Stingray/Honeycomb where a file re-created will keep + // the original file's size filled with 0s. Do not seek to the end to avoid ill effects + if(fileModeAccess & M4OSA_kFileAppend) { + /* Get the file size */ + iSavePos = ftell(pFileHandler); /* 1- Check the first position */ + fseek(pFileHandler, 0, SEEK_END); /* 2- Go to the end of the file*/ + iSize = ftell(pFileHandler); /* 3- Check the file size */ + fseek(pFileHandler, iSavePos, SEEK_SET);/* 4- go to the first position */ + } else { + iSize = 0; + } +#else /* USE_STAGEFRIGHT_CODECS */ + /* Get the file size */ + iSavePos = ftell(pFileHandler); /* 1- Check the first position */ + fseek(pFileHandler, 0, SEEK_END); /* 2- Go to the end of the file*/ + iSize = ftell(pFileHandler); /* 3- Check the file size */ + fseek(pFileHandler, iSavePos, SEEK_SET);/* 4- go to the first position */ +#endif /* USE_STAGEFRIGHT_CODECS */ + + + + /* Warning possible overflow if the file is higher than 2GBytes */ + pFileContext->file_size = iSize; + + *pContext = pFileContext; +// /*tmpLSA*/M4OSA_TRACE1_1("### M4OSA_fileCommonOpen pFileContext 0x%X", pFileContext); + + return M4NO_ERROR; +} + + +/** + ************************************************************************ + * @brief This function convert from UTF16 to UTF8 + * @param pBufferIn: (IN) UTF16 input path + * @param pBufferOut: (OUT) UTF8 output path + * @param bufferOutSize: (IN/OUT) size of the output path + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: the output path size is not enough to contain + * the decoded path + ************************************************************************ +*/ +#ifdef UTF_CONVERSION +M4OSA_ERR M4OSA_ToUTF8_OSAL (M4OSA_Void *pBufferIn, M4OSA_UInt8 *pBufferOut, + M4OSA_UInt32 *bufferOutSize) +{ + M4OSA_UInt16 i; + wchar_t *w_str = (wchar_t *) pBufferIn; + M4OSA_UInt32 len, size_needed, size_given; + if (pBufferIn == NULL) + { + *pBufferOut=NULL; + *bufferOutSize=1; + } + else + { + len = wcslen(w_str); + size_needed = len+1; + size_given = *bufferOutSize; + + *bufferOutSize=size_needed; + if (size_given < size_needed ) + { + return M4ERR_PARAMETER; + } + else + { + for (i=0; i<len; i++) + { + pBufferOut[i]=(M4OSA_UInt8)w_str[i]; + } + pBufferOut[len]=0; + } + } + return M4NO_ERROR; +} +#endif /*UTF CONVERSION*/ + +/** + ************************************************************************ + * @brief This function seeks at the provided position. + * @param context: (IN/OUT) Context of the core file reader + * @param seekMode: (IN) Seek access mode + * @param position: (IN/OUT) Position in the file + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_FILE_INVALID_POSITION: the position cannot be reached + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileCommonSeek(M4OSA_Context pContext, + M4OSA_FileSeekAccessMode seekMode, + M4OSA_FilePosition* pFilePos) +{ + M4OSA_FileContext* pFileContext = pContext; + M4OSA_FilePosition fpos_current; + M4OSA_FilePosition fpos_seek; + M4OSA_FilePosition fpos_null; + M4OSA_FilePosition fpos_neg_un; + M4OSA_FilePosition fpos_file_size; + M4OSA_FilePosition fpos_seek_from_beginning; + + M4OSA_TRACE3_3("M4OSA_fileCommonSeek\t\tM4OSA_Context 0x%x\t M4OSA_FileSeekAccessMode %d\tM4OSA_FilePosition* 0x%x", + pContext, seekMode, pFilePos); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, "M4OSA_fileCommonSeek"); + M4OSA_DEBUG_IF2(0 == seekMode, M4ERR_PARAMETER, "M4OSA_fileCommonSeek"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pFilePos, M4ERR_PARAMETER, "M4OSA_fileCommonSeek"); + + M4OSA_INT_TO_FILE_POSITION(0, fpos_null); + M4OSA_INT_TO_FILE_POSITION(-1, fpos_neg_un); + M4OSA_FPOS_SET(fpos_file_size, pFileContext->file_size); + + if(SeekRead == pFileContext->current_seek) + { + M4OSA_FPOS_SET(fpos_current, pFileContext->read_position); + } + else if(SeekWrite == pFileContext->current_seek) + { + M4OSA_FPOS_SET(fpos_current, pFileContext->write_position); + } + else + { + M4OSA_INT_TO_FILE_POSITION(0, fpos_current); + } + + switch(seekMode) + { + case M4OSA_kFileSeekCurrent: + { + M4OSA_FPOS_SET(fpos_seek, *pFilePos); + break; + } + case M4OSA_kFileSeekBeginning: + { + M4OSA_FPOS_SUB(fpos_seek, *pFilePos, fpos_current) + break; + } + case M4OSA_kFileSeekEnd: + { + M4OSA_FPOS_ADD(fpos_seek, fpos_file_size, *pFilePos); + M4OSA_FPOS_SUB(fpos_seek, fpos_seek, fpos_current); + break; + } + default: + { + return M4ERR_PARAMETER; + } + } + + M4OSA_FPOS_ADD(fpos_seek_from_beginning, fpos_current, fpos_seek); + + if(fseek(pFileContext->file_desc, fpos_seek, SEEK_CUR) != 0) + { + switch(errno) + { + case EINVAL: + { + /* meaning the value for origin is invalid or the position + specified by offset is before the beginning of the file */ + return M4ERR_FILE_INVALID_POSITION; + } + + case EBADF: + default: + { + return M4ERR_BAD_CONTEXT;/* file handle is invalid */ + } + } + } + + /* Set the returned position from the beginning of the file */ + M4OSA_FPOS_SET(*pFilePos, fpos_seek_from_beginning); + + /* SEEK done, reset end of file value */ + pFileContext->b_is_end_of_file = M4OSA_FALSE; + + return M4NO_ERROR; +} + + +/** + ************************************************************************ + * @brief This function asks to close the file (associated to the context) + * @note The context of the core file reader/writer is freed. + * @param context: (IN/OUT) Context of the core file reader + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + ************************************************************************ +*/ + +M4OSA_ERR M4OSA_fileCommonClose(M4OSA_UInt16 core_id, M4OSA_Context pContext) +{ + M4OSA_FileContext* pFileContext = pContext; + M4OSA_Int32 i32_err_code=0; + + M4OSA_TRACE3_2("M4OSA_fileCommonClose\tM4OSA_UInt16 %d\tM4OSA_Context 0x%x", + core_id, pContext); + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, + M4ERR_PARAMETER, "M4OSA_fileCommonClose: pContext is M4OSA_NULL"); +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, M4ERR_BAD_CONTEXT, + "M4OSA_fileCommonClose: semaphore_context is M4OSA_NULL"); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + M4OSA_free((M4OSA_MemAddr32)pFileContext->url_name); + pFileContext->url_name = M4OSA_NULL; + + M4OSA_free((M4OSA_MemAddr32)pFileContext->file_name); + pFileContext->file_name = M4OSA_NULL; + + i32_err_code = fclose(pFileContext->file_desc); + + pFileContext->file_desc = M4OSA_NULL; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreClose(pFileContext->semaphore_context);/* free the semaphore */ +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + M4OSA_free((M4OSA_MemAddr32)pFileContext); + + if (i32_err_code != 0) + { + M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_fileCommonClose"); + return M4ERR_BAD_CONTEXT; + } + + return M4NO_ERROR; +} + + +/** + ************************************************************************ + * @brief This function gets the file attributes (associated to the + * context) + * @param context: (IN) Context of the core file reader + * @param attribute: (OUT) The file attribute (allocated by the caller) + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileCommonGetAttribute(M4OSA_Context pContext, M4OSA_FileAttribute* pAttribute) +{ + + M4OSA_FileContext* fileContext = pContext; + + struct stat TheStat; + + M4OSA_TRACE3_2("M4OSA_fileCommonGetAttribute\tM4OSA_Context 0x%x\t" + "M4OSA_FileAttribute* 0x%x", pContext, pAttribute); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, "M4OSA_fileCommonGetAttribute"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pAttribute, M4ERR_PARAMETER, "M4OSA_fileCommonGetAttribute"); + + if(stat((char*)fileContext->url_name, &TheStat) != 0) + { + M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_fileCommonGetAttribute"); + return M4ERR_BAD_CONTEXT; + } + + M4OSA_INT64_FROM_INT32(pAttribute->creationDate.time, TheStat.st_ctime); + M4OSA_INT64_FROM_INT32(pAttribute->lastAccessDate.time, TheStat.st_atime); + M4OSA_INT64_FROM_INT32(pAttribute->modifiedDate.time, TheStat.st_mtime); + + pAttribute->creationDate.timeScale = 1; + pAttribute->lastAccessDate.timeScale= 1; + pAttribute->modifiedDate.timeScale = 1; + + pAttribute->creationDate.referenceYear = 1970; + pAttribute->lastAccessDate.referenceYear= 1970; + pAttribute->modifiedDate.referenceYear = 1970; + + pAttribute->modeAccess = fileContext->access_mode; + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function gets the file URL (associated to the context). + * @note + * @param context: (IN) Context of the core file reader + * @param url: (OUT) The buffer containing the URL (allocated by + * M4OSA_fileCommonGetURL) + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileCommonGetURL(M4OSA_Context pContext, M4OSA_Char** pUrl) +{ + M4OSA_FileContext* pFileContext = pContext; + M4OSA_UInt32 uiLength; + + M4OSA_TRACE3_2("M4OSA_fileCommonGetURL\tM4OSA_Context 0x%x\tM4OSA_Char** 0x%x", + pContext, pUrl); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileCommonGetURL: pContext is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pUrl, M4ERR_PARAMETER, + "M4OSA_fileCommonGetURL: pUrl is M4OSA_NULL"); + + uiLength = M4OSA_chrLength(pFileContext->url_name)+1; + + /* Allocate the memory to store the url_name */ + *pUrl = (M4OSA_Char*)M4OSA_malloc(uiLength, M4OSA_FILE_COMMON, + (M4OSA_Char*)"M4OSA_fileCommonGetURL: url"); + if(M4OSA_NULL == *pUrl) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileCommonGetURL"); + return M4ERR_ALLOC; + } + + M4OSA_chrNCopy(*pUrl, pFileContext->url_name, uiLength); + + return M4NO_ERROR; +} + + +/** + ************************************************************************ + * @brief This function gets a string containing the file name associated + * to the input URL. + * @note The user should not forget to delete the output string using + * M4OSA_strDestroy + * @param pUrl: (IN) The buffer containing the URL + * @param pFileName: (OUT) The string containing the URL. It is + * allocated inside this function + * @return M4NO_ERROR: there is no error + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + * @return M4ERR_ALLOC: there is no more memory available + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileCommonGetFilename(M4OSA_Char* pUrl, M4OSA_Char** pFileName) +{ + M4OSA_Int32 i = 0; + M4OSA_Int32 iUrlLen = 0; + M4OSA_Int32 FileNameLen = 0; + + M4OSA_Char* ptrUrl = M4OSA_NULL; + M4OSA_Char* ptrFilename = M4OSA_NULL; + + M4OSA_TRACE3_2("M4OSA_fileCommonGetURL\tM4OSA_Char* %s\tM4OSA_Char** 0x%x", + pUrl, pFileName); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pUrl, M4ERR_PARAMETER, + "M4OSA_fileCommonGetFilename: pUrl is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileName, M4ERR_PARAMETER, + "M4OSA_fileCommonGetFilename: pFileName is M4OSA_NULL"); + + *pFileName = M4OSA_NULL; + + /*Parse URL*/ + iUrlLen = M4OSA_chrLength(pUrl); + for(i=iUrlLen-1; i>=0; i--) + { + if (pUrl[i] != '\\' && pUrl[i] != '/') + { + FileNameLen++; + } + else + { + break; /* find the beginning of the file name */ + } + } + + ptrFilename = (M4OSA_Char*) M4OSA_malloc(FileNameLen+1, M4OSA_FILE_COMMON, + (M4OSA_Char*)"M4OSA_fileCommonGetFilename: Filename string"); + if (ptrFilename == M4OSA_NULL) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileCommonGetFilename"); + return M4ERR_ALLOC; + } + + ptrUrl = pUrl + (iUrlLen - FileNameLen); + M4OSA_chrNCopy(ptrFilename, ptrUrl, FileNameLen+1); + + *pFileName = ptrFilename; + + return M4NO_ERROR; +} + diff --git a/libvideoeditor/osal/src/M4OSA_FileExtra.c b/libvideoeditor/osal/src/M4OSA_FileExtra.c new file mode 100755 index 0000000..4a7b532 --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_FileExtra.c @@ -0,0 +1,527 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_FileExtra.c +* @brief File extra for Android +* @note This file implements a set of basic functions to handle file +* itself. +************************************************************************ +*/ + +#include "M4OSA_Debug.h" +#include "M4OSA_FileCommon.h" +#include "M4OSA_FileCommon_priv.h" +#include "M4OSA_FileExtra.h" +#include "M4OSA_FileReader.h" +#include "M4OSA_FileWriter.h" + +#include <errno.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/statfs.h> + + + +/** + ************************************************************************ + * @brief This function deletes the provided URL. + * @note + * @param pUrl: (IN) URL of the file to delete + * @param fileModeAccess: (IN) File mode access + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileExtraDelete(const M4OSA_Char* pUrl) +{ + + M4OSA_Int32 err; +#ifdef UTF_CONVERSION + M4OSA_Void* tempConversionBuf; + M4OSA_UInt32 tempConversionSize = 1000; /*size of the decoded buffer, + can be increase if necessary*/ +#endif /* UTF_CONVERSION */ + + M4OSA_TRACE1_1("M4OSA_fileExtraDelete\t\tM4OSA_Char* %s", pUrl); + M4OSA_DEBUG_IF2(M4OSA_NULL == pUrl, M4ERR_PARAMETER, + "M4OSA_fileExtraDelete: pUrl is M4OSA_NULL"); + +#ifdef UTF_CONVERSION + /*FB: to test the UTF16->UTF8 conversion into Video Artist*/ + /*Convert the URL from UTF16 to UTF8*/ + tempConversionBuf = (M4OSA_Char*)M4OSA_malloc(tempConversionSize +1, 0, + (M4OSA_Char*)"conversion buf"); + if(tempConversionBuf == M4OSA_NULL) + { + M4OSA_TRACE1_0("Error when allocating conversion buffer\n"); + return M4ERR_PARAMETER; + } + M4OSA_ToUTF8_OSAL((M4OSA_Void*)pUrl, tempConversionBuf, &tempConversionSize); + ((M4OSA_Char*)tempConversionBuf)[tempConversionSize ] = '\0'; + + printf("remove file %s\n", tempConversionBuf); + + /*Open the converted path*/ + err = remove (tempConversionBuf); + /*Free the temporary decoded buffer*/ + M4OSA_free((M4OSA_MemAddr32)tempConversionBuf); +#else + err = remove((const char *)pUrl); +#endif /* UTF_CONVERSION */ + + if(-1 == err) + { + M4OSA_DEBUG(M4ERR_PARAMETER, + "M4OSA_fileExtraDelete: Cannot remove the input url"); + return M4ERR_PARAMETER; + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function copies the file located by 'pSrcUrl' to 'pDstUrl'. + * @note + * @param pSrcUrl: (IN) source URL + * @param pDstUrl: (IN) Destination URL + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileExtraCopy(M4OSA_Char* pSrcUrl, M4OSA_Char* pDstUrl) +{ + M4OSA_Context pInputFileContext = M4OSA_NULL; + M4OSA_Context pOutputFileContext= M4OSA_NULL; + + M4OSA_ERR err; + M4OSA_UInt32 uiSizeRead = BUFFER_COPY_SIZE; + M4OSA_MemAddr32 copy_buffer; + + M4OSA_TRACE1_2("M4OSA_fileExtraDelete\t\tM4OSA_Char* %s\tM4OSA_Char* %s", + pSrcUrl, pDstUrl); + M4OSA_DEBUG_IF2(M4OSA_NULL == pDstUrl, M4ERR_PARAMETER, + "M4OSA_fileExtraCopy: pDstUrl is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pSrcUrl, M4ERR_PARAMETER, + "M4OSA_fileExtraCopy: pSrcUrl is M4OSA_NULL"); + + /* Open input file */ + err = M4OSA_fileReadOpen(&pInputFileContext, pSrcUrl, M4OSA_kFileRead); + if(M4NO_ERROR != err) + { + M4OSA_DEBUG(err, "M4OSA_fileExtraCopy: M4OSA_fileReadOpen"); + return err; + } + + /* Open output file */ + err = M4OSA_fileWriteOpen(&pOutputFileContext, pDstUrl, + M4OSA_kFileWrite|M4OSA_kFileCreate); + if(M4NO_ERROR != err) + { + M4OSA_DEBUG(err, "M4OSA_fileExtraCopy: M4OSA_fileWriteOpen"); + return err; + } + + /* Allocate buffer */ + copy_buffer = M4OSA_malloc(BUFFER_COPY_SIZE, M4OSA_FILE_EXTRA, + (M4OSA_Char*)"M4OSA_fileExtraCopy: copy buffer"); + if(M4OSA_NULL == copy_buffer) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileExtraCopy"); + return M4ERR_ALLOC; + } + + /* Copy input file to output file using copy buffer */ + while (1) + { + /* Load data into copy buffer */ + err = M4OSA_fileReadData(pInputFileContext, + (M4OSA_MemAddr8)copy_buffer, &uiSizeRead); + if(M4NO_ERROR == err) + { + /* Write data to output file */ + err = M4OSA_fileWriteData(pOutputFileContext, + (M4OSA_MemAddr8)copy_buffer, uiSizeRead); + if(M4NO_ERROR != err) + { + break; + } + } + else if (M4WAR_NO_DATA_YET == err) + { + /* no more data to copy, end of file reached */ + err = M4OSA_fileWriteData(pOutputFileContext, + (M4OSA_MemAddr8)copy_buffer, uiSizeRead); + break; + } + else + { + break; /* an error occur */ + } + } + + /* Free copy buffer */ + M4OSA_free(copy_buffer); + + err = M4OSA_fileWriteClose(pOutputFileContext); + if(M4NO_ERROR != err) + { + M4OSA_DEBUG(err, "M4OSA_fileExtraCopy: M4OSA_fileWriteClose"); + } + + err = M4OSA_fileReadClose(pInputFileContext); + if(M4NO_ERROR != err) + { + M4OSA_DEBUG(err, "M4OSA_fileExtraCopy: M4OSA_fileReadClose"); + } + + return err; +} + + +/** + ************************************************************************ + * @brief This function renames the 'pSrcUrl' to 'pDstUrl'. + * @note + * @param pSrcUrl: (IN) source URL + * @param pDstUrl: (IN) Destination URL + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileExtraRename(M4OSA_Char* pSrcUrl, M4OSA_Char* pDstUrl) +{ + M4OSA_ERR err; + M4OSA_Int32 iValue; + M4OSA_Char* pSrcFilename = M4OSA_NULL; + M4OSA_Char* pDstFilename = M4OSA_NULL; + + M4OSA_TRACE1_2("M4OSA_fileExtraRename\t\tM4OSA_Char* %s\tM4OSA_Char* %s", + pSrcUrl, pDstUrl); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pDstUrl, M4ERR_PARAMETER, + "M4OSA_fileExtraRename: pSrcUrl is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pSrcUrl, M4ERR_PARAMETER, + "M4OSA_fileExtraRename: pDstUrl is M4OSA_NULL"); + + err = M4OSA_fileCommonGetFilename(pSrcUrl, &pSrcFilename); + if(M4NO_ERROR != err) + { + M4OSA_DEBUG(err, "M4OSA_fileExtraRename: M4OSA_fileCommonGetFilename"); + return err; + } + + err = M4OSA_fileCommonGetFilename(pDstUrl, &pDstFilename); + if(M4NO_ERROR != err) + { + M4OSA_free((M4OSA_MemAddr32)pSrcFilename); + M4OSA_DEBUG(err, "M4OSA_fileExtraRename: M4OSA_fileCommonGetFilename"); + return err; + } + + /* Rename file */ + iValue = rename((const char *)pSrcFilename, (const char *)pDstFilename); + if (0 != iValue) + { + /* + What error code shall be returned ? From MSDN: + Each of these functions returns 0 if it is successful. On an error, the + function returns a nonzero value and sets errno to one of the following + values: + - EACCES: File or directory specified by newname already exists or could + not be created (invalid path); or oldname is a directory and newname + specifies a different path. + - ENOENT: File or path specified by oldname not found. + - EINVAL: Name contains invalid characters. + For other possible return values, see _doserrno, _errno, syserrlist, and + _sys_nerr. */ + M4OSA_DEBUG(M4ERR_PARAMETER, "M4OSA_fileExtraRename: rename failed"); + return M4ERR_PARAMETER; + } + + M4OSA_free((M4OSA_MemAddr32)pDstFilename); + M4OSA_free((M4OSA_MemAddr32)pSrcFilename); + + return M4NO_ERROR; +} + + + +/** + ************************************************************************ + * @brief This function changes the current directory to the specified new + * directory 'url'. + * @note + * @param pUrl: (IN) Directory to which current directory to be changed + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + ************************************************************************ +*/ + +M4OSA_ERR M4OSA_fileExtraChangeCurrentDir(const M4OSA_Char* pUrl) +{ + M4OSA_ERR err; + M4OSA_Char* pFileName = M4OSA_NULL; + M4OSA_Int32 iValue = 0; + + M4OSA_TRACE1_1("M4OSA_fileExtraChangeCurrentDir\t\tM4OSA_Char* %s", pUrl); + M4OSA_DEBUG_IF2(M4OSA_NULL == pUrl, M4ERR_PARAMETER, + "M4OSA_fileExtraChangeCurrentDir: pUrl is M4OSA_NULL"); + + err = M4OSA_fileCommonGetFilename((M4OSA_Char*)pUrl, &pFileName); + if(M4NO_ERROR != err) + { + M4OSA_DEBUG(err, + "M4OSA_fileExtraChangeCurrentDir: M4OSA_fileCommonGetFilename"); + return err; + } + + iValue = chdir((char*)pFileName); + + if (iValue != 0) + { + /* + What error code shall be returned ? From MSDN: + Each of these functions returns a value of 0 if successful. A return + value of -1 indicates that the specified path could not be found, in + which case errno is set to ENOENT.*/ + M4OSA_DEBUG(M4ERR_PARAMETER, + "M4OSA_fileExtraChangeCurrentDir: chdir failed"); + return(M4ERR_PARAMETER); + } + + M4OSA_free((M4OSA_MemAddr32)pFileName); + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function creates a new directory to the specified 'url'. + * @note + * @param pUrl: (IN) Path to create new directory with name + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileExtraCreateDir(const M4OSA_Char* pUrl) +{ + M4OSA_Int32 err; + + M4OSA_TRACE2_1("M4OSA_fileExtraCreateDir %s", pUrl); + M4OSA_DEBUG_IF2(M4OSA_NULL == pUrl, M4ERR_PARAMETER, + "M4OSA_fileExtraCreateDir: pUrl is M4OSA_NULL"); + + err = mkdir((char*)pUrl, S_IRWXU | S_IRWXG | S_IRWXO); + + if( err < 0 ) + { + return M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_EXTRA, errno); + } + + return M4NO_ERROR; +} + + +/** + ************************************************************************ + * @brief This function removes the current directory. + * @note + * @param pUrl: (IN) Path of directory with name + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileExtraRemoveDir(const M4OSA_Char* pUrl) +{ + M4OSA_Int32 err; + + M4OSA_TRACE2_1("M4OSA_fileExtraRemoveDir %s", pUrl); + M4OSA_DEBUG_IF2(M4OSA_NULL == pUrl, M4ERR_PARAMETER, + "M4OSA_fileExtraRemoveDir: pUrl is M4OSA_NULL"); + + err = rmdir((char*)pUrl); + if(err < 0 ) + { + M4OSA_DEBUG(M4ERR_PARAMETER, "M4OSA_fileExtraRemoveDir failed"); + return M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_EXTRA, errno); + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief retrieves the free space. + * @note + * @param pUrl: (IN) root directory + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + ************************************************************************ +*/ +M4OSA_UInt32 M4OSA_fileExtraGetFreeSpace(const M4OSA_Char* pUrl) +{ + M4OSA_UInt32 size = 0; + struct statfs stat; + + if ( M4OSA_NULL != pUrl ) + { + if (0 == statfs( (const char *)pUrl, &stat )) + { + if ((stat.f_bfree * stat.f_bsize) > M4OSA_UINT32_MAX) + { + size = M4OSA_UINT32_MAX; + } + else + { + size = (M4OSA_UInt32)(stat.f_bfree * stat.f_bsize); + } + } + } + + return (size); +} + +/** + ************************************************************************ + * @brief This function gets the total space + * @note + * @param pUrl: (IN) Path of directory with name + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + ************************************************************************ +*/ +M4OSA_UInt32 M4OSA_fileExtraGetTotalSpace(const M4OSA_Char* pUrl) +{ + M4OSA_UInt32 size = 0; + struct statfs stat; + + if ( M4OSA_NULL != pUrl ) + { + if (0 == statfs( (const char *)pUrl, &stat )) + { + if ((stat.f_blocks * stat.f_bsize) > M4OSA_UINT32_MAX) + { + size = M4OSA_UINT32_MAX; + } + else + { + size = (M4OSA_UInt32)(stat.f_blocks * stat.f_bsize); + } + } + } + + return (size); +} + +/** + ************************************************************************ + * @brief This function retrieve the file type (Directory or file). + * @note + * @param pUrl: (IN) Path of directory with name + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + ************************************************************************ +*/ +M4OSA_EntryType M4OSA_fileExtraGetType(const M4OSA_Char* pUrl) +{ + M4OSA_EntryType type = M4OSA_TypeInvalid; + struct stat fileStat; + + if ( M4OSA_NULL != pUrl ) + { + if (0 == stat( (const char *)pUrl, &fileStat)) + { + if ( S_ISDIR( fileStat.st_mode ) ) + { + type = M4OSA_TypeDir; + } + else + { + type = M4OSA_TypeFile; + } + } + } + + return (type); +} + + +/** + ************************************************************************ + * @brief This function truncate a file. + * the file must be previously opened in write mode + * @note the position pointer in the file is set to the beginning + * of the file after the truncate + * @param context: (IN) media context + * @param length: (IN) length of the file after truncation + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_PARAMETER: at least one parameter is NULL + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileExtrafTruncate(M4OSA_Context context, M4OSA_FilePosition length) +{ + M4OSA_ERR err = M4NO_ERROR; + M4OSA_UInt16 result = M4OSA_FALSE; + M4OSA_FileContext* pFileContext = context; + + M4OSA_DEBUG_IF2(M4OSA_NULL == context, M4ERR_PARAMETER, + "M4OSA_fileExtrafTruncate: context is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == length, M4ERR_PARAMETER, + "M4OSA_fileExtrafTruncate: length is M4OSA_NULL"); + + result = ftruncate(pFileContext->file_desc->_file, length); + + if(result != 0) + { + err = errno; + M4OSA_TRACE1_1("SetEndOfFile returns err: 0x%x\n", err); + return M4OSA_ERR_CREATE(M4_ERR, M4OSA_FILE_EXTRA, err); + } + return M4NO_ERROR; +} + + diff --git a/libvideoeditor/osal/src/M4OSA_FileReader.c b/libvideoeditor/osal/src/M4OSA_FileReader.c new file mode 100755 index 0000000..be3bb37 --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_FileReader.c @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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.c + * @author Cedric Lecoutre (cedric.lecoutre@philips.com) + * Laurent Fay (laurent.fay@philips.com) + * @par Org: Philips Digital Systems Laboratories - Paris (PDSL-P) + * @brief File reader for Android + * @note This file implements functions to read a file. + ************************************************************************ +*/ + + +#include "M4OSA_Debug.h" +#include "M4OSA_FileCommon_priv.h" +#include "M4OSA_FileReader.h" +#include "M4OSA_FileReader_priv.h" +#include "M4OSA_Memory.h" + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE +#include "M4OSA_Semaphore.h" +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + +/** +************************************************************************ +* @brief This function opens the provided URL and returns its context. +* If an error occured, the context is set to NULL. +* @param context: (OUT) Context of the core file reader +* @param url: (IN) URL of the input file +* @param fileModeAccess: (IN) File mode access +* @return M4NO_ERROR: there is no error +* @return M4ERR_PARAMETER: at least one parameter is NULL +* @return M4ERR_ALLOC: there is no more memory available +* @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported +* file +* @return M4ERR_FILE_NOT_FOUND: the file cannot be found +* @return M4ERR_FILE_LOCKED: the file is locked by an other +* application/process +* @return M4ERR_FILE_BAD_MODE_ACCESS: the file mode access is not correct +************************************************************************ +*/ +M4OSA_ERR M4OSA_fileReadOpen(M4OSA_Context* pContext, M4OSA_Void* pFileDescriptor, + M4OSA_UInt32 fileModeAccess) +{ + M4OSA_TRACE1_3("M4OSA_fileReadOpen : pC = 0x%p fd = 0x%p mode = %lu", + pContext, pFileDescriptor, fileModeAccess); + + return M4OSA_fileCommonOpen(M4OSA_FILE_READER, pContext, + pFileDescriptor, fileModeAccess); +} + +/** +************************************************************************ +* @brief This function reads the 'size' bytes in the core file reader +* (selected by its 'context') and writes the data to the 'data' +* pointer. +* @note If 'size' byte cannot be read in the core file reader, 'size' +* parameter is updated to match the correct +* @note number of read bytes. +* @param context: (IN/OUT) Context of the core file reader +* @param buffer: (OUT) Data pointer of the read data +* @param size: (IN/OUT) Size of the data to read (in bytes) +* @return M4NO_ERROR: there is no error +* @return M4ERR_PARAMETER: at least one parameter is NULL +* @return M4ERR_BAD_CONTEXT: provided context is not a valid one +* @return M4ERR_ALLOC: there is no more memory available +* @return M4WAR_NO_DATA_YET: there is no enough data to fill the 'data' +* buffer, so the size parameter has been updated. +************************************************************************ +*/ +M4OSA_ERR M4OSA_fileReadData(M4OSA_Context pContext, M4OSA_MemAddr8 data, + M4OSA_UInt32* pSize) +{ + M4OSA_FileContext* pFileContext = pContext; + M4OSA_ERR err = M4NO_ERROR; + M4OSA_Int32 uiSizeRead; + + M4OSA_TRACE2_2("M4OSA_fileReadData : data = 0x%p size = %lu", + data, (M4OSA_NULL != pSize) ? (*pSize) : 0); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileReadData: pContext is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == data, M4ERR_PARAMETER, + "M4OSA_fileReadData: data is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pSize, M4ERR_PARAMETER, + "M4OSA_fileReadData: pSize is M4OSA_NULL"); +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, + M4ERR_BAD_CONTEXT, "M4OSA_fileReadData: semaphore_context is M4OSA_NULL"); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + if(M4OSA_kDescRWAccess == pFileContext->m_DescrModeAccess) /* read write */ + { + uiSizeRead = fread(data, sizeof(M4OSA_Char), *pSize, + pFileContext->file_desc); + if(-1 == uiSizeRead) + { + /* handle is invalid, or the file is not open for reading, or the file is locked */ + *pSize = 0; + err = M4ERR_BAD_CONTEXT; + } + else + { + M4OSA_FPOS_ADD_CONST_UINT32(pFileContext->read_position, + pFileContext->read_position, uiSizeRead); + if ((M4OSA_UInt32)uiSizeRead < *pSize) + { + *pSize = uiSizeRead; + /* This is the end of file */ + pFileContext->b_is_end_of_file = M4OSA_TRUE; + err = M4WAR_NO_DATA_YET; + } + else + { + *pSize = uiSizeRead; + } + } + + return err; + } + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + if(pFileContext->current_seek != SeekRead) + { + /* fseek to the last read position */ + err = M4OSA_fileCommonSeek(pContext, M4OSA_kFileSeekBeginning, + &(pFileContext->read_position)); + if(M4OSA_ERR_IS_ERROR(err)) + { + M4OSA_DEBUG(err, "M4OSA_fileReadData: M4OSA_fileCommonSeek"); + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return err; + } + + pFileContext->current_seek = SeekRead; + } + + /* Read data */ + uiSizeRead = fread(data, sizeof(M4OSA_Char), *pSize, + pFileContext->file_desc); + if(-1 == uiSizeRead) + { + /* handle is invalid, or the file is not open for reading, + or the file is locked */ + *pSize = 0; + err = M4ERR_BAD_CONTEXT; + } + else + { + M4OSA_FPOS_ADD_CONST_UINT32(pFileContext->read_position, + pFileContext->read_position, uiSizeRead); + if ((M4OSA_UInt32)uiSizeRead < *pSize) + { + *pSize = uiSizeRead; + + /* This is the end of file */ + pFileContext->b_is_end_of_file = M4OSA_TRUE; + + err = M4WAR_NO_DATA_YET; + } + else + { + *pSize = uiSizeRead; + } + } + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + + return err; +} + + +/** +************************************************************************ + * @brief This function 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, from + * the end or from the current postion. To support large file + * access (more than 2GBytes), the position is provided on a 64 + * bits. + * @note If this function returns an error the current position pointer + * in the file must not change. Else the current + * position pointer must be updated. + * @param context: (IN/OUT) Context of the core file reader + * @param seekMode: (IN) Seek access mode + * @param position: (IN/OUT) Position in the file + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_FILE_INVALID_POSITION: the position cannot be reached + ************************************************************************ +*/ + +M4OSA_ERR M4OSA_fileReadSeek(M4OSA_Context pContext, M4OSA_FileSeekAccessMode seekMode, + M4OSA_FilePosition* pPosition) +{ + M4OSA_FileContext* pFileContext = (M4OSA_FileContext*)pContext; + M4OSA_ERR err; + + M4OSA_TRACE2_2("M4OSA_fileReadSeek : mode = %d pos = %lu", seekMode, + (pPosition != M4OSA_NULL) ? (*pPosition) : 0); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileReadSeek: pContext is M4OSA_NULL"); + M4OSA_DEBUG_IF2(0 == seekMode, M4ERR_PARAMETER, + "M4OSA_fileReadSeek: seekMode is 0"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pPosition, M4ERR_PARAMETER, + "M4OSA_fileReadSeek: pPosition is M4OSA_NULL"); +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, + M4ERR_BAD_CONTEXT, "M4OSA_fileReadSeek: semaphore_context is M4OSA_NULL"); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + if (M4OSA_kDescRWAccess == pFileContext->m_DescrModeAccess) + { + M4OSA_UInt32 SeekModeOption; + /* Go to the desired position */ + if (M4OSA_kFileSeekBeginning == seekMode) + { + SeekModeOption = SEEK_SET; + } + else if (M4OSA_kFileSeekEnd == seekMode) + { + SeekModeOption = SEEK_END; + } + else if (M4OSA_kFileSeekCurrent == seekMode) + { + SeekModeOption = SEEK_CUR; + } + else + { + M4OSA_TRACE1_0("M4OSA_fileReadSeek: END WITH ERROR !!! (CONVERION ERROR FOR THE SEEK MODE)"); + return M4ERR_PARAMETER; + } + + /** + * Go to the desired position */ + err = fseek(pFileContext->file_desc, *pPosition, SeekModeOption); + if(err != 0) + { + /* converts the error to PSW format*/ + err=((M4OSA_UInt32)(M4_ERR)<<30)+(((M4OSA_FILE_WRITER)&0x003FFF)<<16)+(M4OSA_Int16)(err); + M4OSA_TRACE1_1("M4OSA_FileReadSeek error:%x",err); + } + else + { + return M4NO_ERROR; + } + + /* Return without error */ + return err; + } + + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + if(pFileContext->current_seek != SeekRead) + { + + /* fseek to the last read position */ + err = M4OSA_fileCommonSeek(pContext, M4OSA_kFileSeekBeginning, + &(pFileContext->read_position)); + if(M4OSA_ERR_IS_ERROR(err)) + { + M4OSA_DEBUG(err, "M4OSA_fileReadData: M4OSA_fileCommonSeek"); + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return err; + } + + pFileContext->current_seek = SeekRead; + } + + err = M4OSA_fileCommonSeek(pContext, seekMode, pPosition); + if(M4OSA_ERR_IS_ERROR(err)) + { + M4OSA_DEBUG(err, "M4OSA_fileReadData: M4OSA_fileCommonSeek"); + } + else + { + M4OSA_FPOS_SET(pFileContext->read_position, *pPosition); + } + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return err; +} + + +/** + ************************************************************************ + * @brief This function asks the core file reader to close the file + * (associated to the context). + * @note The context of the core file reader is freed. + * @param pContext: (IN/OUT) Context of the core file reader + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileReadClose(M4OSA_Context pContext) +{ + M4OSA_FileContext* pFileContext = (M4OSA_FileContext*)pContext; + + M4OSA_TRACE1_1("M4OSA_fileReadClose : pC = 0x%p", pContext); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileReadClose: pContext is M4OSA_NULL"); + + if(M4OSA_FILE_WRITER == pFileContext->coreID_write) + { + return M4NO_ERROR; + } + + return M4OSA_fileCommonClose(M4OSA_FILE_READER, pContext); +} + + + + +/** + ************************************************************************ + * @brief This function 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 'value' must be cast according to the type related to the + * optionID As the caller is responsible for + * allocating/de-allocating the 'value' field, the callee must copy + * this field to its internal variable. + * @param pContext: (IN/OUT) Context of the core file reader + * @param pOptionID: (IN) ID of the option + * @param pOptionValue: (OUT) Value of the option + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_BAD_OPTION_ID: the optionID is not a valid one + * @return M4ERR_WRITE_ONLY: this option is a write only one + * @return M4ERR_NOT_IMPLEMENTED: this option is not implemented + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileReadGetOption(M4OSA_Context pContext, M4OSA_FileReadOptionID optionID, + M4OSA_DataOption* pOptionValue) +{ + M4OSA_FileContext* pFileContext = pContext; + + M4OSA_TRACE2_1("M4OSA_fileReadGetOption : option = 0x%x", optionID); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileReadGetOption: pContext is M4OSA_NULL"); + M4OSA_DEBUG_IF2(optionID == 0, M4ERR_PARAMETER, + "M4OSA_fileReadGetOption: optionID is 0"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pOptionValue, M4ERR_PARAMETER, + "M4OSA_fileReadGetOption: pOptionValue is M4OSA_NULL"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_FILE_READER), + M4ERR_BAD_OPTION_ID, "M4OSA_fileReadGetOption"); + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_READABLE(optionID), + M4ERR_WRITE_ONLY, "M4OSA_fileReadGetOption"); +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, + M4ERR_BAD_CONTEXT, + "M4OSA_fileReadGetOption: semaphore_context is M4OSA_NULL"); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + switch(optionID) + { +#if(M4OSA_OPTIONID_FILE_READ_GET_FILE_POSITION == M4OSA_TRUE) + case M4OSA_kFileReadGetFilePosition: + { + M4OSA_FilePosition* pPosition = (M4OSA_FilePosition*)pOptionValue; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + *pPosition = pFileContext->read_position; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_FILE_READ_GET_FILE_POSITION*/ + +#if(M4OSA_OPTIONID_FILE_READ_IS_EOF == M4OSA_TRUE) + case M4OSA_kFileReadIsEOF: + { + M4OSA_Bool* bIsEndOfFile = (M4OSA_Bool*)pOptionValue; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + *bIsEndOfFile = pFileContext->b_is_end_of_file; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_FILE_READ_IS_EOF*/ + + +#if(M4OSA_OPTIONID_FILE_READ_GET_FILE_SIZE == M4OSA_TRUE) + case M4OSA_kFileReadGetFileSize: + { + M4OSA_FilePosition* pPosition = (M4OSA_FilePosition*)pOptionValue; + M4OSA_Int32 iSavePos = 0; + M4OSA_Int32 iSize = 0; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + /** + * Bugfix: update the file size. + * When a file is in read mode, may be another application is writing in. + * So, we have to update the file size */ + iSavePos = ftell(pFileContext->file_desc); /*1- Check the first position */ + fseek(pFileContext->file_desc, 0, SEEK_END); /*2- Go to the end of the file */ + iSize = ftell(pFileContext->file_desc); /*3- Check the file size*/ + fseek(pFileContext->file_desc, iSavePos, SEEK_SET); /*4- go to the first position*/ + pFileContext->file_size = iSize; + + *pPosition = pFileContext->file_size; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_FILE_READ_GET_FILE_SIZE*/ + +#if(M4OSA_OPTIONID_FILE_READ_GET_FILE_ATTRIBUTE == M4OSA_TRUE) + case M4OSA_kFileReadGetFileAttribute: + { + return M4OSA_fileCommonGetAttribute(pContext, + (M4OSA_FileAttribute*)pOptionValue); + } +#endif /*M4OSA_OPTIONID_FILE_READ_GET_FILE_ATTRIBUTE*/ + +#if(M4OSA_OPTIONID_FILE_READ_GET_URL == M4OSA_TRUE) + case M4OSA_kFileReadGetURL: + { + return M4OSA_fileCommonGetURL(pContext, (M4OSA_Char**)pOptionValue); + } +#endif /*M4OSA_OPTIONID_FILE_READ_GET_URL*/ + + case M4OSA_kFileReadLockMode: + { + *(M4OSA_UInt32*)pOptionValue = pFileContext->m_uiLockMode; + return M4NO_ERROR; + } + } + + M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_fileReadGetOption"); + + return M4ERR_NOT_IMPLEMENTED; +} + +/** + ************************************************************************ + * @fn M4OSA_ERR M4OSA_fileReadSetOption (M4OSA_Context context, + * M4OSA_OptionID optionID, M4OSA_DataOption optionValue)) + * @brief This function asks the core file reader to set the value associated with the optionID. + * The caller is responsible for allocating/de-allocating the memory of the value field. + * @note As the caller is responsible for allocating/de-allocating the 'value' field, the callee must copy this field + * to its internal variable. + * @param pContext: (IN/OUT) Context of the core file reader + * @param optionID: (IN) ID of the option + * @param value: (IN) Value of the option + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_BAD_OPTION_ID: the optionID is not a valid one + * @return M4ERR_READ_ONLY: this option is a read only one + * @return M4ERR_NOT_IMPLEMENTED: this option is not implemented + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileReadSetOption(M4OSA_Context pContext, + M4OSA_FileReadOptionID optionID, + M4OSA_DataOption optionValue) +{ + M4OSA_FileContext* pFileContext = pContext; + + M4OSA_TRACE2_1("M4OSA_fileReadSetOption : option = 0x%x", optionID); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileReadSetOption: pContext is M4OSA_NULL"); + M4OSA_DEBUG_IF2(0 == optionID, M4ERR_PARAMETER, + "M4OSA_fileReadSetOption"); + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_FILE_READER), + M4ERR_BAD_OPTION_ID, "M4OSA_fileReadSetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_WRITABLE(optionID), + M4ERR_READ_ONLY, "M4OSA_fileReadSetOption"); +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, + M4ERR_BAD_CONTEXT, + "M4OSA_fileReadSetOption: semaphore_context is M4OSA_NULL"); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + switch(optionID) + { + case M4OSA_kFileReadLockMode: + { + pFileContext->m_uiLockMode= (M4OSA_UInt32)*(M4OSA_UInt32*)optionValue; + return M4NO_ERROR; + } + default: + M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_fileReadSetOption"); + return M4ERR_NOT_IMPLEMENTED; + } +} + diff --git a/libvideoeditor/osal/src/M4OSA_FileReader_RAM.c b/libvideoeditor/osal/src/M4OSA_FileReader_RAM.c new file mode 100755 index 0000000..24acfaa --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_FileReader_RAM.c @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_FileReaderRam.c + * @ingroup OSAL + * @brief File reader from RAM + * @note This file implements functions to read a "file" stored in RAM. + * @date - 2004-05-11: creation + ****************************************************************************** +*/ + +#include "M4OSA_Debug.h" +#include "M4OSA_FileReaderRam.h" +#include "M4OSA_Memory.h" + +/** + ****************************************************************************** + * structure M4OSA_FileReaderRam_Context + * @brief This structure defines the File reader in Ram context (private) + * @note This structure is used for all File Reader calls to store the context + ****************************************************************************** +*/ +typedef struct +{ + M4OSA_MemAddr8 pFileDesc; /* Pointer on file data */ + M4OSA_UInt32 dataSize; /* Size of data to read */ + M4OSA_UInt32 dataOffset; /* Actual offset */ + M4OSA_Bool IsOpened; /* Micro state machine */ +} M4OSA_FileReaderRam_Context; + +/** + ****************************************************************************** + * @brief This function sets the read pointer at the provided adress and + * returns a context. + * If an error occured, the context is set to NULL. + * @param context: (OUT) Context of the core file reader + * @param url: (IN) URL of the input file + * @param fileModeAccess: (IN) File mode access + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + * @return M4ERR_FILE_NOT_FOUND: the file cannot be found + * @return M4ERR_FILE_LOCKED: the file is locked by an other + * application/process + * @return M4ERR_FILE_BAD_MODE_ACCESS: the file mode access is not correct + ****************************************************************************** +*/ +M4OSA_ERR M4OSA_fileReadRamOpen( M4OSA_Context* context, + M4OSA_Void* fileDescriptor, + M4OSA_UInt32 fileModeAccess ) +{ + M4OSA_FileReaderRam_Context* pContext=M4OSA_NULL; + M4OSA_FileReaderRam_Descriptor* pDescriptor=fileDescriptor; + M4OSA_ERR err = M4NO_ERROR; + + M4OSA_TRACE3_3("M4OSA_fileReadRamOpen\t\tM4OSA_Context* 0x%x\tM4OSA_Void* 0x%x" + "\tM4OSA_UInt32 %d", context, fileDescriptor, + fileModeAccess); + + /* Check input parameters */ + if(M4OSA_NULL == context) + { + return M4ERR_PARAMETER; + } + *context = M4OSA_NULL; + if(M4OSA_NULL == fileDescriptor) + { + return M4ERR_PARAMETER; + } + + /* Allocates memory for the context */ + pContext = (M4OSA_FileReaderRam_Context*)M4OSA_malloc(sizeof(M4OSA_FileReaderRam_Context), + M4OSA_FILE_READER, (M4OSA_Char*)"Context allocation"); + if(pContext == M4OSA_NULL) + { + return M4ERR_ALLOC; + } + + /* Verify access mode */ + if (((fileModeAccess & M4OSA_kFileAppend) != 0) + ||(0 == (fileModeAccess & M4OSA_kFileRead))) + { + err=M4ERR_FILE_BAD_MODE_ACCESS; + goto cleanup; + } + + /* Open file in read mode and in binary/text mode with/without creation right */ + if((fileModeAccess & M4OSA_kFileCreate) != 0) + { + err=M4ERR_FILE_BAD_MODE_ACCESS; + } + else + { + if ((fileModeAccess & M4OSA_kFileRead)) + { + pContext->pFileDesc = (M4OSA_MemAddr8)(pDescriptor->pFileDesc); + pContext->dataSize = (M4OSA_Int32)(pDescriptor->dataSize); + pContext->dataOffset = 0; + pContext->IsOpened = M4OSA_TRUE; + } + else + { + err=M4ERR_FILE_BAD_MODE_ACCESS; + } + } + +cleanup: + if(err != M4NO_ERROR) + { + if(pContext != M4OSA_NULL) + { + M4OSA_free((M4OSA_MemAddr32)pContext); + *context = M4OSA_NULL; + } + } + else + { + *context = pContext; + } + return err; +} + +/** + ****************************************************************************** + * @brief This function reads the 'size' bytes in memory + * (selected by its 'context') and writes the data to the 'data' + * pointer. + * @note If 'size' byte cannot be read in the core file reader, 'size' + * parameter is updated to match the correct + * number of read bytes. + * @param context: (IN/OUT) Context of the core file reader + * @param data: (OUT) Data pointer of the read data + * @param size: (IN/OUT) Size of the data to read (in bytes) + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + * @return M4WAR_NO_DATA_YET: there is no enough data to fill the 'data' + * buffer, so the size parameter has been updated. + ****************************************************************************** +*/ +M4OSA_ERR M4OSA_fileReadRamData( M4OSA_Context context, M4OSA_MemAddr8 data, + M4OSA_UInt32* pSize ) +{ + M4OSA_FileReaderRam_Context* pContext=(M4OSA_FileReaderRam_Context*)context; + M4OSA_UInt32 aSize = *pSize; + M4OSA_ERR err = M4NO_ERROR; + + /* Check input parameters */ + if(context == M4OSA_NULL || data == M4OSA_NULL || pSize == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + if (pContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; + } + + /* Check if there is enough data to read or not */ + if((pContext->dataOffset + aSize) > pContext->dataSize) + { + aSize = pContext->dataSize - pContext->dataOffset; + M4OSA_memcpy(data, (pContext->pFileDesc + pContext->dataOffset), aSize); + *pSize = aSize; + err = M4WAR_NO_DATA_YET; + } + else + { + M4OSA_memcpy(data, (pContext->pFileDesc + pContext->dataOffset), aSize); + err = M4NO_ERROR; + } + + pContext->dataOffset += aSize; + return err; +} + +/** + ****************************************************************************** + * @brief This function 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, from + * the end or from the current postion. + * @note If this function returns an error the current position pointer + * in the file must not change. Else the current + * position pointer must be updated. + * @param context: (IN/OUT) Context of the core file reader + * @param seekMode: (IN) Seek access mode + * @param position: (IN/OUT) Position in the file + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_FILE_INVALID_POSITION: the position cannot be reached + ****************************************************************************** +*/ +M4OSA_ERR M4OSA_fileReadRamSeek( M4OSA_Context context, + M4OSA_FileSeekAccessMode seekMode, + M4OSA_FilePosition* position ) +{ + M4OSA_FileReaderRam_Context* pContext=(M4OSA_FileReaderRam_Context*)context; + M4OSA_ERR err = M4NO_ERROR; + + /* Check input parameters */ + if(context == M4OSA_NULL || seekMode == M4OSA_NULL || position == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + if (pContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; + } + + /* */ + switch(seekMode) + { + case M4OSA_kFileSeekBeginning: + /* Check if position is reachable and update dataOffset */ + if(((M4OSA_UInt32)(*position) <= pContext->dataSize) && (*position >= 0)) + { + pContext->dataOffset = *position; + *position = pContext->dataOffset; + err = M4NO_ERROR; + } + else + { + err = M4ERR_FILE_INVALID_POSITION; + } + break; + + case M4OSA_kFileSeekEnd: + /* Check if position is reachable and update dataOffset */ + if(((M4OSA_Int32)(pContext->dataSize) + *position >= 0) && (*position <= 0)) + { + pContext->dataOffset = pContext->dataSize + *position; + *position = pContext->dataOffset; + err = M4NO_ERROR; + } + else + { + err = M4ERR_FILE_INVALID_POSITION; + } + break; + + case M4OSA_kFileSeekCurrent: + /* Check if position is reachable and update dataOffset */ + if((*position + (M4OSA_Int32)(pContext->dataOffset) >= 0) && + (*position + (M4OSA_Int32)(pContext->dataOffset) <= + (M4OSA_Int32)pContext->dataSize)) + { + pContext->dataOffset += *position; + *position = pContext->dataOffset; + err = M4NO_ERROR; + } + else + { + err = M4ERR_FILE_INVALID_POSITION; + } + break; + + default: + err = M4ERR_PARAMETER; + break; + } + + return err; +} + +/** + ****************************************************************************** + * @brief This function asks the core file reader to close the file + * (associated to the context). + * @note The context of the core file reader is freed. + * @param context: (IN/OUT) Context of the core file reader + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + ****************************************************************************** +*/ +M4OSA_ERR M4OSA_fileReadRamClose(M4OSA_Context context) +{ + M4OSA_FileReaderRam_Context* pContext=(M4OSA_FileReaderRam_Context*)context; + + /* Check input parameters */ + if(context == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + if (pContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; + } + + pContext->IsOpened = M4OSA_FALSE; + + M4OSA_free((M4OSA_MemAddr32)pContext); + + return M4NO_ERROR; +} + +/** + ****************************************************************************** + * @brief This function 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 'value' must be cast according to the type related to the + * optionID As the caller is responsible for + * allocating/de-allocating the 'value' field, the callee must copy + * this field to its internal variable. + * @param context: (IN/OUT) Context of the core file reader + * @param optionID: (IN) ID of the option + * @param value: (OUT) Value of the option + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_BAD_OPTION_ID: the optionID is not a valid one + * @return M4ERR_NOT_IMPLEMENTED: this option is not implemented + ****************************************************************************** +*/ +M4OSA_ERR M4OSA_fileReadRamGetOption( M4OSA_Context context, + M4OSA_FileReadOptionID optionID, + M4OSA_DataOption* optionValue ) +{ + M4OSA_FileReaderRam_Context* pContext=(M4OSA_FileReaderRam_Context*)context; + M4OSA_ERR err=M4NO_ERROR; + + /* Check input parameters */ + if(context == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + if (pContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; + } + + switch(optionID) + { + case M4OSA_kFileReadGetFileSize: + (*(M4OSA_UInt32 *)optionValue) = (pContext->dataSize); + break; + + case M4OSA_kFileReadIsEOF: + if(pContext->dataOffset == pContext->dataSize) + { + (*(M4OSA_UInt8 *)optionValue) = M4OSA_TRUE; + } + else + { + (*(M4OSA_UInt8 *)optionValue) = M4OSA_FALSE; + } + break; + + case M4OSA_kFileReadGetFileAttribute: + err = M4ERR_NOT_IMPLEMENTED; + break; + + case M4OSA_kFileReadGetURL: + err = M4ERR_NOT_IMPLEMENTED; + break; + + case M4OSA_kFileReadGetFilePosition : + (*(M4OSA_UInt32 *)optionValue) = pContext->dataOffset; + break; + + default: + err = M4ERR_BAD_OPTION_ID; + M4OSA_TRACE1_1("M4OSA_fileReadRamGetOption invalid option ID 0x%x", + optionID); + break; + } + + return err; +} + +/** + *************************************************************************** + * @fn M4OSA_ERR M4OSA_fileReadSetOption (M4OSA_Context context, + * M4OSA_OptionID optionID, + * M4OSA_DataOption optionValue)) + * @brief This function asks the core file reader to set the value associated with the optionID. + * The caller is responsible for allocating/de-allocating the memory of the value field. + * @note As the caller is responsible for allocating/de-allocating the 'value' field, the callee must copy this field + * to its internal variable. + * @param context: (IN/OUT) Context of the core file reader + * @param optionID: (IN) ID of the option + * @param value: (IN) Value of the option + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_BAD_OPTION_ID: the optionID is not a valid one + * @return M4ERR_READ_ONLY: this option is a read only one + * @return M4ERR_NOT_IMPLEMENTED: this option is not implemented + *************************************************************************** +*/ +M4OSA_ERR M4OSA_fileReadRamSetOption( M4OSA_Context context, + M4OSA_FileReadOptionID optionID, + M4OSA_DataOption optionValue ) +{ + return M4ERR_NOT_IMPLEMENTED; +} + diff --git a/libvideoeditor/osal/src/M4OSA_FileWriter.c b/libvideoeditor/osal/src/M4OSA_FileWriter.c new file mode 100755 index 0000000..1fc73dc --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_FileWriter.c @@ -0,0 +1,577 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_FileWriter.c + * @brief File writer for Android + * @note This file implements functions to write in a file. + ************************************************************************ +*/ + +#include "M4OSA_Debug.h" +#include "M4OSA_FileCommon_priv.h" +#include "M4OSA_FileWriter.h" +#include "M4OSA_FileWriter_priv.h" +#include "M4OSA_Memory.h" + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE +#include "M4OSA_Semaphore.h" +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + +/** + ************************************************************************ + * @brief This function opens the provided URL and returns its context. + * If an error occured, the context is set to NULL. + * @param pContext: (OUT) Context of the core file writer + * @param pUrl: (IN) URL of the input file + * @param fileModeAccess: (IN) File mode access + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported + * file + * @return M4ERR_FILE_NOT_FOUND: the file cannot be found + * @return M4ERR_FILE_LOCKED: the file is locked by an other + * application/process + * @return M4ERR_FILE_BAD_MODE_ACCESS: the file mode access is not correct + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileWriteOpen(M4OSA_Context* pContext, M4OSA_Void* pUrl, + M4OSA_UInt32 fileModeAccess) +{ + M4OSA_TRACE1_3("M4OSA_fileWriteOpen : pC = 0x%p fd = 0x%p mode = %d", + pContext, pUrl, fileModeAccess); + + return M4OSA_fileCommonOpen(M4OSA_FILE_WRITER, pContext, pUrl, + fileModeAccess); +} + + +/** + ************************************************************************ + * @brief This function writes the 'size' bytes stored at 'data' memory + * in the file selected by its context. + * @note The caller is responsible for allocating/de-allocating the + * memory for 'data' parameter. + * @note Moreover the data pointer must be allocated to store at least + * 'size' bytes. + * @param pContext: (IN/OUT) Context of the core file reader + * @param buffer: (IN) Data pointer of the write data + * @param size: (IN) Size of the data to write (in bytes) + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileWriteData(M4OSA_Context pContext, M4OSA_MemAddr8 data, + M4OSA_UInt32 uiSize) +{ + M4OSA_FileContext* pFileContext = pContext; + M4OSA_ERR err; + M4OSA_UInt32 uiSizeWrite; + + M4OSA_TRACE2_2("M4OSA_fileWriteData : data = 0x%p size = %lu", data, + uiSize); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileWriteData: pContext is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_NULL == data, M4ERR_PARAMETER, + "M4OSA_fileWriteData: data is M4OSA_NULL"); + M4OSA_DEBUG_IF2(0 == uiSize, M4ERR_PARAMETER, + "M4OSA_fileWriteData: uiSize is 0"); +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, + M4ERR_BAD_CONTEXT, + "M4OSA_fileWriteData: semaphore_context is M4OSA_NULL"); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + if (M4OSA_kDescRWAccess == pFileContext->m_DescrModeAccess) + { + M4OSA_UInt32 WriteSize; + err = M4NO_ERROR; + WriteSize = fwrite((void *)data,1, uiSize, pFileContext->file_desc); + if(WriteSize != uiSize) + { + /* converts the error to PSW format*/ + err = ((M4OSA_UInt32)(M4_ERR)<<30)+(((M4OSA_FILE_WRITER)&0x003FFF)<<16)+(M4OSA_Int16)(WriteSize); + M4OSA_TRACE1_1("M4OSA_FileWriteData error:%x",err); + } + fflush(pFileContext->file_desc); + + M4OSA_FPOS_ADD_CONST_UINT32(pFileContext->write_position, pFileContext->write_position, WriteSize); + + /* Update the file size */ + if(M4OSA_FPOS_COMPARE(pFileContext->write_position, pFileContext->file_size) > 0) + { + M4OSA_FPOS_SET(pFileContext->file_size, pFileContext->write_position); + } + return err; + } + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + if(pFileContext->current_seek != SeekWrite) + { + /* fseek to the last read position */ + err = M4OSA_fileCommonSeek(pContext, M4OSA_kFileSeekBeginning, + &(pFileContext->write_position)); + + if(M4OSA_ERR_IS_ERROR(err)) + { +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + M4OSA_DEBUG(err, "M4OSA_fileWriteData: M4OSA_fileCommonSeek"); + return err; + } + + pFileContext->current_seek = SeekWrite; + } + + /* Write data */ + uiSizeWrite = fwrite(data, sizeof(M4OSA_Char), uiSize, pFileContext->file_desc); + + if(uiSizeWrite == (M4OSA_UInt32)-1) + { +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + /* An error occured */ + + M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_fileWriteData: fwrite failed"); + return M4ERR_BAD_CONTEXT; + } + + M4OSA_FPOS_ADD_CONST_UINT32(pFileContext->write_position, + pFileContext->write_position, + uiSizeWrite); + + /* Update the file size */ + if(M4OSA_FPOS_COMPARE(pFileContext->write_position, pFileContext->file_size) > 0) + { + M4OSA_FPOS_SET(pFileContext->file_size, pFileContext->write_position); + } + + if((M4OSA_UInt32)uiSizeWrite < uiSize) + { +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileWriteData"); + return M4ERR_ALLOC; + } + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return M4NO_ERROR; +} + + +/** + ************************************************************************ + * @brief This function seeks at the provided position in the core file + * writer (selected by its 'context'). The position is related to + * the seekMode parameter it can be either from the beginning, + * from the end or from the current postion. To support large file + * access (more than 2GBytes), the position is provided on a 64 + * bits. + * @note If this function returns an error the current position pointer + * in the file must not change. Else the current position pointer + * must be updated. + * @param pContext: (IN/OUT) Context of the core file reader + * @param seekMode: (IN) Seek access mode + * @param position: (IN/OUT) Position in the file + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available + * @return M4ERR_FILE_INVALID_POSITION: the position cannot be reached + ************************************************************************ + */ +M4OSA_ERR M4OSA_fileWriteSeek(M4OSA_Context pContext, M4OSA_FileSeekAccessMode seekMode, + M4OSA_FilePosition* pPosition) +{ + M4OSA_FileContext* pFileContext = (M4OSA_FileContext*)pContext; + M4OSA_ERR err; + + M4OSA_TRACE2_2("M4OSA_fileWriteSeek : mode = %d pos = %lu", + seekMode, (M4OSA_NULL != pPosition) ? (*pPosition) : 0); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileWriteSeek: pContext is M4OSA_NULL"); + M4OSA_DEBUG_IF2(0 == seekMode, M4ERR_PARAMETER, + "M4OSA_fileWriteSeek: seemMode is 0"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pPosition, M4ERR_PARAMETER, + "M4OSA_fileWriteSeek: pPosition is M4OSA_NULL"); +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, M4ERR_BAD_CONTEXT, + "M4OSA_fileWriteSeek: semaphore_context is M4OSA_NULL"); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + if (M4OSA_kDescRWAccess == pFileContext->m_DescrModeAccess) /* read write */ + { + M4OSA_UInt32 SeekModeOption; + /*The position for the seek mode between the SHP and the OSAl part are different */ + if (M4OSA_kFileSeekBeginning == seekMode) + { + SeekModeOption = SEEK_SET; + } + else if (M4OSA_kFileSeekEnd == seekMode) + { + SeekModeOption = SEEK_END; + } + else if (M4OSA_kFileSeekCurrent == seekMode) + { + SeekModeOption = SEEK_CUR; + } + else + { + M4OSA_TRACE1_0("M4OSA_fileWriteSeek: END WITH ERROR !!! (CONVERION ERROR FOR THE SEEK MODE) "); + return M4ERR_PARAMETER; + } + + /** + * Go to the desired position */ + err = fseek(pFileContext->file_desc,*pPosition,SeekModeOption); + if(err != 0) + { + /* converts the error to PSW format*/ + err=((M4OSA_UInt32)(M4_ERR)<<30)+(((M4OSA_FILE_WRITER)&0x003FFF)<<16)+(M4OSA_Int16)(err); + M4OSA_TRACE1_1("M4OSA_FileWriteSeek error:%x",err); + } + else + { + return M4NO_ERROR; + } + + return err; + } + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + err = M4OSA_fileCommonSeek(pContext, seekMode, pPosition); + + if(M4OSA_ERR_IS_ERROR(err)) + { + M4OSA_DEBUG(err, "M4OSA_fileWriteSeek: M4OSA_fileCommonSeek"); + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return err; + } + + M4OSA_FPOS_SET(pFileContext->write_position, *pPosition); + + pFileContext->current_seek = SeekWrite; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return M4NO_ERROR; +} + + +/** + ************************************************************************ + * @brief This function asks the core file writer to close the file + * (associated to the context). + * @note The context of the core file writer is freed. + * @param pContext: (IN/OUT) Context of the core file writer + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_ALLOC: there is no more memory available +************************************************************************ +*/ + +M4OSA_ERR M4OSA_fileWriteClose(M4OSA_Context pContext) +{ + M4OSA_FileContext* pFileContext = (M4OSA_FileContext*)pContext; + + M4OSA_TRACE1_1("M4OSA_fileWriteClose : pC = 0x%p", pContext); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileWriteClose: pContext is M4OSA_NULL"); + + return M4OSA_fileCommonClose(M4OSA_FILE_WRITER, pContext); +} + + +/** + ************************************************************************ + * @brief This function flushes the stream associated to the context. + * @param pContext: (IN/OUT) Context of the core file writer + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_fileWriteFlush(M4OSA_Context pContext) +{ + M4OSA_FileContext* pFileContext = pContext; + M4OSA_ERR err = M4NO_ERROR; + + M4OSA_TRACE2_1("M4OSA_fileWriteFlush : pC = 0x%p", pContext); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileWriteFlush: pcontext is M4OSA_NULL"); + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, M4ERR_BAD_CONTEXT, + "M4OSA_fileWriteFlush: semaphore_context is M4OSA_NULL"); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + if (fflush(pFileContext->file_desc) != 0) + { + err = M4ERR_BAD_CONTEXT; + } + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return err; +} + + +/** + ************************************************************************ + * @brief This function asks the core file writer to return the value + * associated with the optionID. + * The caller is responsible for allocating/de-allocating the + * memory of the value field. + * @note 'value' must be cast according to the type related to the + * optionID + * As the caller is responsible for allocating/de-allocating the + * 'value' field, the callee must copy this field + * to its internal variable. + * @param pContext: (IN/OUT) Context of the core file writer + * @param optionID: (IN) ID of the option + * @param value: (OUT) Value of the option + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_BAD_OPTION_ID: the optionID is not a valid one + * @return M4ERR_WRITE_ONLY: this option is a write only one + * @return M4ERR_NOT_IMPLEMENTED: this option is not implemented +************************************************************************ +*/ + +M4OSA_ERR M4OSA_fileWriteGetOption(M4OSA_Context pContext, M4OSA_OptionID optionID, + M4OSA_DataOption* pOptionValue) +{ + M4OSA_FileContext* pFileContext = pContext; + + M4OSA_TRACE2_1("M4OSA_fileWriteGetOption : option = 0x%x", optionID); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileWriteGetOption: pContext is M4OSA_NULL"); + M4OSA_DEBUG_IF2(optionID == 0, M4ERR_PARAMETER, "M4OSA_fileWriteGetOption"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pOptionValue, M4ERR_PARAMETER, + "M4OSA_fileWriteGetOption: pOtionValue is M4OSA_NULL"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_FILE_WRITER), + M4ERR_BAD_OPTION_ID, "M4OSA_fileWriteGetOption"); + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_READABLE(optionID), M4ERR_WRITE_ONLY, + "M4OSA_fileWriteGetOption"); +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, M4ERR_BAD_CONTEXT, + "M4OSA_fileWriteGetOption: semaphore_context is M4OSA_NULL"); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + switch(optionID) + { +#if(M4OSA_OPTIONID_FILE_WRITE_GET_FILE_POSITION == M4OSA_TRUE) + case M4OSA_kFileWriteGetFilePosition: + { + M4OSA_FilePosition* position = (M4OSA_FilePosition*)pOptionValue; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + *position = pFileContext->write_position; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_FILE_WRITE_GET_FILE_POSITION*/ + +#if(M4OSA_OPTIONID_FILE_WRITE_GET_FILE_SIZE == M4OSA_TRUE) + case M4OSA_kFileWriteGetFileSize: + { + M4OSA_FilePosition* position = (M4OSA_FilePosition*)pOptionValue; + + if(M4OSA_kDescRWAccess == pFileContext->m_DescrModeAccess) + { + M4OSA_Int32 iSavePos = 0; + M4OSA_Int32 iSize = 0; + + iSavePos = ftell(pFileContext->file_desc); /*1- Check the first position */ + fseek(pFileContext->file_desc, 0, SEEK_END); /*2- Go to the end of the file */ + *position = ftell(pFileContext->file_desc); /*3- Check the file size*/ + fseek(pFileContext->file_desc, iSavePos, SEEK_SET); /*4- go to the first position*/ + return M4NO_ERROR; + } + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + *position = pFileContext->file_size; + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_semaphorePost(pFileContext->semaphore_context); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_FILE_WRITE_GET_FILE_SIZE*/ + +#if(M4OSA_OPTIONID_FILE_WRITE_GET_URL == M4OSA_TRUE) + case M4OSA_kFileWriteGetURL: + { + return M4OSA_fileCommonGetURL (pContext, (M4OSA_Char**)pOptionValue); + } +#endif /*M4OSA_OPTIONID_FILE_WRITE_GET_URL*/ + +#if(M4OSA_OPTIONID_FILE_WRITE_GET_FILE_ATTRIBUTE == M4OSA_TRUE) + case M4OSA_kFileWriteGetAttribute: + { + return M4OSA_fileCommonGetAttribute(pContext, + (M4OSA_FileAttribute*)pOptionValue); + } +#endif /*M4OSA_OPTIONID_FILE_WRITE_GET_FILE_ATTRIBUTE*/ + +#if(M4OSA_OPTIONID_FILE_WRITE_GET_READER_CONTEXT == M4OSA_TRUE) + case M4OSA_kFileWriteGetReaderContext: + { + M4OSA_FileModeAccess access = pFileContext->access_mode; + + M4OSA_DEBUG_IF1(!(access & M4OSA_kFileRead), M4ERR_BAD_CONTEXT, + "M4OSA_fileWriteGetOption: M4OSA_kFileRead"); + + M4OSA_DEBUG_IF1(!(access & M4OSA_kFileWrite), M4ERR_BAD_CONTEXT, + "M4OSA_fileWriteGetOption: M4OSA_kFileWrite"); + + pFileContext->coreID_read = M4OSA_FILE_READER; + + *pOptionValue = pContext; + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_FILE_WRITE_GET_READER_CONTEXT*/ + + case M4OSA_kFileWriteLockMode: + { + *(M4OSA_UInt32*)pOptionValue = pFileContext->m_uiLockMode; + return M4NO_ERROR; + } + + } + + M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_fileWriteGetOption"); + + return M4ERR_NOT_IMPLEMENTED; +} + + +/** +************************************************************************ +* @brief This function asks the core file writer to set the value +* associated with the optionID. +* The caller is responsible for allocating/de-allocating the +* memory of the value field. +* @note As the caller is responsible for allocating/de-allocating the +* 'value' field, the callee must copy this field to its internal +* variable. +* @param pContext: (IN/OUT) Context of the core file writer +* @param optionID: (IN) ID of the option +* @param value: (IN) Value of the option +* @return M4NO_ERROR: there is no error +* @return M4ERR_PARAMETER: at least one parameter is NULL +* @return M4ERR_BAD_CONTEXT: provided context is not a valid one +* @return M4ERR_BAD_OPTION_ID: the optionID is not a valid one +* @return M4ERR_READ_ONLY: this option is a read only one +* @return M4ERR_NOT_IMPLEMENTED: this option is not implemented +************************************************************************ +*/ + +M4OSA_ERR M4OSA_fileWriteSetOption(M4OSA_Context pContext, + M4OSA_OptionID optionID, + M4OSA_DataOption optionValue) +{ + M4OSA_FileContext* pFileContext = pContext; + + M4OSA_TRACE2_1("M4OSA_fileWriteSetOption : option = 0x%x", optionID); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_fileWriteSetOption"); + + M4OSA_DEBUG_IF2(0 == optionID, M4ERR_PARAMETER, "M4OSA_fileWriteSetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_FILE_WRITER), + M4ERR_BAD_OPTION_ID, "M4OSA_fileWriteSetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_WRITABLE(optionID), M4ERR_READ_ONLY, + "M4OSA_fileReadSetOption"); + +#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE + M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, M4ERR_BAD_CONTEXT, + "M4OSA_fileWriteSetOption: semaphore_context is M4OSA_NULL"); +#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */ + + switch(optionID) + { + case M4OSA_kFileWriteLockMode: + { + pFileContext->m_uiLockMode = (M4OSA_UInt32)*(M4OSA_UInt32*)optionValue; + return M4NO_ERROR; + } + + case M4OSA_kFileWriteDescMode: + { + pFileContext->m_DescrModeAccess = (M4OSA_Int32)*(M4OSA_Int32*)optionValue; + return M4NO_ERROR; + } + + default: + return M4ERR_NOT_IMPLEMENTED; + } + + return M4ERR_NOT_IMPLEMENTED; +} + diff --git a/libvideoeditor/osal/src/M4OSA_FileWriter_RAM.c b/libvideoeditor/osal/src/M4OSA_FileWriter_RAM.c new file mode 100755 index 0000000..9341ca9 --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_FileWriter_RAM.c @@ -0,0 +1,448 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_FileReaderRam.c + + * @brief File reader from RAM + * @note This file implements functions to read a "file" stored in RAM. +****************************************************************************** +*/ + +#include "M4OSA_Debug.h" +#include "M4OSA_FileWriterRam.h" +#include "M4OSA_FileReaderRam.h" +#include "M4OSA_Memory.h" + + +/** + ****************************************************************************** + * structure M4OSA_FileWriteRam_Context + * @brief This structure defines the File writer context (private) + * @note This structure is used for all File writer calls to store the context + ****************************************************************************** +*/ +typedef struct +{ + M4OSA_MemAddr8 pFileDesc; /* Pointer on file data */ + M4OSA_UInt32 dataSize; /* Size of data to write */ + M4OSA_UInt32 dataOffset; /* Actual offset */ + M4OSA_Bool IsOpened; /* Micro state machine */ + M4OSA_UInt32 bufferSize; /* Actual used size inside the buffer */ +} M4OSA_FileWriterRam_Context; + + +/** + ****************************************************************************** + * @brief This method "opens" the provided fileDescriptor (in fact address) + * and returns its context. + * @param pContext: (OUT) File writer 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 + * @return M4ERR_FILE_NOT_FOUND The file can not be opened. + ****************************************************************************** +*/ +M4OSA_ERR M4OSA_fileWriteRamOpen(M4OSA_Context* context, M4OSA_Void* fileDescriptor, + M4OSA_UInt32 fileModeAccess) +{ + M4OSA_FileWriterRam_Context* pContext=M4OSA_NULL; + M4OSA_FileWriterRam_Descriptor* pDescriptor = fileDescriptor; + M4OSA_Int32 aFileDesc=-1; + M4OSA_ERR err=M4NO_ERROR; + + /* Check input parameters */ + if(context == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + *context = M4OSA_NULL; + if(fileDescriptor == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + + /* Allocate memory for the File writer context. */ + pContext = (M4OSA_FileWriterRam_Context *)M4OSA_malloc(sizeof(M4OSA_FileWriterRam_Context), + M4OSA_FILE_WRITER, (M4OSA_Char*)"Context allocation"); + if(pContext == M4OSA_NULL) + { + return M4ERR_ALLOC; + } + + if ((fileModeAccess & M4OSA_kFileWrite)) + { + pContext->pFileDesc = (M4OSA_MemAddr8)(pDescriptor->pFileDesc); + pContext->dataSize = (M4OSA_Int32)(pDescriptor->dataSize); + pContext->dataOffset = 0; + pContext->bufferSize = 0; + pContext->IsOpened = M4OSA_TRUE; + } + else + { + err = M4ERR_FILE_BAD_MODE_ACCESS; + } + if (M4NO_ERROR != err) + { + if (M4OSA_NULL != pContext) + { + M4OSA_free((M4OSA_MemAddr32)pContext); + } + *context=M4OSA_NULL; + } + else + { + *context = pContext; + } + + return err; +} + +/** + ****************************************************************************** + * @brief This method writes the 'size' bytes stored at 'data' memory at the end + * of the file selected by its context. + * The caller is responsible for allocating/de-allocating the memory for 'data' parameter. + * Moreover, the data pointer must be allocated to store at least 'size' bytes. + * @param pContext: (IN) File writer context. + * @param pData : (IN) Data pointer of the written data. + * @param Size : (IN) Size of the data to write (in bytes). + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER 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_fileWriteRamData(M4OSA_Context context,M4OSA_MemAddr8 data, M4OSA_UInt32 Size) +{ + M4OSA_FileWriterRam_Context* pContext=(M4OSA_FileWriterRam_Context*)context; + M4OSA_ERR err=M4NO_ERROR; + + /* Check input parameters */ + if(context == M4OSA_NULL || data == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + + if (pContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; /* The context can not be correct */ + } + + /* Check if there is enough room to write or not */ + if (pContext->dataOffset + Size < pContext->dataSize ) + { + M4OSA_memcpy((pContext->pFileDesc + pContext->dataOffset), data, Size); + pContext->dataOffset += Size; + if(pContext->dataOffset> pContext->bufferSize) pContext->bufferSize = pContext->dataOffset; + err = M4NO_ERROR; + } + else + { + err = M4ERR_FILE_INVALID_POSITION; + } + + return err; +} + +/** + ****************************************************************************** + * @brief This method seeks at the provided position in the core file writer (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_fileWriteRamSeek(M4OSA_Context context, M4OSA_FileSeekAccessMode SeekMode, + M4OSA_FilePosition* position) +{ + M4OSA_FileWriterRam_Context* pContext=(M4OSA_FileWriterRam_Context*)context; + M4OSA_ERR err=M4NO_ERROR; + + /* Check input parameters */ + if(context == M4OSA_NULL || SeekMode == M4OSA_NULL || position == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + + if (pContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; /* The context can not be correct */ + } + + /* Go to the desired position */ + switch(SeekMode) + { + case M4OSA_kFileSeekBeginning: + /* Check if position is reachable and update dataOffset */ + if (((*position) >= 0) && ((M4OSA_UInt32)(*position) <= pContext->dataSize)) + { + pContext->dataOffset = *position; + err = M4NO_ERROR; + } + else + { + err = M4ERR_FILE_INVALID_POSITION; + } + break; + + case M4OSA_kFileSeekEnd: + /* Check if position is reachable and update dataOffset */ + if ((*position) < 0) + { + if (pContext->dataSize >= (M4OSA_UInt32)(-(*position))) + { + pContext->dataOffset = (M4OSA_UInt32) (pContext->pFileDesc + pContext->dataSize + (*position)); + err = M4NO_ERROR; + } + else + { + err = M4ERR_FILE_INVALID_POSITION; + } + } + else if ((*position) == 0) + { + pContext->dataOffset = (M4OSA_UInt32)(pContext->pFileDesc + pContext->dataSize); + err = M4NO_ERROR; + } + else + { + err = M4ERR_FILE_INVALID_POSITION; + } + break; + + case M4OSA_kFileSeekCurrent: + /* Check if position is reachable and update dataOffset */ + if ((*position) < 0) + { + if (pContext->dataOffset >= (M4OSA_UInt32)(-(*position))) + { + pContext->dataOffset = (M4OSA_UInt32) (pContext->dataOffset + (*position)); + err = M4NO_ERROR; + } + else + { + err = M4ERR_FILE_INVALID_POSITION; + } + } + else + { + if (pContext->dataSize >= (M4OSA_UInt32)(pContext->dataOffset + (*position))) + { + pContext->dataOffset = (M4OSA_UInt32) (pContext->dataOffset + (*position)); + err = M4NO_ERROR; + } + else + { + err = M4ERR_FILE_INVALID_POSITION; + } + } + break; + + default: + err = M4ERR_PARAMETER; + break; + } + + return err; +} + +/** + ****************************************************************************** + * @brief This method asks the core file writer to close the file (associated to the context). + * The context of the core file reader must be freed. + * @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_fileWriteRamClose(M4OSA_Context context) +{ + M4OSA_FileWriterRam_Context* pContext=(M4OSA_FileWriterRam_Context*)context; + M4OSA_ERR err=M4NO_ERROR; + + /* Check input parameters */ + if(pContext == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + + if (pContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; /* The context can not be correct */ + } + + pContext->IsOpened = M4OSA_FALSE; + + /* Free the context */ + M4OSA_free((M4OSA_MemAddr32)pContext); + + /* Return error */ + return err; +} + +/** + ****************************************************************************** + * @brief This method asks the core file writer to flush the pending data + * to the file (associated to the context). + * All pending written data are written in the file. + * @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_fileWriteRamFlush(M4OSA_Context context) +{ + M4OSA_FileWriterRam_Context* pContext=(M4OSA_FileWriterRam_Context*)context; + + /* Check input parameters */ + if(context == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + + if (pContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; /* The context can not be correct */ + } + + /* + * DO NOTHING */ + + /** + * Return without error */ + return M4NO_ERROR; +} + +/** + ****************************************************************************** + * @brief This method asks the core file writer to set 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 OptionValue : (IN) Value of the option. + * @return M4NO_ERROR: there is no error + * @return M4ERR_BAD_CONTEXT pContext is NULL + * @return M4ERR_READ_ONLY The option is not implemented yet. + * @return M4ERR_BAD_OPTION_ID the option id is not valid. + * @return M4ERR_NOT_IMPLEMENTED The option is not implemented yet. + ****************************************************************************** +*/ +M4OSA_ERR M4OSA_fileWriteRamSetOption(M4OSA_Context context, + M4OSA_OptionID OptionID, + M4OSA_DataOption OptionValue) +{ + M4OSA_FileWriterRam_Context* pContext=(M4OSA_FileWriterRam_Context*)context; + + /* Check input parameters */ + if(context == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + + if (pContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; /**< The context can not be correct */ + } + + /* Set the desired option if it is avalaible */ + switch(OptionID) + { + case M4OSA_kFileWriteGetReaderContext : /* Get the file attribute*/ + case M4OSA_kFileWriteGetURL : /* Get the directory + name of the file */ + case M4OSA_kFileWriteGetFilePosition : /* Get file position */ + return M4ERR_READ_ONLY; + break; + + case M4OSA_kFileWriteGetAttribute : + /** + * Get the reader context for read & write file. It is NULL if the file is opened + * with write attribute only */ + return M4ERR_NOT_IMPLEMENTED; + + default : /* Bad option ID */ + return M4ERR_BAD_OPTION_ID; + } + + /* Return without error */ + return M4NO_ERROR; +} + +/** + ****************************************************************************** + * @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_ALLOC there is no more memory available + * @return M4ERR_NOT_IMPLEMENTED The option is not implemented yet. + ****************************************************************************** +*/ +M4OSA_ERR M4OSA_fileWriteRamGetOption(M4OSA_Context context, + M4OSA_OptionID OptionID, + M4OSA_DataOption* optionValue) +{ + M4OSA_FileWriterRam_Context* pContext=(M4OSA_FileWriterRam_Context*)context; + M4OSA_ERR err=M4NO_ERROR; + + /* Check input parameters */ + if(context == M4OSA_NULL) + { + return M4ERR_PARAMETER; + } + + if (pContext->IsOpened != M4OSA_TRUE) + { + return M4ERR_BAD_CONTEXT; /**< The context can not be correct */ + } + + /* Get the desired option if it is avalaible */ + switch(OptionID) + { + case M4OSA_kFileWriteGetFileSize:/* Get size of the file, limited to 32 bit size */ + (*(M4OSA_UInt32 *)optionValue) = (pContext->bufferSize); + break; + + case M4OSA_kFileWriteGetURL : /* Get the directory + name of the file */ + return M4ERR_NOT_IMPLEMENTED; + + default : /**< Bad option ID */ + return M4ERR_BAD_OPTION_ID; + break; + } + + /* Return without error */ + return err; +} diff --git a/libvideoeditor/osal/src/M4OSA_Mutex.c b/libvideoeditor/osal/src/M4OSA_Mutex.c new file mode 100755 index 0000000..0d857f6 --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_Mutex.c @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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. + */ +/** + ************************************************************************ + * @brief Mutex for Android + * @note This file implements functions to manipulate mutex + ************************************************************************ +*/ + +#include "M4OSA_Debug.h" +#include "M4OSA_Types.h" +#include "M4OSA_Error.h" +#include "M4OSA_Memory.h" +#include "M4OSA_Mutex.h" + +#include <pthread.h> +#include <errno.h> + + +/* Context for the mutex */ +typedef struct +{ + M4OSA_UInt32 coreID; /* mutex context identifiant */ + pthread_mutex_t mutex; /* mutex */ + pthread_t threadOwnerID; /* thread owner identifiant */ +} M4OSA_MutexContext; + + + +/** + ************************************************************************ + * @brief This method creates a new mutex. + * @note This function creates and allocates a unique context. It's the + * OSAL real time responsibility for managing its context. It must + * be freed by the M4OSA_mutexClose function. The context parameter + * will be sent back to any OSAL core mutex functions to allow + * retrieving data associated to the opened mutex. + * @param pContext:(OUT) Context of the created mutex + * @return M4NO_ERROR: there is no error + * @return M4ERR_ALLOC: there is no more available memory + * @return M4ERR_CONTEXT_FAILED: the context creation failed + ************************************************************************ +*/ +M4OSA_ERR M4OSA_mutexOpen(M4OSA_Context* pContext) +{ + M4OSA_MutexContext* pMutexContext = (M4OSA_MutexContext*)M4OSA_NULL; + pthread_mutexattr_t attribute = { 0 }; + M4OSA_Bool opened = M4OSA_FALSE; + + M4OSA_TRACE1_1("M4OSA_mutexOpen\t\tM4OSA_Context* 0x%x", pContext); + M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, + "M4OSA_mutexOpen: pContext is M4OSA_NULL"); + + *pContext = M4OSA_NULL; + + pMutexContext = (M4OSA_MutexContext*)M4OSA_malloc(sizeof(M4OSA_MutexContext), + M4OSA_MUTEX, (M4OSA_Char*)"M4OSA_mutexOpen: mutex context"); + + if(M4OSA_NULL == pMutexContext) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_mutexOpen"); + return M4ERR_ALLOC; + } + + /* Initialize the mutex attribute. */ + if ( 0 == pthread_mutexattr_init( &attribute ) ) + { + /* Initialize the mutex type. */ + if ( 0 == pthread_mutexattr_settype( &attribute, PTHREAD_MUTEX_RECURSIVE ) ) + { + /* Initialize the mutex. */ + if (0 == pthread_mutex_init( &pMutexContext->mutex, &attribute ) ) + { + opened = M4OSA_TRUE; + } + } + + /* Destroy the mutex attribute. */ + pthread_mutexattr_destroy( &attribute ); + } + + if(!opened) + { + M4OSA_DEBUG(M4ERR_CONTEXT_FAILED, "M4OSA_mutexOpen: OS mutex creation failed"); + M4OSA_free((M4OSA_MemAddr32)pMutexContext); + return M4ERR_CONTEXT_FAILED ; + } + + pMutexContext->coreID = M4OSA_MUTEX; + + pMutexContext->threadOwnerID = 0; + + *pContext = (M4OSA_Context) pMutexContext; + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This method locks the mutex. "Context" identifies the mutex. + * @note If the mutex is already locked, the calling thread blocks until + * the mutex becomes available (by calling M4OSA_mutexUnlock) or + * "timeout" is reached. This is a blocking call. + * @param context:(IN/OUT) Context of the mutex + * @param timeout:(IN) Time out in milliseconds + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4WAR_TIME_OUT: time out is elapsed before mutex has been + * available + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_mutexLock(M4OSA_Context context, M4OSA_UInt32 timeout) +{ + M4OSA_MutexContext* pMutexContext = (M4OSA_MutexContext*)context; + pthread_t currentThread; + int result; + struct timespec ts; + struct timespec left; + + M4OSA_TRACE1_2("M4OSA_mutexLock\t\tM4OSA_Context 0x%x\tM4OSA_UInt32 %d", + context, timeout); + + M4OSA_DEBUG_IF2(M4OSA_NULL == context, M4ERR_PARAMETER, + "M4OSA_mutexLock: context is M4OSA_NULL"); + M4OSA_DEBUG_IF2(pMutexContext->coreID != M4OSA_MUTEX, + M4ERR_BAD_CONTEXT, "M4OSA_mutexLock"); + + currentThread = pthread_self(); + + if(pMutexContext ->threadOwnerID == currentThread) + { + M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_mutexLock: Thread tried to lock a mutex it already owns"); + return M4ERR_BAD_CONTEXT ; + } + + /* Lock the mutex. */ + if ( M4OSA_WAIT_FOREVER == timeout) + { + if ( 0 != pthread_mutex_lock(&pMutexContext->mutex) ) + { + M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_mutexLock: OS mutex wait failed"); + return M4ERR_BAD_CONTEXT; + } + } + else + { + result = pthread_mutex_trylock(&pMutexContext->mutex); + while ( ( EBUSY == result ) && ( 0 < timeout ) ) + { + ts.tv_sec = 0; + if (1 <= timeout) + { + ts.tv_nsec = 1000000; + timeout -= 1; + } + else + { + ts.tv_nsec = timeout * 1000000; + timeout = 0; + } + nanosleep(&ts, &left); + result = pthread_mutex_trylock(&pMutexContext->mutex); + } + if (0 != result) + { + if (EBUSY == result) + { + return M4WAR_TIME_OUT; + } + else + { + M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_mutexLock: OS mutex wait failed"); + return M4ERR_BAD_CONTEXT; + } + } + } + + pMutexContext->threadOwnerID = currentThread; + + return M4NO_ERROR; +} + + + +/** + ************************************************************************ + * @brief This method unlocks the mutex. The mutex is identified by + * its context + * @note The M4OSA_mutexLock unblocks the thread with the highest + * priority and made it ready to run. + * @note No hypotheses can be made on which thread will be un-blocked + * between threads with the same priority. + * @param context:(IN/OUT) Context of the mutex + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one +************************************************************************ +*/ +M4OSA_ERR M4OSA_mutexUnlock(M4OSA_Context context) +{ + M4OSA_MutexContext* pMutexContext = (M4OSA_MutexContext*)context; + pthread_t currentThread; + + M4OSA_TRACE1_1("M4OSA_mutexUnlock\t\tM4OSA_Context 0x%x", context); + M4OSA_DEBUG_IF2(M4OSA_NULL == context, M4ERR_PARAMETER, + "M4OSA_mutexUnlock: context is M4OSA_NULL"); + M4OSA_DEBUG_IF2(M4OSA_MUTEX != pMutexContext->coreID, + M4ERR_BAD_CONTEXT, "M4OSA_mutexUnlock"); + + currentThread = pthread_self(); + + if(pMutexContext->threadOwnerID != currentThread) + { + M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_mutexUnlock: Thread tried to unlock a mutex it doesn't own"); + return M4ERR_BAD_CONTEXT; + } + + pMutexContext->threadOwnerID = 0 ; + + pthread_mutex_unlock(&pMutexContext->mutex); + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This method deletes a mutex (identify by its context). After + * this call, the mutex and its context is no more useable. This + * function frees all the memory related to this mutex. + * @note It is an application issue to warrant no more threads are locked + * on the deleted mutex. + * @param context:(IN/OUT) Context of the mutex + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_mutexClose(M4OSA_Context context) +{ + M4OSA_MutexContext* pMutexContext = (M4OSA_MutexContext*)context; + + M4OSA_TRACE1_1("M4OSA_mutexClose\t\tM4OSA_Context 0x%x", context); + + M4OSA_DEBUG_IF2(M4OSA_NULL == context, M4ERR_PARAMETER, + "M4OSA_mutexClose: context is M4OSA_NULL"); + M4OSA_DEBUG_IF2(pMutexContext->coreID != M4OSA_MUTEX, + M4ERR_BAD_CONTEXT, "M4OSA_mutexUnlock"); + + pthread_mutex_destroy(&pMutexContext->mutex); + + M4OSA_free((M4OSA_MemAddr32) pMutexContext); + + return M4NO_ERROR; +} + diff --git a/libvideoeditor/osal/src/M4OSA_Random.c b/libvideoeditor/osal/src/M4OSA_Random.c new file mode 100755 index 0000000..63fdf5e --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_Random.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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 M4PSW_Trace.c + * @brief Trace function for trace macros + * @note This file gives the implementation of the trace function used + * in the trace instrumentation macros + ************************************************************************ +*/ + +#include <stdio.h> /*for printf */ +#include <stdarg.h> /* ANSI C macros and defs for variable args */ +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "M4OSA_Types.h" +#include "M4OSA_Error.h" +#include "M4OSA_Memory.h" +#include "M4OSA_Mutex.h" +/** + ************************************************************************ + * @fn M4OSA_ERR M4OSA_randInit() + * @brief this function initialize the number generator + * this function must be called once before any call to M4OSA_rand() + * need the stdlib and time libraries + * @note + * @param + * @return M4NO_ERROR + ************************************************************************ +*/ + +M4OSA_ERR M4OSA_randInit() +{ + int i; + + srand(time(NULL)); + + /* Windows' rand is rotten, the first generated value after the init + above is not random enough, so let's shake things a little... */ + + for (i=0; i<100; i++) rand(); + + return M4NO_ERROR; +} +/** + ************************************************************************ + * @fn M4OSA_ERR M4OSA_rand(M4OSA_Int32* out_value, M4OSA_UInt32 max_value) + * @brief This function gives a random number between 1 and max_value + * (inclusive) with approximately equal probability, and + * returns this number in out_value. For instance, a max_value + * of 6 will simulate a fair 6-sided dice roll. + * @note + * @param out_value (OUT): on return, points to random result + * @param max_value (IN): max expected value + * @return M4NO_ERROR + ************************************************************************ +*/ + +M4OSA_ERR M4OSA_rand(M4OSA_Int32* out_value, M4OSA_UInt32 max_value) +{ + if( (out_value == M4OSA_NULL) || (max_value < 1) ) + { + return M4ERR_PARAMETER; + } + + (*out_value) = rand(); + /* notice this algorithm will only work for max_values such that the multiplication + won't overflow, which means that max_value typically shouldn't go over the range of + an Int16. */ + (*out_value) = (((*out_value) * max_value) / ((M4OSA_UInt32)RAND_MAX + 1)) + 1; + + return M4NO_ERROR; +} + + diff --git a/libvideoeditor/osal/src/M4OSA_Semaphore.c b/libvideoeditor/osal/src/M4OSA_Semaphore.c new file mode 100755 index 0000000..a99b136 --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_Semaphore.c @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_Semaphore.c + * @brief Semaphore for Windows + * @note This file implements functions to manipulate semaphore + ************************************************************************ +*/ + + + +#include "M4OSA_Debug.h" +#include "M4OSA_Types.h" +#include "M4OSA_Error.h" +#include "M4OSA_Memory.h" +#include "M4OSA_Semaphore.h" + +#include <semaphore.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <time.h> + + +/* Context for the semaphore */ +typedef struct { + M4OSA_UInt32 coreID; /* semaphore context identifiant */ + sem_t semaphore; /* semaphore */ +} M4OSA_SemaphoreContext; + + + + +/** + ************************************************************************ + * @brief This method creates a new semaphore with the "initialCounter" + * value. + * @note This function creates and allocates a unique context. It's the + * OSAL real time responsibility for managing its context. It must + * be freed by the M4OSA_semaphoreClose function. The context + * parameter will be sent back to any OSAL core semaphore functions + * to allow retrieving data associated to the opened semaphore. + * @param context:(OUT) Context of the created semaphore + * @param initial_count:(IN) Initial counter of the semaphore + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: provided context is NULL + * @return M4ERR_ALLOC: there is no more available memory + * @return M4ERR_CONTEXT_FAILED: the context creation failed + ************************************************************************ +*/ +M4OSA_ERR M4OSA_semaphoreOpen(M4OSA_Context* context, + M4OSA_UInt32 initial_count) +{ + M4OSA_SemaphoreContext* semaphoreContext = M4OSA_NULL; + + M4OSA_TRACE1_2("M4OSA_semaphoreOpen\t\tM4OSA_Context* 0x%x\tM4OSA_UInt32 " + "%d", context, initial_count); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_semaphoreOpen"); + + *context = M4OSA_NULL; + + semaphoreContext = (M4OSA_SemaphoreContext*) M4OSA_malloc( + sizeof(M4OSA_SemaphoreContext), M4OSA_SEMAPHORE, + (M4OSA_Char*)"M4OSA_semaphoreOpen: semaphore context"); + + if(semaphoreContext == M4OSA_NULL) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_semaphoreOpen"); + + return M4ERR_ALLOC; + } + + if (0 != sem_init(&semaphoreContext->semaphore, 0, initial_count)) + { + M4OSA_free((M4OSA_MemAddr32)semaphoreContext); + + M4OSA_DEBUG(M4ERR_CONTEXT_FAILED, + "M4OSA_semaphoreOpen: OS semaphore creation failed"); + + return M4ERR_CONTEXT_FAILED; + } + + semaphoreContext->coreID = M4OSA_SEMAPHORE ; + *context = (M4OSA_Context)semaphoreContext; + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This method decrements (one by one) the semaphore counter. The + * semaphore is identified by its context This call is not blocking + * if the semaphore counter is positive or zero (after + * decrementation). This call is blocking if the semaphore counter + * is less than zero (after decrementation), until the semaphore is + * upper than zero (see M4OSA_semaphorePost) or time_out is + * reached. + * @note If "timeout" value is M4OSA_WAIT_FOREVER, the calling thread + * will block indefinitely until the semaphore is unlocked. + * @param context:(IN/OUT) Context of the semaphore + * @param timeout:(IN) Time out in milliseconds + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4WAR_TIME_OUT: time out is elapsed before semaphore has been + * available. + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_semaphoreWait(M4OSA_Context context, M4OSA_Int32 timeout) +{ + M4OSA_SemaphoreContext* semaphoreContext = (M4OSA_SemaphoreContext*)context; + struct timespec ts; + struct timespec left; + int result; + + M4OSA_TRACE1_2("M4OSA_semaphoreWait\t\tM4OSA_Context 0x%x\tM4OSA_UInt32 %d", + context, timeout); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_semaphoreWait"); + + M4OSA_DEBUG_IF2(semaphoreContext->coreID != M4OSA_SEMAPHORE, + M4ERR_BAD_CONTEXT, "M4OSA_semaphoreWait"); + + if ( (M4OSA_Int32)M4OSA_WAIT_FOREVER == timeout) + { + if ( 0 != sem_wait(&semaphoreContext->semaphore) ) + { + M4OSA_DEBUG(M4ERR_BAD_CONTEXT, + "M4OSA_semaphoreWait: OS semaphore wait failed"); + + return M4ERR_BAD_CONTEXT ; + } + } + else + { + result = sem_trywait(&semaphoreContext->semaphore); + while ( ((EBUSY == result) || (EAGAIN == result)) && ( 0 < timeout ) ) + { + ts.tv_sec = 0; + if (1 <= timeout) + { + ts.tv_nsec = 1000000; + timeout -= 1; + } + else + { + ts.tv_nsec = timeout * 1000000; + timeout = 0; + } + nanosleep(&ts, &left); + result = sem_trywait(&semaphoreContext->semaphore); + } + if (0 != result) + { + if ((EBUSY == result) || (EAGAIN == result)) + { + return M4WAR_TIME_OUT; + } + else + { + M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_semaphoreWait: OS semaphore wait failed"); + return M4ERR_BAD_CONTEXT; + } + } + } + + return M4NO_ERROR; +} + + + + + +/** + ************************************************************************ + * @brief This method increments the semaphore counter. The semaphore is + * identified by its context + * @note If the semaphore counter is upper than zero (after addition), + * the M4OSA_semaphoreWait call of the thread with the highest + * priority is unblocked and made ready to run. + * @note No hypotheses can be made on which thread will be unblocked + * between threads with the same priority. + * @param context:(IN/OUT) Context of the semaphore + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one +************************************************************************ +*/ +M4OSA_ERR M4OSA_semaphorePost(M4OSA_Context context) +{ + M4OSA_SemaphoreContext* semaphoreContext = (M4OSA_SemaphoreContext*)context; + + M4OSA_TRACE1_1("M4OSA_semaphorePost\t\tM4OSA_Context 0x%x", context); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_semaphorePost"); + + M4OSA_DEBUG_IF2(semaphoreContext->coreID != M4OSA_SEMAPHORE, + M4ERR_BAD_CONTEXT, "M4OSA_semaphorePost"); + + sem_post(&semaphoreContext->semaphore); + + return M4NO_ERROR; +} + + + + + +/** + ************************************************************************ + * @brief This method deletes a semaphore (identify by its context). + * After this call the semaphore and its context is no more + * useable. This function frees all the memory related to this + * semaphore. + * @note It is an application issue to warrant no more threads are locked + * on the deleted semaphore. + * @param context:(IN/OUT) Context of the semaphore + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one. +************************************************************************ +*/ +M4OSA_ERR M4OSA_semaphoreClose(M4OSA_Context context) +{ + M4OSA_SemaphoreContext* semaphoreContext = (M4OSA_SemaphoreContext*)context; + + M4OSA_TRACE1_1("M4OSA_semaphoreClose\t\tM4OSA_Context 0x%x", context); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_semaphoreClose"); + + M4OSA_DEBUG_IF2(semaphoreContext->coreID != M4OSA_SEMAPHORE, + M4ERR_BAD_CONTEXT, "M4OSA_semaphoreClose"); + + sem_destroy(&semaphoreContext->semaphore); + + M4OSA_free((M4OSA_MemAddr32)semaphoreContext); + + return M4NO_ERROR; +} + diff --git a/libvideoeditor/osal/src/M4OSA_String.c b/libvideoeditor/osal/src/M4OSA_String.c new file mode 100755 index 0000000..af98b4b --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_String.c @@ -0,0 +1,2417 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_String.c + ************************************************************************ +*/ + +#include "M4OSA_Debug.h" +#include "M4OSA_Memory.h" +#include "M4OSA_Types.h" +#include "M4OSA_Error.h" +#include "M4OSA_CharStar.h" +#include "M4OSA_FileCommon.h" +#include "M4OSA_String_priv.h" +#include "M4OSA_String.h" + + +/** + ************************************************************************ + * @brief This function creates an empty M4OSA_String + * @note + * @param pStrOut + * @return M4OSA_ERROR + ************************************************************************ +*/ +M4OSA_ERR M4OSA_strCreate(M4OSA_String* pStrOut) +{ + M4OSA_strStruct* pStr = M4OSA_NULL; + + M4OSA_TRACE1_1("M4OSA_strCreate\t\tM4OSA_String* 0x%x", pStrOut); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStrOut, M4ERR_PARAMETER, "M4OSA_strCreate"); + M4OSA_DEBUG_IF2(M4OSA_NULL != *pStrOut, M4ERR_STR_BAD_STRING, + "M4OSA_strCreate"); + + /* Allocate the output M4OSA_String */ + pStr = (M4OSA_strStruct*)M4OSA_malloc(sizeof(M4OSA_strStruct), M4OSA_STRING, + (M4OSA_Char*)"M4OSA_strPrivCreate: output string"); + + /* Check memory allocation error */ + if(M4OSA_NULL == pStr) + { + *pStrOut = M4OSA_NULL ; + + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_strPrivCreate"); + + return M4ERR_ALLOC; + } + + pStr->coreID = M4OSA_STRING; + pStr->pui8_buffer = M4OSA_NULL; + pStr->ui32_length = 0; + pStr->ui32_size = 0; + + *pStrOut = pStr; + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This function reset the M4OSA_String + * @note + * @param str_in + * @return M4OSA_ERROR + ************************************************************************ + */ +M4OSA_ERR M4OSA_strReset(M4OSA_String str_in) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_Char* pBuffer; + + M4OSA_TRACE1_1("M4OSA_strReset\t\tM4OSA_String* 0x%x", str_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strReset"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strReset"); + + pBuffer = pStr->pui8_buffer; + + if(M4OSA_NULL != pBuffer) + { + M4OSA_free((M4OSA_MemAddr32)pBuffer); + + pStr->pui8_buffer = M4OSA_NULL; + } + + pStr->ui32_length = 0; + pStr->ui32_size = 0; + + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This function free the memory of the input M4OSA_String + * @note + * @param str_in + * @return M4OSA_ERROR + ************************************************************************ + */ +M4OSA_ERR M4OSA_strDestroy(M4OSA_String str_in) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + + M4OSA_TRACE1_1("M4OSA_strDestroy\t\tM4OSA_String 0x%x", str_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strDestroy"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strDestroy"); + + + /* Free M4OSA_String buffer */ + M4OSA_free((M4OSA_MemAddr32)(pStr->pui8_buffer)); + + /* Free M4OSA_String structure memory */ + M4OSA_free((M4OSA_MemAddr32)pStr); + + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief str_in content + * @note + * @param str_in + * @param pChar + * @return M4OSA_ERROR + ************************************************************************ + */ +M4OSA_ERR M4OSA_strSetCharContent(M4OSA_String str_in, M4OSA_Char *pChar) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + + M4OSA_TRACE1_2("M4OSA_strSetContent\t\tM4OSA_String 0x%x\tM4OSA_Char*" + " 0x%x", str_in, pChar); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetContent"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pChar, M4ERR_PARAMETER, + "M4OSA_strSetContent"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetContent"); + + return M4OSA_strPrivSet(pStr, pChar, M4OSA_chrLength(pChar)); +} + + + + +/** + ************************************************************************ +* @brief This function returns, in pac_content, the "C-String" of str_in + * @note + * @param str_in + * @param pac_content + * @return M4OSA_ERROR + ************************************************************************ +*/ +M4OSA_ERR M4OSA_strGetCharContent(M4OSA_String str_in, M4OSA_Char** ppchar) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + + M4OSA_TRACE1_2("M4OSA_strGetContent\t\tM4OSA_String 0x%x\tM4OSA_Char**" + " 0x%x", str_in, ppchar); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetContent"); + M4OSA_DEBUG_IF2(M4OSA_NULL == ppchar, M4ERR_PARAMETER, + "M4OSA_strGetContent"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetContent"); + + *ppchar = pStr->pui8_buffer; + + + return M4NO_ERROR; +} + +M4OSA_ERR M4OSA_strSetChar(M4OSA_String str_in, M4OSA_Char c_in) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err; + + M4OSA_TRACE1_2("M4OSA_strSetChar\t\tM4OSA_String 0x%x\tM4OSA_Char %c", + str_in, c_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetChar"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetChar"); + + + err = M4OSA_strPrivRealloc(pStr, 1); + + if(M4OSA_ERR_IS_ERROR(err)) + { + return err; + } + + pStr->pui8_buffer[0] = c_in; + pStr->pui8_buffer[1] = '\0'; + pStr->ui32_length = 1; + + + return M4NO_ERROR; +} + + + + +M4OSA_ERR M4OSA_strGetChar(M4OSA_String str_in, M4OSA_Char* pc_out) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + + M4OSA_TRACE1_2("M4OSA_strGetChar\t\tM4OSA_String 0x%x\tM4OSA_Char* 0x%x", + str_in, pc_out); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pc_out, M4ERR_PARAMETER, "M4OSA_strGetChar"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetChar"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetChar"); + + if(pStr->ui32_length == 0) + { + return M4ERR_STR_CONV_FAILED; + } + + *pc_out = pStr->pui8_buffer[0]; + + + return M4NO_ERROR; +} + +M4OSA_ERR M4OSA_strSetInt8(M4OSA_String str_in, M4OSA_Int8 i8_in, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char aui8_buffer[8]; + M4OSA_ERR err_code; + + M4OSA_TRACE1_2("M4OSA_strSetInt8\t\tM4OSA_String 0x%x\tM4OSA_Int8 %d", + str_in, i8_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetInt8"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetInt8"); + + + /* Convert input number into "C-String" */ + switch(base) + { + case M4OSA_kstrDec: + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, (M4OSA_Char*)"%d", i8_in); + break; + } + + case M4OSA_kstrHexa: + { + if(i8_in < 0) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, (M4OSA_Char*)"-%X", + -i8_in); + } + else + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, (M4OSA_Char*)"%X", + i8_in); + } + break; + } + + case M4OSA_kstrOct: + { + if(i8_in < 0) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, (M4OSA_Char*)"-%o", + -i8_in); + } + else + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, (M4OSA_Char*)"%o", + i8_in); + } + break; + } + + default: + { + return M4ERR_PARAMETER; + } + } + + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + return err_code; + } + + /* Calculate M4OSA_String content length */ + ui32_length = M4OSA_chrLength(aui8_buffer) ; + + + return M4OSA_strPrivSet(pStr, aui8_buffer, ui32_length); +} + +M4OSA_ERR M4OSA_strGetInt8(M4OSA_String str_in, M4OSA_Int8* pi8_out, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strGetInt8\t\tM4OSA_String 0x%x\tM4OSA_Int8* 0x%x\t" + "M4OSA_strNumBase %d", str_in, pi8_out, base); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetInt8"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pi8_out, M4ERR_PARAMETER, "M4OSA_strGetInt8"); + M4OSA_DEBUG_IF2((base != M4OSA_kstrDec) && (base != M4OSA_kstrHexa) && + (base != M4OSA_kstrOct), M4ERR_PARAMETER, "M4OSA_strGetInt8"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID,M4ERR_STR_BAD_STRING, + "M4OSA_strGetInt8"); + + + err_code = M4OSA_chrGetInt8(pStr->pui8_buffer, pi8_out, M4OSA_NULL, base); + + if(M4NO_ERROR != err_code) + { + M4OSA_DEBUG(M4ERR_STR_CONV_FAILED, "M4OSA_strGetInt8"); + + return M4ERR_STR_CONV_FAILED; + } + + + return M4NO_ERROR; +} + + + +M4OSA_ERR M4OSA_strSetUInt8(M4OSA_String str_in, M4OSA_UInt8 ui8_in, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char aui8_buffer[4]; + M4OSA_ERR err_code; + M4OSA_Char* pFormat; + + M4OSA_TRACE1_2("M4OSA_strSetUInt8\t\tM4OSA_String* 0x%x\tM4OSA_UInt8 %d", + str_in, ui8_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetUInt8"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetUInt8"); + + if (base == M4OSA_kchrDec) + { + pFormat = (M4OSA_Char*)"%u"; + } + else if (base == M4OSA_kchrHexa) + { + pFormat = (M4OSA_Char*)"%X"; + } + else if (base == M4OSA_kchrOct) + { + pFormat = (M4OSA_Char*)"%o"; + } + else + { + pFormat = M4OSA_NULL; + } + + /* Convert input number into "C-String" */ + err_code = M4OSA_chrSPrintf(aui8_buffer, 4, pFormat, ui8_in); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + return err_code; + } + + /* Calculate M4OSA_String content length */ + ui32_length = M4OSA_chrLength(aui8_buffer) ; + + + return M4OSA_strPrivSet(pStr, aui8_buffer, ui32_length); +} + + + +M4OSA_ERR M4OSA_strGetUInt8(M4OSA_String str_in, + M4OSA_UInt8* pui8_out, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strGetUInt8\t\tM4OSA_String 0x%x\tM4OSA_UInt8* 0x%x\t" + "M4OSA_strNumBase %d", str_in, pui8_out, base); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetUInt8"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui8_out, M4ERR_PARAMETER, + "M4OSA_strGetUInt8"); + M4OSA_DEBUG_IF2((base != M4OSA_kstrDec) && (base != M4OSA_kstrHexa) + && (base != M4OSA_kstrOct), M4ERR_PARAMETER, "M4OSA_strGetUInt8"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetUInt8"); + + + err_code = M4OSA_chrGetUInt8(pStr->pui8_buffer, pui8_out, M4OSA_NULL, base); + + if(M4NO_ERROR != err_code) + { + M4OSA_DEBUG(M4ERR_STR_CONV_FAILED, "M4OSA_strGetUInt8"); + + return M4ERR_STR_CONV_FAILED; + } + + return M4NO_ERROR; +} + + + +M4OSA_ERR M4OSA_strSetInt16(M4OSA_String str_in, M4OSA_Int16 i16_in, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char aui8_buffer[8]; + M4OSA_ERR err_code; + + M4OSA_TRACE1_2("M4OSA_strSetInt16\t\tM4OSA_String* 0x%x\tM4OSA_Int16 %d", + str_in, i16_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetInt16"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetInt16"); + + /* Convert input number into "C-String" */ + switch(base) + { + case M4OSA_kstrDec: + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, (M4OSA_Char*)"%d", + i16_in); + break; + } + + case M4OSA_kstrHexa: + { + if(i16_in < 0) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, (M4OSA_Char*)"-%X", + -i16_in); + } + else + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, (M4OSA_Char*)"%X", + i16_in); + } + break; + } + + case M4OSA_kstrOct: + { + if(i16_in < 0) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, (M4OSA_Char*)"-%o", + -i16_in); + } + else + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, (M4OSA_Char*)"%o", + i16_in); + } + break; + } + + default: + { + return M4ERR_PARAMETER; + } + } + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + return err_code; + } + + /* Calculate M4OSA_String content length */ + ui32_length = M4OSA_chrLength(aui8_buffer) ; + + return M4OSA_strPrivSet(pStr, aui8_buffer, ui32_length); +} + + + +M4OSA_ERR M4OSA_strGetInt16(M4OSA_String str_in, M4OSA_Int16* pi16_out, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strGetInt16\t\tM4OSA_String 0x%x\tM4OSA_Int16* 0x%x" + "\tM4OSA_strNumBase %d", str_in, pi16_out, base); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetInt16"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pi16_out, M4ERR_PARAMETER, + "M4OSA_strGetInt16"); + M4OSA_DEBUG_IF2((base != M4OSA_kstrDec) && (base != M4OSA_kstrHexa) + && (base != M4OSA_kstrOct),M4ERR_PARAMETER, "M4OSA_strGetInt16"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetInt16"); + + err_code = M4OSA_chrGetInt16(pStr->pui8_buffer, pi16_out, M4OSA_NULL, base); + + if(M4NO_ERROR != err_code) + { + M4OSA_DEBUG(M4ERR_STR_CONV_FAILED, "M4OSA_strGetInt16"); + + return M4ERR_STR_CONV_FAILED; + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strSetUInt16(M4OSA_String str_in, M4OSA_UInt16 ui16_in, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char aui8_buffer[8]; + M4OSA_ERR err_code; + M4OSA_Char* pFormat; + + M4OSA_TRACE1_2("M4OSA_strSetUInt16\t\tM4OSA_String* 0x%x\tM4OSA_UInt16 %d", + str_in, ui16_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetUInt16"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetUInt16"); + + if (M4OSA_kchrDec == base) + { + pFormat = (M4OSA_Char*)"%u"; + } + else if (M4OSA_kchrHexa == base) + { + pFormat = (M4OSA_Char*)"%X"; + } + else if (M4OSA_kchrOct == base) + { + pFormat = (M4OSA_Char*)"%o"; + } + else + { + pFormat = M4OSA_NULL; + } + + /* Convert input number into "C-String" */ + err_code = M4OSA_chrSPrintf(aui8_buffer, 8, pFormat, ui16_in); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + return err_code; + } + + /* Calculate M4OSA_String content length */ + ui32_length = M4OSA_chrLength(aui8_buffer) ; + + + return M4OSA_strPrivSet(pStr, aui8_buffer, ui32_length); +} + + +M4OSA_ERR M4OSA_strGetUInt16(M4OSA_String str_in, M4OSA_UInt16* pui16_out, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strGetUInt16\t\tM4OSA_String 0x%x\tM4OSA_UInt16* " + "0x%x\tM4OSA_strNumBase %d", str_in, pui16_out, base); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetUInt16"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui16_out, M4ERR_PARAMETER, + "M4OSA_strGetUInt16"); + M4OSA_DEBUG_IF2((base != M4OSA_kstrDec) && (base != M4OSA_kstrHexa) + && (base != M4OSA_kstrOct), M4ERR_PARAMETER, "M4OSA_strGetUInt16"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetUInt16"); + + err_code = M4OSA_chrGetUInt16(pStr->pui8_buffer, pui16_out, M4OSA_NULL, + base); + + if(M4NO_ERROR != err_code) + { + M4OSA_DEBUG(M4ERR_STR_CONV_FAILED, "M4OSA_strGetUInt16"); + + return M4ERR_STR_CONV_FAILED; + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strSetInt32(M4OSA_String str_in, M4OSA_Int32 i32_in, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char aui8_buffer[16]; + M4OSA_ERR err_code; + M4OSA_Char* pFormat; + + M4OSA_TRACE1_2("M4OSA_strSetInt32\t\tM4OSA_String* 0x%x\tM4OSA_Int32 %d", + str_in, i32_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetInt32"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetInt32"); + + if (M4OSA_kchrDec == base) + { + pFormat = (M4OSA_Char*)"%d"; + } + else if (M4OSA_kchrHexa == base) + { + pFormat = (M4OSA_Char*)"%X"; + } + else if (M4OSA_kchrOct == base) + { + pFormat = (M4OSA_Char*)"%o"; + } + else + { + pFormat = M4OSA_NULL; + } + + /* Convert input number into "C-String" */ + switch(base) + { + case M4OSA_kstrDec: + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 16, (M4OSA_Char*)"%d", + i32_in); + break; + } + + case M4OSA_kstrHexa: + { + if(i32_in < 0) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 16, (M4OSA_Char*)"-%X", + -i32_in); + } + else + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 16, (M4OSA_Char*)"%X", + i32_in); + } + break; + } + + case M4OSA_kstrOct: + { + if(i32_in < 0) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 16, (M4OSA_Char*)"-%o", + -i32_in); + } + else + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 16, (M4OSA_Char*)"%o", + i32_in); + } + break; + } + + default: + { + return M4ERR_PARAMETER; + } + } + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + return err_code; + } + + /* Calculate M4OSA_String content length */ + ui32_length = M4OSA_chrLength(aui8_buffer) ; + + return M4OSA_strPrivSet(pStr, aui8_buffer, ui32_length); +} + +M4OSA_ERR M4OSA_strGetInt32(M4OSA_String str_in, + M4OSA_Int32* pi32_out, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strGetInt32\t\tM4OSA_String 0x%x\tM4OSA_Int32* 0x%x" + "\tM4OSA_strNumBase %d", str_in, pi32_out, base); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetInt32"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pi32_out, M4ERR_PARAMETER, + "M4OSA_strGetInt32"); + M4OSA_DEBUG_IF2((base != M4OSA_kstrDec) && (base != M4OSA_kstrHexa) + && (base != M4OSA_kstrOct), M4ERR_PARAMETER, "M4OSA_strGetInt32"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetInt32"); + + err_code = M4OSA_chrGetInt32(pStr->pui8_buffer, pi32_out, M4OSA_NULL, base); + + if(M4NO_ERROR != err_code) + { + M4OSA_DEBUG(M4ERR_STR_CONV_FAILED, "M4OSA_strGetInt32"); + + return M4ERR_STR_CONV_FAILED; + } + + return M4NO_ERROR; +} + +M4OSA_ERR M4OSA_strSetUInt32(M4OSA_String str_in, M4OSA_UInt32 ui32_in, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char aui8_buffer[12]; + M4OSA_ERR err_code; + M4OSA_Char* pFormat; + + M4OSA_TRACE1_2("M4OSA_strSetUInt32\t\tM4OSA_String* 0x%x\tM4OSA_UInt32 %d", + str_in, ui32_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetUInt32"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetUInt32"); + + if (M4OSA_kchrDec == base) + { + pFormat = (M4OSA_Char*)"%u"; + } + else if (M4OSA_kchrHexa == base) + { + pFormat = (M4OSA_Char*)"%X"; + } + else if (M4OSA_kchrOct == base) + { + pFormat = (M4OSA_Char*)"%o"; + } + else + { + pFormat = M4OSA_NULL; + } + + /* Convert input number into "C-String" */ + err_code = M4OSA_chrSPrintf(aui8_buffer, 12, pFormat, ui32_in); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + return err_code; + } + + /* Calculate M4OSA_String content length */ + ui32_length = M4OSA_chrLength(aui8_buffer) ; + + + return M4OSA_strPrivSet(pStr, aui8_buffer, ui32_length); +} + + +M4OSA_ERR M4OSA_strGetUInt32(M4OSA_String str_in, M4OSA_UInt32* pui32_out, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strGetUInt32\t\tM4OSA_String 0x%x\tM4OSA_UInt32* " + "0x%x\tM4OSA_strNumBase %d", str_in, pui32_out, base); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetUInt32"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui32_out, M4ERR_PARAMETER, + "M4OSA_strGetUInt32"); + M4OSA_DEBUG_IF2((base != M4OSA_kstrDec) && (base != M4OSA_kstrHexa) + && (base != M4OSA_kstrOct), M4ERR_PARAMETER, "M4OSA_strGetUInt32"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetUInt32"); + + err_code = M4OSA_chrGetUInt32(pStr->pui8_buffer, pui32_out, + M4OSA_NULL, base); + + if(M4NO_ERROR != err_code) + { + M4OSA_DEBUG(M4ERR_STR_CONV_FAILED, "M4OSA_strGetUInt32"); + + return M4ERR_STR_CONV_FAILED; + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strSetInt64(M4OSA_String str_in, M4OSA_Int64 i64_in, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char aui8_buffer[24]; + M4OSA_ERR err_code; + + + M4OSA_TRACE1_2("M4OSA_strSetInt64\t\tM4OSA_String* 0x%x\tM4OSA_Int64 0x%x", + str_in, &i64_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetInt64"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetInt64"); + + /* Convert input number into "C-String" */ + switch(base) + { + case M4OSA_kstrDec: + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"%lld", + i64_in); + break; + } + + case M4OSA_kstrHexa: + { + if(M4OSA_INT64_IS_POSITIVE(i64_in)) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"%llX", + i64_in); + } + else + { + M4OSA_INT64_NEG(i64_in, i64_in); + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"-%llX", + i64_in); + } + break; + } + + case M4OSA_kstrOct: + { + if(M4OSA_INT64_IS_POSITIVE(i64_in)) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"%llo", + i64_in); + } + else + { + M4OSA_INT64_NEG(i64_in, i64_in); + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"-%llo", + i64_in); + } + break; + } + + default: + { + return M4ERR_PARAMETER; + } + } + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + return err_code; + } + + /* Calculate M4OSA_String content length */ + ui32_length = M4OSA_chrLength(aui8_buffer) ; + + return M4OSA_strPrivSet(pStr, aui8_buffer, ui32_length); +} + +M4OSA_ERR M4OSA_strGetInt64(M4OSA_String str_in, M4OSA_Int64* pi64_out, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strGetInt64\t\tM4OSA_String 0x%x\tM4OSA_Int64* 0x%x" + "\tM4OSA_strNumBase %d", str_in, pi64_out, base); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetInt64"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pi64_out, M4ERR_PARAMETER, + "M4OSA_strGetInt64"); + M4OSA_DEBUG_IF2((base != M4OSA_kstrDec) && (base != M4OSA_kstrHexa) + && (base != M4OSA_kstrOct), M4ERR_PARAMETER, "M4OSA_strGetInt64"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetInt64"); + + err_code = M4OSA_chrGetInt64(pStr->pui8_buffer, pi64_out, M4OSA_NULL, base); + + if(M4NO_ERROR != err_code) + { + M4OSA_DEBUG(M4ERR_STR_CONV_FAILED, "M4OSA_strGetInt64"); + + return M4ERR_STR_CONV_FAILED; + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strSetDouble(M4OSA_String str_in, M4OSA_Double d_in) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char aui8_buffer[24]; + M4OSA_ERR err_code; + + M4OSA_TRACE1_2("M4OSA_strSetDouble\t\tM4OSA_String* 0x%x\tM4OSA_Double* " + "0x%x", str_in, &d_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetDouble"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetDouble"); + + /* Convert input number into "C-String" */ + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"%e", d_in); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + return err_code; + } + + /* Calculate M4OSA_String content length */ + ui32_length = M4OSA_chrLength(aui8_buffer) ; + + return M4OSA_strPrivSet(pStr, aui8_buffer, ui32_length); +} + + +M4OSA_ERR M4OSA_strGetDouble(M4OSA_String str_in, M4OSA_Double* pd_out) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + + M4OSA_TRACE1_2("M4OSA_strGetDouble\t\tM4OSA_String 0x%x\tM4OSA_Double* " + "0x%x", str_in, pd_out); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetDouble"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pd_out, M4ERR_PARAMETER, "M4OSA_strGetDouble"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetDouble"); + + err_code = M4OSA_chrGetDouble(pStr->pui8_buffer, pd_out, M4OSA_NULL); + if(M4NO_ERROR != err_code) + { + M4OSA_DEBUG(M4ERR_STR_CONV_FAILED, "M4OSA_strGetDouble"); + + return M4ERR_STR_CONV_FAILED; + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strSetFilePosition(M4OSA_String str_in, M4OSA_FilePosition fpos_in, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char aui8_buffer[24]; + M4OSA_ERR err_code; + + + M4OSA_TRACE1_2("M4OSA_strSetFilePosition\t\tM4OSA_String* 0x%x\t" + "M4OSA_FilePosition* 0x%x", str_in, &fpos_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, + "M4OSA_strSetFilePosition"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetFilePosition"); + + + /* Convert input number into "C-String" */ + switch(base) + { + case M4OSA_kstrDec: + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"%aad", + fpos_in); + break; + } + + case M4OSA_kstrHexa: + { + if(M4OSA_FPOS_IS_POSITIVE(fpos_in)) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"%aaX", + fpos_in); + } + else + { + M4OSA_FPOS_NEG(fpos_in, fpos_in); + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"-%aaX", + fpos_in); + } + break; + } + + case M4OSA_kstrOct: + { + if(M4OSA_FPOS_IS_POSITIVE(fpos_in)) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"%aao", + fpos_in); + } + else + { + M4OSA_FPOS_NEG(fpos_in, fpos_in); + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"-%aao", + fpos_in); + } + break; + } + + default: + { + return M4ERR_PARAMETER; + } + } + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + return err_code; + } + + /* Calculate M4OSA_String content length */ + ui32_length = M4OSA_chrLength(aui8_buffer) ; + + return M4OSA_strPrivSet(pStr, aui8_buffer, ui32_length); +} + +M4OSA_ERR M4OSA_strGetFilePosition(M4OSA_String str_in, M4OSA_FilePosition* pfpos_out, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strGetFilePosition\t\tM4OSA_String 0x%x\t" + "M4OSA_FilePosition* 0x%x\t\tM4OSA_strNumBase %d", + str_in, pfpos_out, base); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, + "M4OSA_strGetFilePosition"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pfpos_out, M4ERR_PARAMETER, + "M4OSA_strGetFilePosition"); + M4OSA_DEBUG_IF2((base != M4OSA_kstrDec) && (base != M4OSA_kstrHexa) + && (base != M4OSA_kstrOct), M4ERR_PARAMETER, "M4OSA_strGetFilePosition"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetFilePosition"); + + err_code = M4OSA_chrGetFilePosition(pStr->pui8_buffer, pfpos_out, + M4OSA_NULL, base); + + if(M4NO_ERROR != err_code) + { + M4OSA_DEBUG(M4ERR_STR_CONV_FAILED, "M4OSA_strGetFilePosition"); + + return M4ERR_STR_CONV_FAILED; + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strSetTime(M4OSA_String str_in, M4OSA_Time t_in, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char aui8_buffer[24]; + M4OSA_ERR err_code; + + M4OSA_TRACE1_2("M4OSA_strSetDouble\t\tM4OSA_String* 0x%x\tM4OSA_Time* 0x%x", + str_in, &t_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetTime"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetTime"); + + /* Convert input number into "C-String" */ + switch(base) + { + case M4OSA_kstrDec: + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"%tmd", + t_in); + break; + } + + case M4OSA_kstrHexa: + { + if(M4OSA_TIME_IS_POSITIVE(t_in)) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"%tmX", + t_in); + } + else + { + M4OSA_TIME_NEG(t_in, t_in); + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"-%tmX", + t_in); + } + break; + } + + case M4OSA_kstrOct: + { + if(M4OSA_TIME_IS_POSITIVE(t_in)) + { + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"%tmo", + t_in); + } + else + { + M4OSA_TIME_NEG(t_in, t_in); + err_code = M4OSA_chrSPrintf(aui8_buffer, 24, (M4OSA_Char*)"-%tmo", + t_in); + } + break; + } + + default: + { + return M4ERR_PARAMETER; + } + } + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + return err_code; + } + + /* Calculate M4OSA_String content length */ + ui32_length = M4OSA_chrLength(aui8_buffer) ; + + return M4OSA_strPrivSet(pStr, aui8_buffer, ui32_length); +} + + +M4OSA_ERR M4OSA_strGetTime(M4OSA_String str_in, M4OSA_Time* pt_out, + M4OSA_strNumBase base) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strGetTime\t\tM4OSA_String 0x%x\tM4OSA_Time* 0x%x" + "\tM4OSA_strNumBase %d", str_in, pt_out, base); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetTime"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pt_out, M4ERR_PARAMETER, "M4OSA_strGetTime"); + M4OSA_DEBUG_IF2((base != M4OSA_kstrDec) && (base != M4OSA_kstrHexa) + && (base != M4OSA_kstrOct), M4ERR_PARAMETER, "M4OSA_strGetTime"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID,M4ERR_STR_BAD_STRING, + "M4OSA_strGetTime"); + + err_code = M4OSA_chrGetTime(pStr->pui8_buffer, pt_out, M4OSA_NULL, base); + + if(M4NO_ERROR != err_code) + { + M4OSA_DEBUG(M4ERR_STR_CONV_FAILED, "M4OSA_strGetTime"); + + return M4ERR_STR_CONV_FAILED; + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strGetLength(M4OSA_String str_in, M4OSA_UInt32* pui32_len) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + + M4OSA_TRACE1_2("M4OSA_strGetLength\t\tM4OSA_String 0x%x\tM4OSA_UInt32* " + "0x%x", str_in, pui32_len); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strGetLength"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui32_len, M4ERR_PARAMETER, "M4OSA_strGetLength"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, "M4OSA_strGetLength"); + + /* Get the M4OSA_StringStuct length field */ + *pui32_len = pStr->ui32_length ; + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strCompare(M4OSA_String str_in1, M4OSA_String str_in2, + M4OSA_Int32* pi32_result) +{ + M4OSA_strStruct* pStr1 = (M4OSA_strStruct*)str_in1; + M4OSA_strStruct* pStr2 = (M4OSA_strStruct*)str_in2; + M4OSA_UInt32 length, length1, length2; + M4OSA_Int32 result; + M4OSA_UInt32 i; + M4OSA_Char* buffer1; + M4OSA_Char* buffer2; + M4OSA_Char* pTmp1; + M4OSA_Char* pTmp2; + + M4OSA_TRACE1_3("M4OSA_strCompare\t\tM4OSA_String 0x%x\tM4OSA_String 0x%x\t" + "M4OSA_UInt32* 0x%x", str_in1, str_in2, pi32_result); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr1, M4ERR_PARAMETER, "M4OSA_strCompare"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr2, M4ERR_PARAMETER, "M4OSA_strCompare"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pi32_result, M4ERR_PARAMETER, "M4OSA_strCompare"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr1->coreID, M4ERR_STR_BAD_STRING, "M4OSA_strCompare"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr2->coreID, M4ERR_STR_BAD_STRING, "M4OSA_strCompare"); + + buffer1 = pStr1->pui8_buffer; + buffer2 = pStr2->pui8_buffer; + + length1 = pStr1->ui32_length; + length2 = pStr2->ui32_length; + + length = (length1 < length2) ? length1 : length2; + + pTmp1 = (M4OSA_Char*)M4OSA_malloc(2 * length * sizeof(M4OSA_Char), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strCompare"); + + M4OSA_CHECK_MALLOC(pTmp1, "M4OSA_strCompare"); + + pTmp2 = pTmp1 + length; + + M4OSA_memcpy(pTmp1, buffer1, length); + + M4OSA_memcpy(pTmp2, buffer2, length); + + for(i=0; i<length; i++) + { + pTmp1[i] = M4OSA_chrToLower(buffer1[i]); + pTmp2[i] = M4OSA_chrToLower(buffer2[i]); + } + + M4OSA_chrNCompare(pTmp1, pTmp2, length, &result); + + M4OSA_free((M4OSA_MemAddr32)pTmp1); + + if(result != 0) + { + *pi32_result = result; + } + else + { + if (length1 == length2) + { + *pi32_result = 0; + } + else if (length1 > length2) + { + *pi32_result = 1; + } + else + { + *pi32_result = -1; + } + } + + return M4NO_ERROR; +} + +M4OSA_ERR M4OSA_strCompareSubStr(M4OSA_String str_in1, + M4OSA_UInt32 ui32_offset1, + M4OSA_String str_in2, + M4OSA_UInt32 ui32_offset2, + M4OSA_UInt32* pui32_num, + M4OSA_Int32* pi32_result) +{ + M4OSA_strStruct* pStr1 = (M4OSA_strStruct*)str_in1; + M4OSA_strStruct* pStr2 = (M4OSA_strStruct*)str_in2; + M4OSA_Char* pBuffer1; + M4OSA_Char* pBuffer2; + M4OSA_Char* pTmp1; + M4OSA_Char* pTmp2; + M4OSA_UInt32 length1, length2, i; + M4OSA_ERR err_code, return_code = M4NO_ERROR; + + M4OSA_TRACE1_5("M4OSA_strCompareSubStr\t\tM4OSA_String 0x%x\tM4OSA_UInt32 " + "%d\tM4OSA_String 0x%x\tM4OSA_UInt32 %d\tM4OSA_UInt32* 0x%x" + "\tM4OSA_Int32* 0x%x", str_in1, ui32_offset1, str_in2, + ui32_offset2, *pui32_num); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr1, M4ERR_PARAMETER, + "M4OSA_strCompareSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr2, M4ERR_PARAMETER, + "M4OSA_strCompareSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pi32_result, M4ERR_PARAMETER, + "M4OSA_strCompareSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui32_num, M4ERR_PARAMETER, + "M4OSA_strCompareSubStr"); + M4OSA_DEBUG_IF2(*pui32_num == 0, M4ERR_PARAMETER, "M4OSA_strCompareSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr1->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strCompareSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr2->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strCompareSubStr"); + M4OSA_DEBUG_IF2(ui32_offset1 >= pStr1->ui32_length, M4ERR_STR_OVERFLOW, + "M4OSA_strCompareSubStr"); + M4OSA_DEBUG_IF2(ui32_offset2 >= pStr2->ui32_length, M4ERR_STR_OVERFLOW, + "M4OSA_strCompareSubStr"); + + length1 = pStr1->ui32_length - ui32_offset1; + length2 = pStr2->ui32_length - ui32_offset2; + + pBuffer1 = pStr1->pui8_buffer + ui32_offset1; + pBuffer2 = pStr2->pui8_buffer + ui32_offset2; + + if(length1 < *pui32_num) + { + *pui32_num = length1; + + return_code = M4WAR_STR_OVERFLOW; + } + + if(length2 < *pui32_num) + { + *pui32_num = length2; + + return_code = M4WAR_STR_OVERFLOW; + } + + pTmp1 = (M4OSA_Char*)M4OSA_malloc(2 * (*pui32_num) * sizeof(M4OSA_Char), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strCompareSubStr"); + + M4OSA_CHECK_MALLOC(pTmp1, "M4OSA_strCompareSubStr"); + + pTmp2 = pTmp1 + (*pui32_num); + + M4OSA_memcpy(pTmp1, pBuffer1, *pui32_num); + + M4OSA_memcpy(pTmp2, pBuffer2, *pui32_num); + + for(i=0; i<(*pui32_num); i++) + { + pTmp1[i] = M4OSA_chrToLower(pBuffer1[i]); + pTmp2[i] = M4OSA_chrToLower(pBuffer2[i]); + } + + err_code = M4OSA_chrNCompare(pTmp1, pTmp2, *pui32_num, pi32_result); + + M4OSA_DEBUG_IF2((M4OSA_ERR)M4ERR_PARAMETER == err_code, M4ERR_PARAMETER, + "M4OSA_strCompareSubStr: M4OSA_chrNCompare"); + + M4OSA_free((M4OSA_MemAddr32)pTmp1); + + return return_code; +} + + +M4OSA_ERR M4OSA_strCaseCompare(M4OSA_String str_in1, M4OSA_String str_in2, + M4OSA_Int32* pi32_result) +{ + M4OSA_strStruct* pStr1 = (M4OSA_strStruct*)str_in1; + M4OSA_strStruct* pStr2 = (M4OSA_strStruct*)str_in2; + M4OSA_UInt32 length, length1, length2; + M4OSA_Char *pBuffer1, *pBuffer2; + M4OSA_Int32 result; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strCaseCompare\t\tM4OSA_String 0x%x\tM4OSA_String " + "0x%x\tM4OSA_UInt32* 0x%x", str_in1, str_in2, pi32_result); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr1, M4ERR_PARAMETER, "M4OSA_strCaseCompare"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr2, M4ERR_PARAMETER, "M4OSA_strCaseCompare"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pi32_result,M4ERR_PARAMETER, + "M4OSA_strCaseCompare"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr1->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strCaseCompare"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr2->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strCaseCompare"); + + length1 = pStr1->ui32_length; + length2 = pStr2->ui32_length; + + /** NB: Never use this expression "i = (value1 == value2) ? x: y;" + * because that doens't compile on other platforms (ADS for example) + * Use: if(value1 == value2) + * { i= x; ..etc + */ + if (M4OSA_NULL == pStr1->pui8_buffer) + { + pBuffer1 = (M4OSA_Char*)""; + } + else + { + pBuffer1 = pStr1->pui8_buffer; + } + + if (M4OSA_NULL == pStr2->pui8_buffer) + { + pBuffer2 = (M4OSA_Char*)""; + } + else + { + pBuffer2 = pStr2->pui8_buffer; + } + + if ((length1 < length2)) + { + length = length1; + } + else + { + length = length2; + } + + err_code = M4OSA_chrNCompare(pBuffer1, pBuffer2, length, &result); + + M4OSA_DEBUG_IF2((M4OSA_ERR)M4ERR_PARAMETER == err_code, M4ERR_PARAMETER, + "M4OSA_strCaseCompare: M4OSA_chrNCompare"); + + if (result != 0) + { + *pi32_result = result; + } + else if (length1 > length2) + { + *pi32_result = 1 ; + } + else + { + *pi32_result = -1; + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @author Nicolas Santini (PDSL-P) + * @author Hilaire Verschuere (PDSL-P) + * @brief + * @note + * @param str_in + * @param + * @return M4OSA_ERROR + * @date - 2002-12-32: creation + ************************************************************************ + */ +M4OSA_ERR M4OSA_strCaseCompareSubStr(M4OSA_String str_in1, + M4OSA_UInt32 ui32_offset1, + M4OSA_String str_in2, + M4OSA_UInt32 ui32_offset2, + M4OSA_UInt32* pui32_num, + M4OSA_Int32* pi32_result) +{ + M4OSA_strStruct* pStr1 = (M4OSA_strStruct*)str_in1; + M4OSA_strStruct* pStr2 = (M4OSA_strStruct*)str_in2; + M4OSA_Char* pBuffer1; + M4OSA_Char* pBuffer2; + M4OSA_UInt32 length1, length2; + M4OSA_ERR err_code = M4NO_ERROR; + + M4OSA_TRACE1_5("M4OSA_strCaseCompareSubStr\t\tM4OSA_String 0x%x\t" + "M4OSA_UInt32 %d\tM4OSA_String 0x%x\tM4OSA_UInt32 %d\t" + "M4OSA_UInt32* 0x%x\tM4OSA_Int32* 0x%x", str_in1, + ui32_offset1, str_in2, ui32_offset2, *pui32_num); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr1, M4ERR_PARAMETER, + "M4OSA_strCaseCompareSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr2, M4ERR_PARAMETER, + "M4OSA_strCaseCompareSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pi32_result, M4ERR_PARAMETER, + "M4OSA_strCaseCompareSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui32_num, M4ERR_PARAMETER, + "M4OSA_strCaseCompareSubStr"); + M4OSA_DEBUG_IF2(*pui32_num == 0, M4ERR_PARAMETER, + "M4OSA_strCaseCompareSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr1->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strCaseCompareSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr2->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strCaseCompareSubStr"); + M4OSA_DEBUG_IF2(ui32_offset1 >= pStr1->ui32_length, M4ERR_STR_OVERFLOW, + "M4OSA_strCaseCompareSubStr"); + M4OSA_DEBUG_IF2(ui32_offset2 >= pStr2->ui32_length, M4ERR_STR_OVERFLOW, + "M4OSA_strCaseCompareSubStr"); + + + length1 = pStr1->ui32_length - ui32_offset1; + length2 = pStr2->ui32_length - ui32_offset2; + + pBuffer1 = pStr1->pui8_buffer + ui32_offset1; + pBuffer2 = pStr2->pui8_buffer + ui32_offset2; + + if(length1 < *pui32_num) + { + *pui32_num = length1; + + err_code = M4WAR_STR_OVERFLOW; + } + + if(length2 < *pui32_num) + { + *pui32_num = length2; + + err_code = M4WAR_STR_OVERFLOW; + } + + M4OSA_chrNCompare(pBuffer1, pBuffer2, *pui32_num, pi32_result); + + return err_code; +} + + +M4OSA_ERR M4OSA_strSpan(M4OSA_String str_in, M4OSA_Char* charset, + M4OSA_UInt32* pui32_pos) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char* pBuffer; + M4OSA_ERR err_code; + + + M4OSA_TRACE1_3("M4OSA_strSpan\t\tM4OSA_String 0x%x\tM4OSA_Char* 0x%x\t" + "M4OSA_UInt32* 0x%x", str_in, charset, pui32_pos); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSpan"); + M4OSA_DEBUG_IF2(M4OSA_NULL == charset, M4ERR_PARAMETER, "M4OSA_strSpan"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui32_pos, M4ERR_PARAMETER, "M4OSA_strSpan"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSpan"); + + pStr = (M4OSA_strStruct*)str_in ; + + if(*pui32_pos >= pStr->ui32_length) + { + return M4ERR_STR_OVERFLOW; + } + + pBuffer = pStr->pui8_buffer + *pui32_pos; + + err_code = M4OSA_chrSpan(pBuffer, charset, &ui32_length); + + M4OSA_DEBUG_IF2((M4OSA_ERR)M4ERR_PARAMETER == err_code, M4ERR_PARAMETER, + "M4OSA_strSpan: M4OSA_chrSpan"); + + *pui32_pos += ui32_length; + + return M4NO_ERROR; +} + + + + + +M4OSA_ERR M4OSA_strSpanComplement(M4OSA_String str_in, M4OSA_Char* charset, + M4OSA_UInt32* pui32_pos) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code; + M4OSA_UInt32 ui32_length; + + M4OSA_TRACE1_3("M4OSA_strSpanComplement\t\tM4OSA_String 0x%x\tM4OSA_Char* " + "0x%x\tM4OSA_UInt32* 0x%x", str_in, charset, pui32_pos); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, + "M4OSA_strSpanComplement"); + M4OSA_DEBUG_IF2(M4OSA_NULL == charset, M4ERR_PARAMETER, + "M4OSA_strSpanComplement"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui32_pos, M4ERR_PARAMETER, + "M4OSA_strSpanComplement"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSpanComplement"); + + if(*pui32_pos >= pStr->ui32_length) + { + return M4ERR_STR_OVERFLOW; + } + + err_code = M4OSA_chrSpanComplement(pStr->pui8_buffer + *pui32_pos, + charset, &ui32_length); + + M4OSA_DEBUG_IF2((M4OSA_ERR)M4ERR_PARAMETER == err_code, M4ERR_PARAMETER, + "M4OSA_strSpanComplement: M4OSA_chrSpanComplement"); + + if(M4WAR_CHR_NOT_FOUND == err_code) + { + return M4WAR_STR_NOT_FOUND; + } + + *pui32_pos += ui32_length; + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strFindFirstChar(M4OSA_String str_in, M4OSA_Char c, + M4OSA_UInt32* pui32_pos) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_Char* pBuffer; + M4OSA_Char* pchar; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strFindFirstChar\t\tM4OSA_String 0x%x\tM4OSA_Char" + " 0x%x\tM4OSA_UInt32* 0x%x", str_in, c, pui32_pos); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, + "M4OSA_strFindFirstChar"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui32_pos, M4ERR_PARAMETER, + "M4OSA_strFindFirstChar"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strFindFirstChar"); + + if(*pui32_pos >= pStr->ui32_length) + { + return M4ERR_STR_OVERFLOW; + } + + pBuffer = pStr->pui8_buffer + *pui32_pos; + + err_code = M4OSA_chrFindChar(pBuffer, c, &pchar); + + M4OSA_DEBUG_IF2(err_code == (M4OSA_ERR)M4ERR_PARAMETER, + M4ERR_PARAMETER, "M4OSA_strFindFirstChar"); + + if(M4WAR_CHR_NOT_FOUND == err_code) + { + return M4WAR_STR_NOT_FOUND; + } + + *pui32_pos = pchar - pStr->pui8_buffer; + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strFindLastChar(M4OSA_String str_in, M4OSA_Char c, + M4OSA_UInt32* pui32_pos) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_Char* pBuffer; + M4OSA_UInt32 i; + + M4OSA_TRACE1_3("M4OSA_strFindLastChar\t\tM4OSA_String 0x%x\tM4OSA_Char" + " 0x%x\tM4OSA_UInt32* 0x%x", str_in, c, pui32_pos); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER,"M4OSA_strFindLastChar"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui32_pos, M4ERR_PARAMETER, + "M4OSA_strFindLastChar"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strFindLastChar"); + + if(*pui32_pos > pStr->ui32_length) + { + return M4ERR_STR_OVERFLOW; + } + + pBuffer = pStr->pui8_buffer; + + for(i=(*pui32_pos); i!=0; i--) + { + if(pBuffer[i] == c) + { + *pui32_pos = i; + + return M4NO_ERROR; + } + } + + return M4WAR_STR_NOT_FOUND; +} + + +M4OSA_ERR M4OSA_strFindFirstSubStr(M4OSA_String str_in1, M4OSA_String str_in2, + M4OSA_UInt32* pui32_pos) +{ + M4OSA_strStruct* pStr1 = (M4OSA_strStruct*)str_in1; + M4OSA_strStruct* pStr2 = (M4OSA_strStruct*)str_in2; + M4OSA_Char* pResult; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strFindFirstSubStr\t\tM4OSA_String 0x%x\tM4OSA_String" + " 0x%x\tM4OSA_UInt32* 0x%x", str_in1, str_in2, pui32_pos); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr1, M4ERR_PARAMETER, + "M4OSA_strFindFirstSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr2, M4ERR_PARAMETER, + "M4OSA_strFindFirstSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui32_pos, M4ERR_PARAMETER, + "M4OSA_strFindFirstSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr1->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strFindFirstSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr2->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strFindFirstSubStr"); + + if(*pui32_pos >= pStr1->ui32_length) + { + return M4ERR_STR_OVERFLOW; + } + + if(pStr2->ui32_length == 0) + { + return M4WAR_STR_NOT_FOUND; + } + + err_code = M4OSA_chrFindPattern(pStr1->pui8_buffer + (*pui32_pos), + pStr2->pui8_buffer, &pResult); + + M4OSA_DEBUG_IF2((M4OSA_ERR)M4ERR_PARAMETER == err_code, M4ERR_PARAMETER, + "M4OSA_strFindFirstSubStr: M4OSA_chrFindPattern"); + + if(M4WAR_CHR_NOT_FOUND == err_code) + { + return M4WAR_STR_NOT_FOUND; + } + + *pui32_pos = pResult - pStr1->pui8_buffer; + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strFindLastSubStr(M4OSA_String str_in1, M4OSA_String str_in2, + M4OSA_UInt32* pui32_pos) +{ + M4OSA_strStruct* pStr1 = (M4OSA_strStruct*)str_in1; + M4OSA_strStruct* pStr2 = (M4OSA_strStruct*)str_in2; + M4OSA_Int32 i32_result; + + + M4OSA_TRACE1_3("M4OSA_strFindLastSubStr\t\tM4OSA_String 0x%x\tM4OSA_String" + " 0x%x\tM4OSA_UInt32* 0x%x", str_in1, str_in2, pui32_pos); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr1, M4ERR_PARAMETER, + "M4OSA_strFindLastSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr2, M4ERR_PARAMETER, + "M4OSA_strFindLastSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pui32_pos, M4ERR_PARAMETER, + "M4OSA_strFindLastSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr1->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strFindLastSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr2->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strFindLastSubStr"); + + if(*pui32_pos > pStr1->ui32_length) + { + return M4ERR_STR_OVERFLOW; + } + + if((pStr2->ui32_length == 0) || (pStr1->ui32_length == 0)) + { + return M4WAR_STR_NOT_FOUND; + } + + i32_result = M4OSA_strPrivFindLastSubStr(pStr1, pStr2, *pui32_pos); + + if(i32_result < 0) + { + return M4WAR_STR_NOT_FOUND; + } + + *pui32_pos = i32_result; + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strTruncate(M4OSA_String str_in, M4OSA_UInt32 ui32_length) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + + M4OSA_TRACE1_2("M4OSA_strTroncate\t\tM4OSA_String 0x%x\tM4OSA_UInt32 %d", + str_in, ui32_length); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strTroncate"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strTroncate"); + + if(ui32_length >= pStr->ui32_length) + { + return M4WAR_STR_OVERFLOW; + } + + pStr->ui32_length = ui32_length; + + if(pStr->pui8_buffer != M4OSA_NULL) + { + pStr->pui8_buffer[ui32_length] = '\0'; + } + + return M4NO_ERROR; +} + +M4OSA_ERR M4OSA_strCopy(M4OSA_String str_out, M4OSA_String str_in) +{ + M4OSA_strStruct* pIstr = (M4OSA_strStruct*)str_in; + M4OSA_strStruct* pOstr = (M4OSA_strStruct*)str_out; + + M4OSA_TRACE1_2("M4OSA_strCopy\t\tM4OSA_String 0x%x\tM4OSA_String 0x%x", + str_in, str_out); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pIstr, M4ERR_PARAMETER, "M4OSA_strCopy"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pOstr, M4ERR_PARAMETER, "M4OSA_strCopy"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pIstr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strCopy"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pOstr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strCopy"); + + return M4OSA_strPrivSet(pOstr, pIstr->pui8_buffer, pIstr->ui32_length); +} + + +M4OSA_ERR M4OSA_strCopySubStr(M4OSA_String str_out, + M4OSA_UInt32 ui32_pos, + M4OSA_String str_in, + M4OSA_UInt32 ui32_offset, + M4OSA_UInt32* ui32_num) +{ + M4OSA_strStruct *pIstr = (M4OSA_strStruct*)str_in; + M4OSA_strStruct *pOstr = (M4OSA_strStruct*)str_out; + M4OSA_ERR err_code = M4NO_ERROR; + M4OSA_UInt32 ui32_length, olength; + M4OSA_Char* pSrc; + M4OSA_Char* pDest; + + + M4OSA_TRACE1_5("M4OSA_strCopySubStr\t\tM4OSA_String 0x%x\tM4OSA_UInt32 %d" + "\tM4OSA_String 0x%x\tM4OSA_UInt32 %d\tM4OSA_UInt32* %0x%x", + str_out, str_in, str_out, ui32_pos, ui32_num); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pIstr, M4ERR_PARAMETER, "M4OSA_strCopySubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pOstr, M4ERR_PARAMETER, "M4OSA_strCopySubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == ui32_num, M4ERR_PARAMETER, + "M4OSA_strCopySubStr"); + M4OSA_DEBUG_IF2(*ui32_num == 0, M4ERR_PARAMETER, "M4OSA_strCopySubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pOstr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strCopySubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pIstr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strCopySubStr"); + M4OSA_DEBUG_IF2(ui32_pos > pOstr->ui32_length, M4ERR_STR_OVERFLOW, + "M4OSA_strCopySubStr"); + M4OSA_DEBUG_IF2(ui32_offset > pIstr->ui32_length, M4ERR_STR_OVERFLOW, + "M4OSA_strCopySubStr"); + + /* Calculate there is enough char in str_in after ui32_offset */ + ui32_length = pIstr->ui32_length - ui32_offset; + + if(*ui32_num > ui32_length) + { + *ui32_num = ui32_length; + + err_code = M4WAR_STR_OVERFLOW; + } + + /* Calculate the future length of str2 */ + ui32_length = ui32_pos + *ui32_num; + + olength = pOstr->ui32_length; + + if(ui32_length >= olength) + { + olength = ui32_length; + } + + /* Reallocation if needed */ + if(M4OSA_strPrivReallocCopy(pOstr, olength) != M4NO_ERROR) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_strCopySubStr"); + + return M4ERR_ALLOC; + } + + pSrc = pIstr->pui8_buffer + ui32_offset; + pDest = pOstr->pui8_buffer + ui32_pos; + + M4OSA_memcpy(pDest, pSrc, *ui32_num); + + pOstr->ui32_length = olength; + pOstr->pui8_buffer[pOstr->ui32_length] = '\0'; + + return err_code; +} + + +M4OSA_ERR M4OSA_strConcat(M4OSA_String str_first, M4OSA_String str_second) +{ + M4OSA_strStruct* pStr1 = (M4OSA_strStruct*)str_first; + M4OSA_strStruct* pStr2 = (M4OSA_strStruct*)str_second; + M4OSA_UInt32 ui32_length; + M4OSA_Char* pBuffer; + + M4OSA_TRACE1_2("M4OSA_strConcat\t\tM4OSA_String 0x%x\tM4OSA_String 0x%x", + str_first, str_second); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr1, M4ERR_PARAMETER, "M4OSA_strConcat"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr2, M4ERR_PARAMETER, "M4OSA_strConcat"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr1->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strConcat"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr2->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strConcat"); + + if(pStr2->ui32_length == 0) + { + return M4NO_ERROR; + } + + ui32_length = pStr1->ui32_length + pStr2->ui32_length; + + if(M4OSA_strPrivReallocCopy(pStr1, ui32_length) != M4NO_ERROR) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_strConcat"); + + return M4ERR_ALLOC; + } + + pBuffer = pStr1->pui8_buffer + pStr1->ui32_length; + + /* Fill the actual M4OSA_String content */ + M4OSA_memcpy(pBuffer, pStr2->pui8_buffer, pStr2->ui32_length+1); + + pStr1->ui32_length = ui32_length; + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strInsertSubStr(M4OSA_String str_out, + M4OSA_UInt32 ui32_pos, + M4OSA_String str_in, + M4OSA_UInt32 ui32_offset, + M4OSA_UInt32* ui32_num) +{ + M4OSA_strStruct *pIstr = (M4OSA_strStruct*)str_in; + M4OSA_strStruct *pOstr = (M4OSA_strStruct*)str_out; + M4OSA_ERR err_code, return_code = M4NO_ERROR; + M4OSA_UInt32 ui32_length; + + M4OSA_TRACE1_5("M4OSA_strInsertSubStr\t\tM4OSA_String 0x%x\tM4OSA_UInt32 %d" + "\tM4OSA_String 0x%x\tM4OSA_UInt32 %d\tM4OSA_UInt32* %0x%x", + str_out, str_in, str_out, ui32_pos, ui32_num); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pIstr, M4ERR_PARAMETER, + "M4OSA_strInsertSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pOstr, M4ERR_PARAMETER, + "M4OSA_strInsertSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == ui32_num, M4ERR_PARAMETER, + "M4OSA_strInsertSubStr"); + M4OSA_DEBUG_IF2(*ui32_num == 0, M4ERR_PARAMETER, + "M4OSA_strInsertSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pIstr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strInsertSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pOstr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strInsertSubStr"); + M4OSA_DEBUG_IF2(ui32_pos > pOstr->ui32_length, M4ERR_STR_OVERFLOW, + "M4OSA_strInsertSubStr"); + M4OSA_DEBUG_IF2(ui32_offset > pIstr->ui32_length, M4ERR_STR_OVERFLOW, + "M4OSA_strInsertSubStr"); + + /* Calculate there is enough char in str_in after ui32_offset */ + ui32_length = pIstr->ui32_length - ui32_offset; + + if(*ui32_num > ui32_length) + { + *ui32_num = ui32_length; + + return_code = M4WAR_STR_OVERFLOW; + } + + err_code = M4OSA_strPrivSetAndRepleceStr(pOstr, ui32_pos, 0, + pIstr->pui8_buffer + ui32_offset, *ui32_num); + + if(err_code == (M4OSA_ERR)M4ERR_ALLOC) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_strInsertSubStr"); + + return M4ERR_ALLOC; + } + + return return_code; +} + + +M4OSA_ERR M4OSA_strDelSubStr(M4OSA_String str_in, M4OSA_UInt32 ui32_offset, + M4OSA_UInt32* ui32_num) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_length; + M4OSA_Char* pBuffer; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strDelSubStr\t\tM4OSA_String 0x%x\tM4OSA_UInt32 %d\t" + "M4OSA_UInt32* 0x%x", str_in, ui32_offset, ui32_num); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strDelSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == ui32_num, M4ERR_PARAMETER, + "M4OSA_strDelSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strDelSubStr"); + + pBuffer = pStr->pui8_buffer; + + ui32_length = pStr->ui32_length ; + + if(ui32_offset >= ui32_length) + { + return M4ERR_STR_OVERFLOW; + } + + ui32_length -= ui32_offset; + + if(*ui32_num >= ui32_length) + { + *ui32_num = ui32_length; + + pStr->ui32_length -= ui32_length; + + pBuffer[pStr->ui32_length] = '\0'; + + err_code = M4WAR_STR_OVERFLOW; + } + else + { + err_code = M4OSA_strPrivSetAndRepleceStr(pStr, ui32_offset, *ui32_num, + M4OSA_NULL, 0); + } + + return err_code; +} + + +M4OSA_ERR M4OSA_strReplaceSubStr(M4OSA_String str_in, M4OSA_String str_old, + M4OSA_String str_new, M4OSA_strMode mode) +{ + M4OSA_strStruct* pIstr = (M4OSA_strStruct*)str_in; + M4OSA_strStruct* pOstr = (M4OSA_strStruct*)str_old; + M4OSA_strStruct* pNstr = (M4OSA_strStruct*)str_new; + M4OSA_UInt32 olength, nlength, ilength; + M4OSA_Bool ostr2free = M4OSA_FALSE; + M4OSA_Bool nstr2free = M4OSA_FALSE; + M4OSA_ERR err_code; + + + M4OSA_TRACE1_4("M4OSA_strReplaceSubStr\t\tM4OSA_String 0x%x\tM4OSA_String " + "0x%x\tM4OSA_String 0x%x\tM4OSA_strSupprMode %d", + str_in, str_old, str_new, mode); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pIstr, M4ERR_PARAMETER, + "M4OSA_strReplaceSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pOstr, M4ERR_PARAMETER, + "M4OSA_strReplaceSubStr"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pNstr, M4ERR_PARAMETER, + "M4OSA_strReplaceSubStr"); + M4OSA_DEBUG_IF2((mode != M4OSA_kstrAll) && (mode != M4OSA_kstrEnd) + && (mode != M4OSA_kstrBegin), M4ERR_PARAMETER, + "M4OSA_strReplaceSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pIstr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strReplaceSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pOstr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strReplaceSubStr"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pNstr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strReplaceSubStr"); + + olength = pOstr->ui32_length; + nlength = pNstr->ui32_length; + ilength = pIstr->ui32_length; + + if((olength == 0) || (ilength == 0) || (olength > ilength)) + { + M4OSA_DEBUG(M4WAR_STR_NOT_FOUND, "M4OSA_strReplaceSubStr"); + + return M4WAR_STR_NOT_FOUND; + } + + if(pIstr == pOstr) + { + M4OSA_strPrivDuplicate(&pOstr, pIstr); + + ostr2free = M4OSA_TRUE; + } + + if(pIstr == pNstr) + { + M4OSA_strPrivDuplicate(&pNstr, pIstr); + + nstr2free = M4OSA_TRUE; + } + + if(nlength == olength) + { + err_code = M4OSA_strPrivReplaceSameSizeStr(pIstr, pOstr, pNstr, mode); + } + else if(nlength < olength) + { + err_code = M4OSA_strPrivReplaceSmallerStr(pIstr, pOstr, pNstr, mode); + } + else + { + err_code = M4OSA_strPrivReplaceBiggerStr(pIstr, pOstr, pNstr, mode); + } + + if(ostr2free == M4OSA_TRUE) + { + M4OSA_free((M4OSA_MemAddr32)pOstr->pui8_buffer); + M4OSA_free((M4OSA_MemAddr32)pOstr); + } + + if(nstr2free == M4OSA_TRUE) + { + M4OSA_free((M4OSA_MemAddr32)pNstr->pui8_buffer); + M4OSA_free((M4OSA_MemAddr32)pNstr); + } + + return err_code; +} + + +M4OSA_ERR M4OSA_strGetFirstToken(M4OSA_String str_in, M4OSA_String str_token, + M4OSA_String str_delim) +{ + M4OSA_strStruct* pIn = (M4OSA_strStruct*)str_in; + M4OSA_strStruct* pToken = (M4OSA_strStruct*)str_token; + M4OSA_strStruct* pDelim = (M4OSA_strStruct*)str_delim; + M4OSA_UInt32 length_token, length_delim; + M4OSA_Char* pBuffer; + M4OSA_Char* pchar; + M4OSA_ERR err_code; + + + M4OSA_TRACE1_3("M4OSA_strGetFirstToken\t\tM4OSA_String 0x%x\tM4OSA_String" + " 0x%x\tM4OSA_String 0x%x", str_in, str_token, str_delim); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pIn, M4ERR_PARAMETER,"M4OSA_strGetFirstToken"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pToken, M4ERR_PARAMETER, + "M4OSA_strGetFirstToken"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pDelim, M4ERR_PARAMETER, + "M4OSA_strGetFirstToken"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pIn->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetFirstToken"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pToken->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetFirstToken"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pDelim->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetFirstToken"); + + length_delim = pDelim->ui32_length; + + if(pDelim->ui32_length == 0) + { + M4OSA_DEBUG(M4WAR_STR_NOT_FOUND, "M4OSA_strGetFirstToken"); + + return M4WAR_STR_NOT_FOUND; + } + + pBuffer = pIn->pui8_buffer; + + err_code = M4OSA_chrFindPattern(pBuffer,pDelim->pui8_buffer, &pchar); + + if(err_code != M4NO_ERROR) + { + M4OSA_DEBUG(M4WAR_STR_NOT_FOUND, "M4OSA_strGetFirstToken"); + + return M4WAR_STR_NOT_FOUND; + } + + length_token = pchar - pBuffer; + + err_code = M4OSA_strPrivSet(pToken, pBuffer, length_token); + + if(err_code == (M4OSA_ERR)M4ERR_ALLOC) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_strGetFirstToken: M4OSA_strPrivSet"); + + return M4ERR_ALLOC; + } + + err_code = M4OSA_strPrivSetAndRepleceStr(pIn, 0, length_token + length_delim, + M4OSA_NULL, 0); + + if(err_code == (M4OSA_ERR)M4ERR_ALLOC) + { + M4OSA_DEBUG(M4ERR_ALLOC, + "M4OSA_strGetFirstToken: M4OSA_strPrivSetAndRepleceStr"); + + return M4ERR_ALLOC; + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strGetLastToken(M4OSA_String str_in, M4OSA_String str_token, + M4OSA_String str_delim) +{ + M4OSA_strStruct* pIn = (M4OSA_strStruct*)str_in; + M4OSA_strStruct* pToken = (M4OSA_strStruct*)str_token; + M4OSA_strStruct* pDelim = (M4OSA_strStruct*)str_delim; + M4OSA_UInt32 in_length, token_length, delim_length; + M4OSA_Char* pIn_buffer; + M4OSA_Char* pToken_buffer; + M4OSA_Int32 delim_pos; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_strGetLastToken\t\tM4OSA_String 0x%x\tM4OSA_String" + " 0x%x\tM4OSA_String 0x%x", str_in, str_token, str_delim); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pIn, M4ERR_PARAMETER, + "M4OSA_strGetLastToken"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pToken, M4ERR_PARAMETER, + "M4OSA_strGetLastToken"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pDelim, M4ERR_PARAMETER, + "M4OSA_strGetLastToken"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pIn->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetLastToken"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pToken->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetLastToken"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pDelim->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strGetLastToken"); + + in_length = pIn->ui32_length; + delim_length = pDelim->ui32_length; + pIn_buffer = pIn->pui8_buffer; + + if(pDelim->ui32_length > pIn->ui32_length) + { + M4OSA_DEBUG(M4WAR_STR_NOT_FOUND, "M4OSA_strGetLastToken"); + + return M4WAR_STR_NOT_FOUND; + } + + delim_pos = M4OSA_strPrivFindLastSubStr(pIn, pDelim, in_length-delim_length); + + if(delim_pos < 0) + { + M4OSA_DEBUG(M4WAR_STR_NOT_FOUND, "M4OSA_strGetLastToken"); + + return M4WAR_STR_NOT_FOUND; + } + + pToken_buffer = pIn_buffer + delim_pos + delim_length; + token_length = in_length - delim_pos + delim_length; + + err_code = M4OSA_strPrivSet(str_token, pToken_buffer, token_length); + + if(err_code == (M4OSA_ERR)M4ERR_ALLOC) + { + M4OSA_DEBUG(M4ERR_ALLOC, + "M4OSA_strGetLastToken: M4OSA_strPrivSet"); + + return err_code; + } + + pIn_buffer[delim_pos] = '\0'; + + pIn->ui32_length = delim_pos; + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strSetUpperCase(M4OSA_String str_in) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_Char* pBuffer; + M4OSA_Char* pchar; + + + M4OSA_TRACE1_1("M4OSA_strSetUpperCase\t\tM4OSA_String 0x%x", str_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetUpperCase"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetUpperCase"); + + pBuffer = pStr->pui8_buffer; + + for(pchar=pBuffer; pchar!=(pBuffer+pStr->ui32_length); pchar++) + { + *pchar = M4OSA_chrToUpper(*pchar); + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strSetLowerCase(M4OSA_String str_in) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_Char* pBuffer; + M4OSA_Char* pchar; + + M4OSA_TRACE1_1("M4OSA_strSetLowerCase\t\tM4OSA_String 0x%x", str_in); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetLowerCase"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetLowerCase"); + + pBuffer = pStr->pui8_buffer; + + for(pchar=pBuffer; pchar!=(pBuffer+pStr->ui32_length); pchar++) + { + *pchar = M4OSA_chrToLower(*pchar); + } + + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strSprintf(M4OSA_String str_in, M4OSA_Char* pFormat, ...) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_ERR err_code = M4ERR_STR_OVERFLOW; + M4OSA_UInt32 ui32_size; + va_list args; + + M4OSA_TRACE1_2("M4OSA_strSprintf\t\tM4OSA_String 0x%x\tM4OSA_Char* 0x%x", + str_in, pFormat); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pFormat, M4ERR_PARAMETER, "M4OSA_strSprintf"); + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSprintf"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetLowerCase"); + + ui32_size = pStr->ui32_length + (M4OSA_UInt32)(1.5 * M4OSA_chrLength(pFormat)); + + va_start(args, pFormat); + + while(err_code == (M4OSA_ERR)M4ERR_STR_OVERFLOW) + { + err_code = M4OSA_strPrivReallocCopy(pStr, ui32_size); + + if(err_code == (M4OSA_ERR)M4ERR_ALLOC) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_strSprintf"); + + va_end(args); + + return M4ERR_ALLOC; + } + + ui32_size *= 2; + + err_code = M4OSA_strPrivSPrintf(pStr, pFormat, args); + } + + va_end(args); + + pStr->ui32_length = M4OSA_chrLength(pStr->pui8_buffer); + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strSetMinAllocationSize(M4OSA_String str_in, M4OSA_UInt32 ui32_newsize) +{ + M4OSA_strStruct* pStr = (M4OSA_strStruct*)str_in; + M4OSA_UInt32 ui32_size; + M4OSA_Char* pBuffer; + M4OSA_Char* pIbuffer; + + M4OSA_TRACE1_2("M4OSA_strSetMinAllocationSize\t\tM4OSA_String 0x%x\t" + "M4OSA_Int32 %d", str_in, ui32_newsize); + + M4OSA_DEBUG_IF2(M4OSA_NULL == pStr, M4ERR_PARAMETER, "M4OSA_strSetInt32"); + M4OSA_DEBUG_IF2(M4OSA_STRING != pStr->coreID, M4ERR_STR_BAD_STRING, + "M4OSA_strSetInt32"); + + ui32_size = pStr->ui32_size; + pIbuffer = pStr->pui8_buffer; + + if(ui32_newsize > ui32_size) + { + ui32_size = ui32_newsize + ((4 - (ui32_newsize % 4)) % 4); + } + + /* Allocate the actual M4OSA_String content */ + pBuffer = (M4OSA_Char*)M4OSA_malloc(ui32_size * sizeof(M4OSA_Char), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strSetMinAllocationSize"); + + M4OSA_CHECK_MALLOC(pBuffer, "M4OSA_strSetMinAllocationSize"); + + if(pIbuffer != M4OSA_NULL) + { + M4OSA_memcpy(pBuffer, pIbuffer, pStr->ui32_length+1); + + M4OSA_free((M4OSA_MemAddr32)pIbuffer); + } + + pStr->pui8_buffer = pBuffer; + + pStr->ui32_size = ui32_size; + + return M4NO_ERROR; +} + diff --git a/libvideoeditor/osal/src/M4OSA_String_priv.c b/libvideoeditor/osal/src/M4OSA_String_priv.c new file mode 100755 index 0000000..07cef33 --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_String_priv.c @@ -0,0 +1,1136 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_String_priv.c + ************************************************************************ +*/ + +#include "M4OSA_Debug.h" +#include "M4OSA_Types.h" +#include "M4OSA_Memory.h" +#include "M4OSA_Error.h" +#include "M4OSA_String_priv.h" +#include "M4OSA_String.h" + +/** + ************************************************************************ + * @brief This function replaces a string buffer by a new "C-String" + * and manage memory if needed + * @note + * @param pstr_src + * @param pac_in + * @return M4OSA_ERROR + ************************************************************************ + */ +M4OSA_ERR M4OSA_strPrivRealloc(M4OSA_strStruct* str, + M4OSA_UInt32 ui32_length) +{ + M4OSA_UInt32 ui32_size; + M4OSA_Char* buffer; + + M4OSA_TRACE2_2("M4OSA_strPrivRealloc\t\tM4OSA_strStruct* 0x%x\t" + "M4OSA_UInt32* %d", str, ui32_length); + + ui32_size = str->ui32_size; + + /* Realloc if size is not sufficient to contain it entirely */ + if(ui32_length >= ui32_size) + { + if(ui32_size == 0) + { + ui32_size = 16; + } + + while(ui32_length >= ui32_size) + { + ui32_size <<= 1; + } + + buffer = str->pui8_buffer; + + if(buffer != M4OSA_NULL) + { + M4OSA_free((M4OSA_MemAddr32)buffer); + } + + /* Allocate the actual M4OSA_String content */ + buffer = (M4OSA_Char*)M4OSA_malloc(ui32_size * sizeof(M4OSA_Char), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strPrivRealloc"); + + /* Check memory allocation error */ + if(buffer == M4OSA_NULL) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_strPrivRealloc"); + + str->pui8_buffer = M4OSA_NULL; + str->ui32_size = 0; + str->ui32_length = 0; + + return M4ERR_ALLOC; + } + + str->pui8_buffer = buffer; + str->ui32_size = ui32_size; + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function replaces a string buffer by a new "C-String" + * and manage memory if needed + * @note + * @param pstr_src + * @param pac_in + * @return M4OSA_ERROR + ************************************************************************ + */ +M4OSA_ERR M4OSA_strPrivReallocCopy(M4OSA_strStruct* str, + M4OSA_UInt32 ui32_length) +{ + M4OSA_UInt32 ui32_size; + M4OSA_Char* buffer; + M4OSA_Char* pui8_buffer; + + M4OSA_TRACE2_2("M4OSA_strPrivReallocCopy\t\tM4OSA_strStruct* 0x%x\t" + "M4OSA_UInt32* %d", str, ui32_length); + + + ui32_size = str->ui32_size; + + /* Realloc if size is not sufficient to contain it entirely */ + if(ui32_length >= ui32_size) + { + if(ui32_size == 0) + { + ui32_size = 16; + } + + while(ui32_length >= ui32_size) + { + ui32_size <<= 1; + } + + /* Allocate the actual M4OSA_String content */ + buffer = (M4OSA_Char*)M4OSA_malloc(ui32_size * sizeof(M4OSA_Char), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strPrivReallocCopy"); + + /* Check memory allocation error */ + if(buffer == M4OSA_NULL) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_strPrivReallocCopy"); + + str->pui8_buffer = M4OSA_NULL; + str->ui32_size = 0; + str->ui32_length = 0; + + return M4ERR_ALLOC; + } + + pui8_buffer = str->pui8_buffer; + + if(pui8_buffer != M4OSA_NULL) + { + M4OSA_memcpy(buffer, pui8_buffer, str->ui32_length + 1); + + M4OSA_free((M4OSA_MemAddr32)pui8_buffer); + } + + str->pui8_buffer = buffer; + str->ui32_size = ui32_size; + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strPrivDuplicate(M4OSA_strStruct** ostr, + M4OSA_strStruct* istr) +{ + M4OSA_strStruct* str; + M4OSA_ERR err_code; + + M4OSA_TRACE2_2("M4OSA_strPrivDuplicate\t\tM4OSA_strStruct** 0x%x\t" + "M4OSA_strStruct** 0x%x", ostr, istr); + + /* Allocate the output M4OSA_String */ + str = (M4OSA_strStruct*)M4OSA_malloc(sizeof(M4OSA_strStruct), M4OSA_STRING, + (M4OSA_Char*)"M4OSA_strPrivDuplicate: output string"); + + /* Check memory allocation error */ + if(str == M4OSA_NULL) + { + *ostr = M4OSA_NULL ; + + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_strPrivDuplicate"); + + return M4ERR_ALLOC; + } + + str->coreID = M4OSA_STRING; + str->pui8_buffer = M4OSA_NULL; + str->ui32_length = 0; + str->ui32_size = 0; + + err_code = M4OSA_strPrivSet(str, istr->pui8_buffer, istr->ui32_length); + + if(err_code != M4NO_ERROR) + { + return err_code; + } + + *ostr = str; + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function replaces a string buffer by a new "C-String" + * and manage memory if needed + * @note + * @param pstr_src + * @param pac_in + * @return M4OSA_ERROR + ************************************************************************ +*/ +M4OSA_ERR M4OSA_strPrivSet(M4OSA_strStruct* str, + M4OSA_Char* pchar, + M4OSA_UInt32 ui32_length) +{ + M4OSA_UInt32 length; + M4OSA_Char* buffer; + + M4OSA_TRACE2_3("M4OSA_strPrivSet\t\tM4OSA_strStruct* 0x%x\tM4OSA_Char* " + "0x%x\tM4OSA_UInt32 %d", str, pchar, ui32_length); + + if(ui32_length != 0) + { + length = M4OSA_chrLength(pchar); + + if(length < ui32_length) + { + ui32_length = length; + } + + if(M4OSA_strPrivRealloc(str, ui32_length) != M4NO_ERROR) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_strPrivSet"); + + return M4ERR_ALLOC; + } + + buffer = str->pui8_buffer; + + /* Fill the actual M4OSA_String content */ + M4OSA_memcpy(buffer, pchar, ui32_length); + + buffer[ui32_length] = '\0'; + } + else if(str->pui8_buffer != M4OSA_NULL) + { + str->pui8_buffer[0] = '\0'; + } + + str->ui32_length = ui32_length; + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function replaces a string buffer by a new "C-String" + * and manage memory if needed + * @note + * @param pstr_src + * @param pac_in + * @return M4OSA_ERROR + ************************************************************************ +*/ +M4OSA_Int32 M4OSA_strPrivFindLastSubStr(M4OSA_strStruct* str1, + M4OSA_strStruct* str2, + M4OSA_UInt32 ui32_pos) +{ + M4OSA_Char *pchar; + M4OSA_Char *buffer1; + M4OSA_Char *buffer2; + M4OSA_Int32 i32_result; + M4OSA_UInt32 length1, length2; + M4OSA_Int32 dist; + + M4OSA_TRACE2_3("M4OSA_strPrivFindLastSubStr\t\tM4OSA_strStruct* 0x%x\t" + "M4OSA_strStruct* 0x%x\tM4OSA_UInt32 %d", + str1, str2, ui32_pos); + + length1 = str1->ui32_length; + length2 = str2->ui32_length; + + if((length1 == 0) || (length2 == 0)) + { + return -1; + } + + buffer1 = str1->pui8_buffer; + buffer2 = str2->pui8_buffer; + + dist = length1 - length2; + + if(dist < 0) + { + return -1; + } + + if((M4OSA_Int32)ui32_pos > dist) + { + ui32_pos = dist; + } + + for(pchar = buffer1 + ui32_pos; pchar != buffer1; pchar--) + { + M4OSA_chrNCompare(pchar, buffer2, length2, &i32_result); + + if(i32_result == 0) + { + return pchar - buffer1; + } + } + + return -1; +} + +/** + ************************************************************************ + * @brief This function replaces a string buffer by a new "C-String" + * and manage memory if needed + * @note + * @param pstr_src + * @param pac_in + * @return M4OSA_ERROR + ************************************************************************ + */ +M4OSA_ERR M4OSA_strPrivSetAndRepleceStr(M4OSA_strStruct* istr, + M4OSA_UInt32 ui32_pos, + M4OSA_UInt32 olength, + M4OSA_Char* nbuff, + M4OSA_UInt32 nlength) +{ + M4OSA_Char* buffer; + M4OSA_Char* ibuffer; + M4OSA_UInt32 ui32_length, ui32_size, ui32_lend, ui32_poso, ui32_posn; + + M4OSA_TRACE2_5("M4OSA_strPrivSetAndRepleceStr\t\tM4OSA_strStruct* 0x%x\t" + "M4OSA_UInt32 %d\tM4OSA_UInt32 %d\tM4OSA_Char* 0x%x\t" + "M4OSA_UInt32 %d", istr, ui32_pos, olength, nbuff, nlength); + + ui32_length = istr->ui32_length - olength + nlength; + + ibuffer = istr->pui8_buffer; + + /* string to replace has the same this that new string */ + if(nlength == olength) + { + if(nlength == 0) + { + return M4NO_ERROR; + } + + M4OSA_memcpy(ibuffer + ui32_pos, nbuff, nlength); + } + else + { + ui32_lend = istr->ui32_length - ui32_pos - olength; + ui32_poso = ui32_pos + olength; + ui32_posn = ui32_pos + nlength; + + /* string to replace is bigger that new string */ + if(nlength < olength) + { + if(nlength > 0) + { + M4OSA_memcpy(ibuffer + ui32_pos, nbuff, nlength); + } + + if((olength - nlength) >= ui32_lend) + { + M4OSA_memcpy(ibuffer + ui32_posn, ibuffer + ui32_poso, ui32_lend); + } + else + { + buffer = (M4OSA_Char*)M4OSA_malloc(ui32_lend * sizeof(M4OSA_Char), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strPrivSetAndRepleceStr"); + + M4OSA_CHECK_MALLOC(buffer, "M4OSA_strPrivSetAndRepleceStr"); + M4OSA_memcpy(buffer, ibuffer + ui32_poso, ui32_lend); + M4OSA_memcpy(ibuffer + ui32_posn, buffer, ui32_lend); + M4OSA_free((M4OSA_MemAddr32)buffer); + } + } + /* string to replace is smaller that new string */ + else + { + ui32_size = istr->ui32_size; + + /* check if there is enough memory allocated in istr */ + if(ui32_length >= ui32_size) + { + if(ui32_size == 0) + { + ui32_size = 16; + } + + while(ui32_length >= ui32_size) + { + ui32_size <<= 1; + } + + buffer = (M4OSA_Char*)M4OSA_malloc(ui32_size * sizeof(M4OSA_Char), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strPrivSetAndRepleceStr"); + + M4OSA_CHECK_MALLOC(buffer, "M4OSA_strPrivSetAndRepleceStr"); + + M4OSA_memcpy(buffer, ibuffer, ui32_pos); + + M4OSA_memcpy(buffer + ui32_pos, nbuff, nlength); + + M4OSA_memcpy(buffer + ui32_posn, ibuffer + ui32_poso, ui32_lend); + + M4OSA_free((M4OSA_MemAddr32)ibuffer); + + istr->pui8_buffer = buffer; + + istr->ui32_size = ui32_size; + } + else + { + buffer = (M4OSA_Char*)M4OSA_malloc(ui32_lend * sizeof(M4OSA_Char), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strPrivSetAndRepleceStr"); + + M4OSA_CHECK_MALLOC(buffer, "M4OSA_strPrivSetAndRepleceStr"); + + M4OSA_memcpy(buffer, ibuffer + ui32_poso, ui32_lend); + + M4OSA_memcpy(ibuffer + ui32_pos, nbuff, nlength); + + M4OSA_memcpy(ibuffer + ui32_posn, buffer, ui32_lend); + + M4OSA_free((M4OSA_MemAddr32)buffer); + } + } + } + + + istr->pui8_buffer[ui32_length] = '\0'; + + istr->ui32_length = ui32_length; + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function replaces a string buffer by a new "C-String" + * and manage memory if needed + * @note + * @param pstr_src + * @param pac_in + * @return M4OSA_ERROR + ************************************************************************ + */ +M4OSA_ERR M4OSA_strPrivReplaceSameSizeStr(M4OSA_strStruct* istr, + M4OSA_strStruct* ostr, + M4OSA_strStruct* nstr, + M4OSA_strMode mode) +{ + M4OSA_Char* ibuffer; + M4OSA_Char* obuffer; + M4OSA_Char* nbuffer; + M4OSA_Char* ptr; + M4OSA_UInt32 ilength, nlength; + M4OSA_Int32 i32_pos; + M4OSA_ERR err_code; + + M4OSA_TRACE2_4("M4OSA_strPrivReplaceSameSizeStr\t\tM4OSA_strStruct* 0x%x\t" + "M4OSA_strStruct* 0x%x\tM4OSA_strStruct* 0x%x\t" + "M4OSA_strMode %d", istr, ostr, nstr, mode); + + ibuffer = istr->pui8_buffer; + obuffer = ostr->pui8_buffer; + nbuffer = nstr->pui8_buffer; + + ilength = istr->ui32_length; + nlength = nstr->ui32_length; + + if(mode != M4OSA_kstrEnd) + { + err_code = M4OSA_chrFindPattern(ibuffer, obuffer, &ptr); + + M4OSA_DEBUG_IF2(M4OSA_ERR_IS_ERROR(err_code), err_code, + "M4OSA_strPrivReplaceSameSizeStr"); + + if(err_code == M4WAR_CHR_NOT_FOUND) + { + return M4WAR_STR_NOT_FOUND; + } + + if(mode == M4OSA_kstrAll) + { + do + { + M4OSA_memcpy(ptr, nbuffer, nlength); + + err_code = M4OSA_chrFindPattern(ptr+nlength, obuffer, &ptr); + + M4OSA_DEBUG_IF2(M4OSA_ERR_IS_ERROR(err_code), err_code, + "M4OSA_strPrivReplaceSameSizeStr"); + + } while(err_code != M4WAR_CHR_NOT_FOUND); + } + else + { + M4OSA_memcpy(ptr, nbuffer, nlength); + } + } + else + { + i32_pos = M4OSA_strPrivFindLastSubStr(istr, ostr, ilength-1); + + if(i32_pos < 0) + { + return M4WAR_STR_NOT_FOUND; + } + + M4OSA_memcpy(ibuffer + i32_pos, nbuffer, nlength); + } + + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function replaces a string buffer by a new "C-String" + * and manage memory if needed + * @note + * @param pstr_src + * @param pac_in + * @return M4OSA_ERROR + ************************************************************************ + */ +M4OSA_ERR M4OSA_strPrivReplaceSmallerStr(M4OSA_strStruct* istr, + M4OSA_strStruct* ostr, + M4OSA_strStruct* nstr, + M4OSA_strMode mode) +{ + M4OSA_Char* ibuffer; + M4OSA_Char* obuffer; + M4OSA_Char* nbuffer; + M4OSA_Char* buffer; + M4OSA_Char* ptr_src; + M4OSA_Char* ptr_dest; + M4OSA_UInt32 ilength, nlength, olength, size, length; + M4OSA_Int32 i32_pos; + M4OSA_ERR err_code; + + M4OSA_TRACE2_4("M4OSA_strPrivReplaceSmallerStr\t\tM4OSA_strStruct* 0x%x\t" + "M4OSA_strStruct* 0x%x\tM4OSA_strStruct* 0x%x\t" + "M4OSA_strMode %d", istr, ostr, nstr, mode); + + ibuffer = istr->pui8_buffer; + obuffer = ostr->pui8_buffer; + nbuffer = nstr->pui8_buffer; + + ilength = istr->ui32_length; + olength = ostr->ui32_length; + nlength = nstr->ui32_length; + + length = ilength; + + if(mode == M4OSA_kstrAll) + { + err_code = M4OSA_chrFindPattern(ibuffer, obuffer, &ptr_src); + + M4OSA_DEBUG_IF2(M4OSA_ERR_IS_ERROR(err_code), err_code, + "M4OSA_strPrivReplaceSameSizeStr"); + + if(err_code == M4WAR_CHR_NOT_FOUND) + { + return M4WAR_STR_NOT_FOUND; + } + + /* Allocate the actual M4OSA_String content */ + buffer = (M4OSA_Char*)M4OSA_malloc(istr->ui32_size * sizeof(M4OSA_Char), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strPrivReplaceSmallerStr"); + + M4OSA_CHECK_MALLOC(buffer, "M4OSA_strPrivReplaceSmallerStr"); + + ptr_dest = buffer; + + do + { + size = (M4OSA_UInt32)ptr_src - (M4OSA_UInt32)ibuffer; + + length += (nlength - olength); + + M4OSA_memcpy(ptr_dest, ibuffer, size); + + ptr_dest += size; + + M4OSA_memcpy(ptr_dest, nbuffer, nlength); + + ptr_dest += nlength; + + ibuffer += (size + olength); + + err_code = M4OSA_chrFindPattern(ibuffer, obuffer, &ptr_src); + + M4OSA_DEBUG_IF2(M4OSA_ERR_IS_ERROR(err_code), err_code, + "M4OSA_strPrivReplaceSameSizeStr"); + + } while(err_code != M4WAR_CHR_NOT_FOUND); + + size = ilength - (M4OSA_UInt32)(ibuffer - istr->pui8_buffer); + + M4OSA_memcpy(ptr_dest, ibuffer, size); + + M4OSA_free((M4OSA_MemAddr32)istr->pui8_buffer); + + istr->ui32_length = length ; + + buffer[length] = '\0'; + + istr->pui8_buffer = buffer; + } + else + { + if(mode == M4OSA_kstrBegin) + { + err_code = M4OSA_chrFindPattern(ibuffer, obuffer, &ptr_src); + + M4OSA_DEBUG_IF2(M4OSA_ERR_IS_ERROR(err_code), err_code, + "M4OSA_strPrivReplaceSameSizeStr"); + + if(err_code == M4WAR_CHR_NOT_FOUND) + { + return M4WAR_STR_NOT_FOUND; + } + + i32_pos = (M4OSA_UInt32)ptr_src - (M4OSA_UInt32)ibuffer; + } + else + { + i32_pos = M4OSA_strPrivFindLastSubStr(istr, ostr, ilength-1); + + if(i32_pos == -1) + { + return M4WAR_STR_NOT_FOUND; + } + } + + err_code = M4OSA_strPrivSetAndRepleceStr(istr, i32_pos, olength, + nbuffer, nlength); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + M4OSA_DEBUG(err_code, "M4OSA_strPrivReplaceSmallerStr"); + + return err_code; + } + } + + return M4NO_ERROR; +} + +/** + ************************************************************************ + * @brief This function replaces a string buffer by a new "C-String" + * and manage memory if needed + * @note + * @param pstr_src + * @param pac_in + * @return M4OSA_ERROR + ************************************************************************ + */ +M4OSA_ERR M4OSA_strPrivReplaceBiggerStr(M4OSA_strStruct* istr, + M4OSA_strStruct* ostr, + M4OSA_strStruct* nstr, + M4OSA_strMode mode) +{ + M4OSA_Char* ibuffer; + M4OSA_Char* obuffer; + M4OSA_Char* nbuffer; + M4OSA_Char* buffer; + M4OSA_Char* ptr; + M4OSA_UInt32 ilength, nlength, olength, length; + M4OSA_Int32 i32_pos; + M4OSA_ERR err_code; + + M4OSA_TRACE2_4("M4OSA_strPrivReplaceBiggerStr\t\tM4OSA_strStruct* 0x%x\t" + "M4OSA_strStruct* 0x%x\tM4OSA_strStruct* 0x%x\t" + "M4OSA_strMode %d", istr, ostr, nstr, mode); + + ibuffer = istr->pui8_buffer; + obuffer = ostr->pui8_buffer; + nbuffer = nstr->pui8_buffer; + + ilength = istr->ui32_length; + olength = ostr->ui32_length; + nlength = nstr->ui32_length; + + + if(mode == M4OSA_kstrAll) + { + M4OSA_UInt32 n=0, i; + M4OSA_Int32* patterns; + M4OSA_UInt32 pos=0, size; + M4OSA_UInt32 max_pattern = ilength / olength; + M4OSA_UInt32 ui32_size = istr->ui32_size; + M4OSA_Char* src; + M4OSA_Char* dest; + + /* Allocate the actual M4OSA_String content */ + patterns = (M4OSA_Int32*)M4OSA_malloc(max_pattern * sizeof(M4OSA_UInt32), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strPrivReplaceBiggerStr"); + + M4OSA_CHECK_MALLOC(patterns, (M4OSA_Char*)"M4OSA_strPrivReplaceBiggerStr"); + + + err_code = M4OSA_chrFindPattern(ibuffer, obuffer, &ptr); + + M4OSA_DEBUG_IF2(M4OSA_ERR_IS_ERROR(err_code), err_code, + "M4OSA_strPrivReplaceBiggerStr"); + + if(err_code == M4WAR_CHR_NOT_FOUND) + { + return M4WAR_STR_NOT_FOUND; + } + + do + { + patterns[n] = (M4OSA_UInt32)ptr - (M4OSA_UInt32)ibuffer; + + n++; + + err_code = M4OSA_chrFindPattern(ptr + olength, obuffer, &ptr); + + M4OSA_DEBUG_IF2(M4OSA_ERR_IS_ERROR(err_code), err_code, + "M4OSA_strPrivReplaceBiggerStr"); + + } while(err_code != M4WAR_CHR_NOT_FOUND); + + length = ilength - (n * olength) + (n * nlength); + + + if(length >= ui32_size) + { + do + { + ui32_size <<= 1; + + } while(length >= ui32_size); + } + + /* Allocate the actual M4OSA_String content */ + buffer = (M4OSA_Char*)M4OSA_malloc(ui32_size * sizeof(M4OSA_Char), + M4OSA_STRING, (M4OSA_Char*)"M4OSA_strPrivReplaceBiggerStr"); + + M4OSA_CHECK_MALLOC(buffer, "M4OSA_strPrivReplaceBiggerStr"); + + src = ibuffer; + dest = buffer; + + for(i=0; i<n; i++) + { + size = patterns[i] - pos; + + M4OSA_memcpy(dest, src, size); + + pos = patterns[i] + olength; + + src = ibuffer + pos; + + dest += size; + + M4OSA_memcpy(dest, nbuffer, nlength); + + dest += nlength; + } + + size = ilength - (M4OSA_UInt32)(src - ibuffer); + + M4OSA_memcpy(dest, src, size); + + M4OSA_free((M4OSA_MemAddr32)patterns); + + M4OSA_free((M4OSA_MemAddr32)ibuffer); + + istr->ui32_length = length; + + istr->pui8_buffer = buffer; + + istr->pui8_buffer[length] = '\0'; + } + else + { + if(mode == M4OSA_kstrBegin) + { + err_code = M4OSA_chrFindPattern(ibuffer, obuffer, &ptr); + + M4OSA_DEBUG_IF2(M4OSA_ERR_IS_ERROR(err_code), err_code, + "M4OSA_strPrivReplaceSameSizeStr"); + + if(err_code == M4WAR_CHR_NOT_FOUND) + { + return M4WAR_STR_NOT_FOUND; + } + + i32_pos = (M4OSA_UInt32)ptr - (M4OSA_UInt32)ibuffer; + } + else + { + i32_pos = M4OSA_strPrivFindLastSubStr(istr, ostr, ilength-1); + + if(i32_pos == -1) + { + return M4WAR_STR_NOT_FOUND; + } + } + + err_code = M4OSA_strPrivSetAndRepleceStr(istr, i32_pos, olength, + nbuffer, nlength); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + M4OSA_DEBUG(err_code, "M4OSA_strPrivReplaceSmallerStr"); + + return err_code; + } + } + + return M4NO_ERROR; +} + + +M4OSA_ERR M4OSA_strPrivSPrintf(M4OSA_strStruct* str, + M4OSA_Char *format, + va_list marker) +{ + M4OSA_Char *temp; + M4OSA_Char *percentPointer; + M4OSA_Char *newFormat; + M4OSA_Char* strOut = str->pui8_buffer + str->ui32_length; + M4OSA_UInt32 strOutMaxLen = str->ui32_size-1; + M4OSA_Int32 newFormatLength = 0; + M4OSA_UInt32 count_ll = 0; + M4OSA_UInt32 count_tm = 0; + M4OSA_UInt32 count_aa = 0; + M4OSA_UInt32 count; + M4OSA_UInt32 nbChar; + M4OSA_Int32 iResult; + + M4OSA_Int32 err; + M4OSA_Char flagChar[] = "'-+ #0"; + M4OSA_Char widthOrPrecisionChar[] = "*0123456789"; + M4OSA_Char otherPrefixChar[] = "hlL"; + M4OSA_Char conversionChar[] = "diouxXnfeEgGcCsSp%"; + + M4OSA_TRACE2_2("M4OSA_strSPrintf\t\tM4OSA_String 0x%x\tM4OSA_Char* 0x%x", + str, format); + + + /* count the number of %[flags][width][.precision]ll[conversion] */ + temp = format; + + while(*temp) + { + /* get the next percent character */ + err = M4OSA_chrFindChar (temp, '%', &percentPointer); + + if((!percentPointer) || (M4WAR_CHR_NOT_FOUND == err)) + { + break; /* "This is the End", (c) J. Morrisson */ + } + + temp = percentPointer+1; /* span it */ + if(!*temp) /* "This is the End", (c) J. Morrisson */ + { + break; + } + + /* span the optional flags */ + M4OSA_chrSpan(format, conversionChar, &nbChar); + temp += nbChar; + + if(!*temp) /* "This is the End", (c) J. Morrisson */ + { + break; + } + + /* span the optional width */ + M4OSA_chrSpan(temp, widthOrPrecisionChar, &nbChar); + temp += nbChar; + if(!*temp) /* "This is the End", (c) J. Morrisson */ + { + break; + } + + if(*temp=='.') + { + /* span the optional precision */ + M4OSA_chrSpan(++temp, widthOrPrecisionChar, &nbChar); + temp += nbChar; + } + if(!*temp) /* "This is the End", (c) J. Morrisson */ + { + break; + } + + if(M4OSA_chrLength(temp)>=2) + { + + M4OSA_chrNCompare(temp, (M4OSA_Char*)"ll",2, &iResult); + if (iResult != 0) + { + count_ll++; /* I got ONE */ + temp +=2; /* span the "ll" prefix */ + } + else + { + M4OSA_chrNCompare(temp, (M4OSA_Char*)"tm",2, &iResult); + if (iResult != 0) /* à voir si ce n'est pas == 0 */ + { + count_tm++; + temp +=2; + } + else + { + M4OSA_chrNCompare(temp, (M4OSA_Char*)"aa",2, &iResult); + if (iResult != 0) /* à voir si ce n'est pas == 0 */ + { + count_aa++; + temp +=2; + } + } + } + } + + /* span the other optional prefix */ + M4OSA_chrSpan(temp, otherPrefixChar, &nbChar); + temp += nbChar; + if(!*temp) /* "This is the End", (c) J. Morrisson */ + { + break; + } + + M4OSA_chrSpan(temp, conversionChar, &nbChar); + temp += nbChar; + if(!*temp) /* "This is the End", (c) J. Morrisson */ + { + break; + } + + } + + count = count_ll + count_tm + count_aa; + + if(!count) + { + err = M4OSA_chrSPrintf(strOut,strOutMaxLen,format,marker); + + if(M4ERR_CHR_STR_OVERFLOW == err) + { + return M4ERR_STR_OVERFLOW; + } + + return M4NO_ERROR; + } + + + newFormatLength = M4OSA_chrLength(format) + 1; + +#ifdef M4OSA_64BITS_SUPPORTED +#ifdef M4OSA_FILE_POS_64_BITS_SUPPORTED + newFormatLength += (count_ll+count_tm+count_aa); +#else + newFormatLength += (count_ll+count_tm-count_aa); +#endif +#elif defined M4OSA_64BITS_NOT_SUPPORTED + newFormatLength -= (count_ll+count_tm+count_aa); +#else + return M4ERR_NOT_IMPLEMENTED; +#endif + + newFormat =(M4OSA_Char*)M4OSA_malloc(newFormatLength, + M4OSA_CHARSTAR, (M4OSA_Char*)"M4OSA_chrPrintf: newFormat"); + if(newFormat == M4OSA_NULL) return M4ERR_ALLOC; + newFormat[newFormatLength-1] = '\0'; + temp = newFormat; + /* copy format to newFormat, replacing + %[flags][width][.precision]ll[conversion] + by %[flags][width][.precision]I64[conversion] */ + while(*format) + { + M4OSA_chrSpanComplement(format, (M4OSA_Char*)"%", &nbChar); + if(nbChar) + { + M4OSA_chrNCopy(temp,format,nbChar); /* copy characters before the % character */ + format +=nbChar; + temp +=nbChar; + } + if(!*format) + { + break; + } + *temp++ = *format++; /* copy the % character */ + + M4OSA_chrSpan(format, flagChar, &nbChar); + if(nbChar) + { + M4OSA_chrNCopy(temp,format,nbChar); /* copy the flag characters */ + format +=nbChar; + temp +=nbChar; + } + if(!*format) + { + break; + } + + M4OSA_chrSpan(format, widthOrPrecisionChar, &nbChar); + if(nbChar) + { + M4OSA_chrNCopy(temp,format,nbChar); /* copy the width characters */ + format +=nbChar; + temp +=nbChar; + } + if(!*format) + { + break; + } + if(*format=='.') + { + *temp++ = *format++; /* copy the dot character */ + if(!*format) + { + break; + } + + M4OSA_chrSpan(format, widthOrPrecisionChar, &nbChar); + if(nbChar) + { + M4OSA_chrNCopy(temp,format,nbChar); /* copy the width characters */ + format +=nbChar; + temp +=nbChar; + } + if(!*format) + { + break; + } + } + if(M4OSA_chrLength(format)>=2) + { + + M4OSA_chrNCompare(format, (M4OSA_Char*)"ll",2, &iResult); + if (iResult != 0) + { +#ifdef M4OSA_64BITS_SUPPORTED + *temp++ = 'I'; /* %I64 */ + *temp++ = '6'; + *temp++ = '4'; +#else + *temp++ = 'l'; /* %l */ +#endif + format +=2; /* span the "ll" prefix */ + } + else + { + M4OSA_chrNCompare(format, (M4OSA_Char*)"tm",2, &iResult); + if (iResult != 0) + { +#ifdef M4OSA_64BITS_SUPPORTED + *temp++ = 'I'; /* %I64 */ + *temp++ = '6'; + *temp++ = '4'; +#else + *temp++ = 'l'; /* %l */ +#endif + format +=2; /* span the "tm" prefix */ + } + else + { + M4OSA_chrNCompare(format, (M4OSA_Char*)"aa",2, &iResult); + if (iResult != 0) /* à voir si ce n'est pas != 0 */ + { +#ifdef M4OSA_64BITS_SUPPORTED +#ifdef M4OSA_FILE_POS_64_BITS_SUPPORTED + *temp++ = 'I'; /* %I64 */ + *temp++ = '6'; + *temp++ = '4'; +#else + *temp++ = 'l'; +#endif +#else + *temp++ = 'l'; +#endif + format +=2; /* span the "aa" prefix */ + } + } + } + } + + M4OSA_chrSpan(format, otherPrefixChar, &nbChar); + + if(nbChar) + { + M4OSA_chrNCopy(temp,format,nbChar); /* copy the other Prefix */ + format +=nbChar; + temp +=nbChar; + } + + if(!*format) + { + break; + } + + M4OSA_chrSpan(format, conversionChar, &nbChar); + if(nbChar) + { + M4OSA_chrNCopy(temp,format,nbChar); + format += nbChar; + temp += nbChar; + } + + if(!*format) + { + break; + } + } + + err = M4OSA_chrSPrintf(strOut,strOutMaxLen,newFormat,marker); + + M4OSA_free((M4OSA_MemAddr32)newFormat); + + if (M4ERR_CHR_STR_OVERFLOW == err) + { + return M4ERR_STR_OVERFLOW; + } + else + { + return M4NO_ERROR; + } +} + diff --git a/libvideoeditor/osal/src/M4OSA_Thread.c b/libvideoeditor/osal/src/M4OSA_Thread.c new file mode 100755 index 0000000..c09b82c --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_Thread.c @@ -0,0 +1,954 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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_Thread.c + * @ingroup OSAL + * @brief Implements and manipulate threads + * @note This file implements functions to manipulate threads + ************************************************************************ +*/ + +#include <sched.h> +#include <time.h> +#include <pthread.h> +#include <errno.h> + +#include <utils/threads.h> +#include "M4OSA_Debug.h" +#include "M4OSA_Memory.h" +#include "M4OSA_Thread.h" +#include "M4OSA_Thread_priv.h" +#include "M4OSA_Mutex.h" +#include "M4OSA_Semaphore.h" +#include "M4OSA_CharStar.h" + + +void* M4OSA_threadSyncForEverDo(void *context) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + M4OSA_Bool auto_kill = M4OSA_FALSE; + + /* + M4OSA_Void* userData; + */ + + M4OSA_TRACE2_1("M4OSA_threadSyncForEverDo\t\tLPVOID 0x%x", context); + + /* + userData = threadContext->userData; + */ + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + /*if(threadContext->startCallBack != M4OSA_NULL) + { + threadContext->startCallBack(threadContext, userData); + }*/ + + threadContext->state = M4OSA_kThreadRunning; + + M4OSA_semaphorePost(threadContext->semStartStop); + + while(threadContext->state == M4OSA_kThreadRunning) + { + M4OSA_mutexUnlock(threadContext->stateMutex); + + if((threadContext->func(threadContext->param)) != M4NO_ERROR) + { + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + if(threadContext->state == M4OSA_kThreadRunning) + { + + //PR 2354 - ACO : Suppress stopping state and don't + // unlock mutex before closing the thread + threadContext->state = M4OSA_kThreadOpened; + M4OSA_mutexUnlock(threadContext->stateMutex); + return 0; + } + + M4OSA_mutexUnlock(threadContext->stateMutex); + } + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + } + + + M4OSA_semaphorePost(threadContext->semStartStop); + + + M4OSA_mutexUnlock(threadContext->stateMutex); + + + return 0; +} + + + + + +/** + ************************************************************************ + * @brief This method creates a new thread. After this call the thread is + * identified by its "context". The thread function is provided by + * the "func" parameter. This function creates & allocates a unique + * context. It's the OSAL real time responsibility for managing its + * context. It must be freed by the M4OSA_threadSyncClose function. + * The context parameter will be sent back to any OSAL core thread + * functions to allow retrieving data associated to the opened + * thread. + * @note This function creates the thread, but the thread is not running. + * @note Once the thread is created, the state is M4OSA_kThreadOpened. + * @param context:(OUT) Context of the created thread + * @param func:(IN) "doIt" function pointer to run + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_ALLOC: there is no more available memory + * @return M4ERR_CONTEXT_FAILED: the context creation failed + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncOpen(M4OSA_Context* context, + M4OSA_ThreadDoIt func) +{ + M4OSA_ThreadContext* threadContext = M4OSA_NULL; + M4OSA_ERR err_code; + + M4OSA_TRACE1_2("M4OSA_threadSyncOpen\t\tM4OSA_Context* 0x%x\t" + "M4OSA_ThreadDoIt 0x%x", context, func); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncOpen"); + + M4OSA_DEBUG_IF2(func == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncOpen"); + + *context = M4OSA_NULL; + + threadContext = + (M4OSA_ThreadContext*)M4OSA_malloc(sizeof(M4OSA_ThreadContext), + M4OSA_THREAD, (M4OSA_Char*)"M4OSA_threadSyncOpen: thread context"); + + if(threadContext == M4OSA_NULL) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_threadSyncOpen"); + + return M4ERR_ALLOC; + } + + threadContext->func = func; + threadContext->stackSize = 64 * 1024; + threadContext->name = M4OSA_NULL; + threadContext->threadID = 0; + threadContext->coreID = M4OSA_THREAD; +/* + threadContext->userData = M4OSA_NULL; + threadContext->stopCallBack = M4OSA_NULL; + threadContext->startCallBack = M4OSA_NULL; +*/ + threadContext->state = M4OSA_kThreadOpened; + threadContext->priority = M4OSA_kThreadNormalPriority ; + + err_code = M4OSA_mutexOpen(&(threadContext->stateMutex)); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + M4OSA_DEBUG(err_code, "M4OSA_threadSyncOpen: M4OSA_mutexOpen"); + + return err_code; + } + + err_code = M4OSA_semaphoreOpen(&(threadContext->semStartStop), 0); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + M4OSA_DEBUG(err_code, "M4OSA_threadSyncOpen: M4OSA_semaphoreOpen"); + + return err_code; + } + + *context = threadContext; + + return M4NO_ERROR; +} + + + + + +/** + ************************************************************************ + * @brief This method runs a specified thread. The "param" parameter + * allows the application to set a specific parameter to the + * created thread. This parameter will be used as the second one of + * the "M4OSA_ThreadDoIt" function. + * @note This method is a blocking up to the thread is running. + * Before calling this method, the state is M4OSA_kThreadOpened. + * Once the method is called, the state is M4OSA_kThreadStarting. + * Once the thread is running, the state is M4OSA_kThreadRunning. + * @note This method returns immediately. If the "threadStarted" optionID + * is not NULL, the thread will call it before running the doIt + * function. + * @param context:(IN/OUT) Context of the thread + * @param param:(IN) Application data thread parameter + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_STATE: this function cannot be called now + * @return M4ERR_THREAD_NOT_STARTED: the thread did not start + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncStart(M4OSA_Context context, + M4OSA_Void* param) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + pthread_attr_t attribute = { 0, 0, 0, 0, 0, 0 }; + int min = 0; + int max = 0; + int priority = 0; + struct sched_param sched = { 0 }; + + M4OSA_TRACE1_2("M4OSA_threadSyncStart\t\tM4OSA_Context 0x%x\tM4OSA_Void* " + "0x%x", context, param); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncStart"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncStart"); + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + if(threadContext->state != M4OSA_kThreadOpened) + { + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncStart"); + + return M4ERR_STATE; + } + + threadContext->state = M4OSA_kThreadStarting; + + M4OSA_mutexUnlock(threadContext->stateMutex); + threadContext->param = param; + + if ( 0 == pthread_attr_init( &attribute ) ) + { + if ( 0 == pthread_attr_setdetachstate( &attribute, PTHREAD_CREATE_DETACHED ) ) + { + if ( 0 == pthread_attr_setstacksize( &attribute, (size_t)threadContext->stackSize ) ) + { + if ( 0 == pthread_attr_setschedpolicy( &attribute, SCHED_OTHER ) ) + { +#if 0 + min = sched_get_priority_min( SCHED_OTHER ); + max = sched_get_priority_max( SCHED_OTHER ); + + switch(threadContext->priority) + { + case M4OSA_kThreadLowestPriority: + priority = min; + break; + case M4OSA_kThreadLowPriority: + priority = min + ( max - min ) / 4; + break; + case M4OSA_kThreadNormalPriority: + priority = min + ( max - min ) / 2; + break; + case M4OSA_kThreadHighPriority: + priority = max - ( max - min ) / 4; + break; + case M4OSA_kThreadHighestPriority: + priority = max; + break; + } +#else + /* Tentative patches to handle priorities in a better way : */ + /* Use Android's predefined priorities (range +19..-20) + *rather than Linux ones (0..99)*/ + + /* Get min and max priorities */ + min = sched_get_priority_min( SCHED_FIFO ); + max = sched_get_priority_max( SCHED_FIFO ); + + M4OSA_TRACE1_2("M4OSA_threadSyncStart MAX=%d MIN=%d", max, min); + + /* tentative modification of the priorities */ + /* Set the priority based on default android priorities */ + /* This probably requires some more tuning, + * outcome of this priority settings are not yet satisfactory */ + /* Implementing thread handling based on Android's thread creation + * helpers might bring some improvement (see threads.h) */ + switch(threadContext->priority) + { + case M4OSA_kThreadLowestPriority: + priority = ANDROID_PRIORITY_NORMAL; + break; + case M4OSA_kThreadLowPriority: + priority = ANDROID_PRIORITY_DISPLAY; + break; + case M4OSA_kThreadNormalPriority: + priority = ANDROID_PRIORITY_URGENT_DISPLAY; + break; + case M4OSA_kThreadHighPriority: + priority = ANDROID_PRIORITY_AUDIO; + break; + case M4OSA_kThreadHighestPriority: + priority = ANDROID_PRIORITY_URGENT_AUDIO; + break; + } +#endif + sched.sched_priority = priority; + + if ( 0 == pthread_attr_setschedparam( &attribute, &sched ) ) + { + if ( 0 == pthread_create( &threadContext->threadID, + &attribute, + &M4OSA_threadSyncForEverDo, + (void *)threadContext ) ) + { + if ( M4OSA_FALSE == M4OSA_ERR_IS_ERROR( M4OSA_semaphoreWait( + threadContext->semStartStop, + M4OSA_WAIT_FOREVER ) ) ) + { + return M4NO_ERROR; + } + } + } + } + } + } + pthread_attr_destroy( &attribute ); + } + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + threadContext->state = M4OSA_kThreadOpened; + + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_DEBUG(M4ERR_THREAD_NOT_STARTED, "M4OSA_threadSyncStart"); + + return M4ERR_THREAD_NOT_STARTED; +} + + + + +/** + ************************************************************************ + * @brief This method stops a specified thread. + * @note This call is a blocking one up to the "M4OSA_ThreadDoIt" + * function has returned. + * Before the method is called, the state is M4OSA_kThreadRunning. + * Once the method is called, the state is M4OSA_kThreadStopping. + * Once the thread is stopped, the state is M4OSA_kThreadOpened. + * @note This method returns once the thread has been stopped. If the + * "threadStopped" optionID is not NULL, the thread will call it + * before dying. + * @param context:(IN/OUT) Context of the thread + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_STATE: this function cannot be called now + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncStop(M4OSA_Context context) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE1_1("M4OSA_threadSyncStop\t\tM4OSA_Context 0x%x", context); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncStop"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncStop"); + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + if(threadContext->state != M4OSA_kThreadRunning) + { + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncStop"); + + return M4ERR_STATE; + } + + threadContext->state = M4OSA_kThreadStopping; + + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_semaphoreWait(threadContext->semStartStop, M4OSA_WAIT_FOREVER); + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + threadContext->state = M4OSA_kThreadOpened; + + M4OSA_mutexUnlock(threadContext->stateMutex); + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This method deletes a thread (identified by its context). After + * this call the thread and its context are no more useable. This + * function frees all the memory related to this thread. + * @note Before the method is called, the state is M4OSA_kThreadOpened. + * Once the method is called, the state is M4OSA_kThreadClosed. + * @param context:(IN/OUT) Context of the thread + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_STATE: this function cannot be called now + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncClose(M4OSA_Context context) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + M4OSA_ERR err_code; + + M4OSA_TRACE1_1("M4OSA_threadSyncClose\t\tM4OSA_Context 0x%x", context); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncClose"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncClose"); + + M4OSA_DEBUG_IF2(threadContext->state == M4OSA_kThreadClosed, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncClose"); + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + if(threadContext->state != M4OSA_kThreadOpened) + { + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncClose"); + + return M4ERR_STATE; + } + + threadContext->state = M4OSA_kThreadClosed; + + M4OSA_mutexUnlock(threadContext->stateMutex); + + err_code = M4OSA_mutexClose(threadContext->stateMutex); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + M4OSA_DEBUG(err_code, "M4OSA_threadSyncClose: M4OSA_mutexClose"); + + return err_code; + } + + err_code = M4OSA_semaphoreClose(threadContext->semStartStop); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + M4OSA_DEBUG(err_code, "M4OSA_threadSyncClose: M4OSA_semaphoreClose"); + + return err_code; + } + + if(threadContext->name != M4OSA_NULL) + { + M4OSA_free((M4OSA_MemAddr32)threadContext->name); + } + + M4OSA_free((M4OSA_MemAddr32)threadContext); + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This method asks the thread to return its state. + * @note The caller is responsible for allocating/deallocating the state + * field. + * @param context:(IN) Context of the thread + * @param state:(OUT) Thread state + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncGetState(M4OSA_Context context, + M4OSA_ThreadState* state) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE1_2("M4OSA_threadSyncGetState\t\tM4OSA_Context 0x%x\t" + "M4OSA_ThreadState* 0x%x", context, state); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncGetState"); + + M4OSA_DEBUG_IF2(state == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncGetState"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncGetState"); + + *state = threadContext->state; + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This method asks the calling thread to sleep during "timeSleep" + * milliseconds. + * @note This function does not have any context. + * @param time:(IN) Time to sleep in milliseconds + * @return M4NO_ERROR: there is no error + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSleep(M4OSA_UInt32 time) +{ + struct timespec rqtp = { 0, 0 }; + struct timespec rmtp = { 0, 0 }; + + M4OSA_TRACE1_1("M4OSA_threadSleep\t\tM4OSA_UInt32 %d", time); + + rqtp.tv_sec = (time_t)time/1000; + rqtp.tv_nsec = (time%1000) * 1000000; + nanosleep(&rqtp, &rmtp); + + return M4NO_ERROR; +} + + + + +#if(M4OSA_OPTIONID_THREAD_STARTED == M4OSA_TRUE) + +/*M4OSA_ERR M4OSA_SetThreadSyncStarted(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context ; + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncStarted\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + threadContext->startCallBack = (M4OSA_ThreadCallBack)optionValue; + + return M4NO_ERROR; +}*/ + +#endif /*M4OSA_OPTIONID_THREAD_STARTED*/ + + + + +#if(M4OSA_OPTIONID_THREAD_STOPPED == M4OSA_TRUE) + +/*M4OSA_ERR M4OSA_SetThreadSyncStopped(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncStopped\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + threadContext->stopCallBack = (M4OSA_ThreadCallBack)optionValue; + + return M4NO_ERROR; +}*/ + +#endif /*M4OSA_OPTIONID_THREAD_STOPPED*/ + + + +#if(M4OSA_OPTIONID_THREAD_PRIORITY == M4OSA_TRUE) + +M4OSA_ERR M4OSA_SetThreadSyncPriority(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + M4OSA_ThreadPriorityLevel priority + = (M4OSA_ThreadPriorityLevel)(optionValue); + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncPriority\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + if((M4OSA_UInt32)optionValue>M4OSA_kThreadLowestPriority) + { + return M4ERR_PARAMETER; + } + + threadContext->priority = priority; + + return M4NO_ERROR; +} + +#endif /*M4OSA_OPTIONID_THREAD_PRIORITY*/ + + + + +#if(M4OSA_OPTIONID_THREAD_NAME == M4OSA_TRUE) + +M4OSA_ERR M4OSA_SetThreadSyncName(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + M4OSA_Char* name = (M4OSA_Char*)optionValue; + M4OSA_UInt32 nameSize ; + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncName\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + if(threadContext->name != NULL) + { + M4OSA_free((M4OSA_MemAddr32)threadContext->name); + threadContext->name = M4OSA_NULL; + } + + if(optionValue != M4OSA_NULL) + { + nameSize = M4OSA_chrLength(name)+1; + + threadContext->name = + (M4OSA_Char*)M4OSA_malloc(nameSize, M4OSA_THREAD, + (M4OSA_Char*)"M4OSA_SetThreadSyncName: thread name"); + + if(threadContext == M4OSA_NULL) + { + return M4ERR_ALLOC; + } + + M4OSA_memcpy((M4OSA_MemAddr8)threadContext->name, (M4OSA_MemAddr8)name, + nameSize); + } + + return M4NO_ERROR; +} + +#endif /*M4OSA_OPTIONID_THREAD_NAME*/ + + +#if(M4OSA_OPTIONID_THREAD_STACK_SIZE == M4OSA_TRUE) + +M4OSA_ERR M4OSA_SetThreadSyncStackSize(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncStackSize\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + threadContext->stackSize = (M4OSA_UInt32)optionValue; + + return M4NO_ERROR; +} + +#endif /*M4OSA_OPTIONID_THREAD_STACK_SIZE*/ + + + +#if(M4OSA_OPTIONID_THREAD_USER_DATA == M4OSA_TRUE) + +/*M4OSA_ERR M4OSA_SetThreadSyncUserData(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncUserData\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + threadContext->userData = (M4OSA_Void*)optionValue; + + return M4NO_ERROR; +}*/ + +#endif /*M4OSA_OPTIONID_THREAD_USER_DATA*/ + + + + + +/** + ************************************************************************ + * @brief This method asks the core OSAL-Thread component to set the value + * associated with the optionID. The caller is responsible for + * allocating/deallocating the memory of the value field. + * @note As the caller is responsible of allocating/de-allocating the + * "value" field, the callee must copy this field to its internal + * variable. + * @param context:(IN/OUT) Context of the thread + * @param optionID:(IN) ID of the option + * @param optionValue:(IN) Value of the option + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_BAD_OPTION_ID: the optionID is not a valid one + * @return M4ERR_STATE: this option is not available now + * @return M4ERR_READ_ONLY: this option is a read only one + * @return M4ERR_NOT_IMPLEMENTED: this option is not implemented + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncSetOption(M4OSA_Context context, + M4OSA_ThreadOptionID optionID, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_threadSyncSetOption\t\tM4OSA_Context 0x%x\t" + "M4OSA_OptionID %d\tM4OSA_DataOption 0x%x", + context, optionID, optionValue); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncSetOption"); + + M4OSA_DEBUG_IF2(optionID == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncSetOption"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncSetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_THREAD), + M4ERR_BAD_OPTION_ID, "M4OSA_threadSyncSetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_WRITABLE(optionID), + M4ERR_READ_ONLY, "M4OSA_threadSyncSetOption"); + + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + if(threadContext->state != M4OSA_kThreadOpened) + { + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncSetOption"); + + return M4ERR_STATE; + } + + switch(optionID) + { +#if(M4OSA_OPTIONID_THREAD_STARTED == M4OSA_TRUE) + /*case M4OSA_ThreadStarted: + { + err_code = M4OSA_SetThreadSyncStarted(context, optionValue); + + break; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_STARTED*/ + +#if(M4OSA_OPTIONID_THREAD_STOPPED == M4OSA_TRUE) + /*case M4OSA_ThreadStopped: + { + err_code = M4OSA_SetThreadSyncStopped(context, optionValue); + + break; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_STOPPED*/ + +#if(M4OSA_OPTIONID_THREAD_USER_DATA == M4OSA_TRUE) + /*case M4OSA_ThreadUserData: + { + err_code = M4OSA_SetThreadSyncUserData(context, optionValue); + + break; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_USER_DATA*/ + +#if(M4OSA_OPTIONID_THREAD_PRIORITY == M4OSA_TRUE) + case M4OSA_ThreadPriority: + { + err_code = M4OSA_SetThreadSyncPriority(context, optionValue); + + break; + } +#endif /*M4OSA_OPTIONID_THREAD_PRIORITY*/ + +#if(M4OSA_OPTIONID_THREAD_NAME == M4OSA_TRUE) + case M4OSA_ThreadName: + { + err_code = M4OSA_SetThreadSyncName(context, optionValue); + + break; + } +#endif /*M4OSA_OPTIONID_THREAD_NAME*/ + +#if(M4OSA_OPTIONID_THREAD_STACK_SIZE == M4OSA_TRUE) + case M4OSA_ThreadStackSize: + { + err_code = M4OSA_SetThreadSyncStackSize(context, optionValue); + + break; + } +#endif /*M4OSA_OPTIONID_THREAD_STACK_SIZE*/ + + default: + { + M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_threadSyncSetOption"); + + err_code = M4ERR_NOT_IMPLEMENTED; + } + } + + M4OSA_mutexUnlock(threadContext->stateMutex); + + return err_code; +} + + + +/** + ************************************************************************ + * @brief This method asks the OSAL-Thread to return the value associated + * with the optionID. The caller is responsible for + * allocating/deallocating the memory of the value field. + * @note "optionValue" must be cast according to the type related to the + * optionID. + * @note As the caller is responsible for de-allocating the "value" + * field, the core OSAL-Thread component must perform a copy of its + * internal value to the value field. + * @param context:(IN) Context of the thread + * @param optionID:(IN) ID of the option + * @param optionValue:(OUT) Value of the option + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_BAD_OPTION_ID: the optionID is not a valid one + * @return M4ERR_WRITE_ONLY: this option is a write only one + * @return M4ERR_NOT_IMPLEMENTED: this option is not implemented + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncGetOption(M4OSA_Context context, + M4OSA_ThreadOptionID optionID, + M4OSA_DataOption* optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE1_3("M4OSA_threadSyncGetOption\t\tM4OSA_Context 0x%x\t" + "M4OSA_OptionID %d\tM4OSA_DataOption* 0x%x", + context, optionID, optionValue); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncGetOption"); + + M4OSA_DEBUG_IF2(optionID == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncGetOption"); + + M4OSA_DEBUG_IF2(optionValue == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncGetOption"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncGetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_THREAD), + M4ERR_BAD_OPTION_ID, "M4OSA_threadSyncGetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_READABLE(optionID), + M4ERR_WRITE_ONLY, "M4OSA_threadSyncGetOption"); + + switch(optionID) + { +#if(M4OSA_OPTIONID_THREAD_STARTED == M4OSA_TRUE) + /*case M4OSA_ThreadStarted: + { + M4OSA_ThreadCallBack* startCallBack = (M4OSA_ThreadCallBack*)optionValue; + + *startCallBack = threadContext->startCallBack; + + return M4NO_ERROR; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_STARTED*/ + +#if(M4OSA_OPTIONID_THREAD_STOPPED == M4OSA_TRUE) + /*case M4OSA_ThreadStopped: + { + M4OSA_ThreadCallBack* stopCallBack = (M4OSA_ThreadCallBack*)optionValue; + + *stopCallBack = threadContext->stopCallBack; + + return M4NO_ERROR; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_STOPPED*/ + +#if(M4OSA_OPTIONID_THREAD_USER_DATA == M4OSA_TRUE) + /*case M4OSA_ThreadUserData: + { + M4OSA_Void** userData = (M4OSA_Void**)optionValue; + + *userData = threadContext->userData; + + return M4NO_ERROR; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_USER_DATA*/ + +#if(M4OSA_OPTIONID_THREAD_PRIORITY == M4OSA_TRUE) + case M4OSA_ThreadPriority: + { + M4OSA_ThreadPriorityLevel* priority = + (M4OSA_ThreadPriorityLevel*)optionValue; + + *priority = threadContext->priority; + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_THREAD_PRIORITY*/ + +#if(M4OSA_OPTIONID_THREAD_NAME == M4OSA_TRUE) + case M4OSA_ThreadName: + { + M4OSA_Char** name = (M4OSA_Char**)optionValue; + + *name = threadContext->name; + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_THREAD_NAME*/ + +#if(M4OSA_OPTIONID_THREAD_STACK_SIZE == M4OSA_TRUE) + case M4OSA_ThreadStackSize: + { + M4OSA_UInt32* stackSize = (M4OSA_UInt32*)optionValue; + + *stackSize = threadContext->stackSize; + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_THREAD_STACK_SIZE*/ + + default: + break; + } + + M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_threadSyncGetOption"); + + return M4ERR_NOT_IMPLEMENTED; +} + diff --git a/libvideoeditor/osal/src/M4PSW_DebugTrace.c b/libvideoeditor/osal/src/M4PSW_DebugTrace.c new file mode 100755 index 0000000..71a6a06 --- /dev/null +++ b/libvideoeditor/osal/src/M4PSW_DebugTrace.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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 M4PSW_DebugTrace.c + * @brief Default trace function for debugging macros + * @note This file gives the default implementation of the trace function + * used in the debug instrumentation macros, based on printf. + * Application writers are strongly encouraged to implement their + * own "M4OSA_DebugTrace". + ************************************************************************ +*/ + + +#include <stdio.h> /*for printf */ + +#include "M4OSA_Types.h" +#include "M4OSA_Error.h" + +/*#define NO_FILE */ /* suppresses the file name print out */ + + +/** + ************************************************************************ + * void M4OSA_DebugTrace(M4OSA_Int32 line, char* file, M4OSA_Int32 level, + * M4OSA_Char* cond, char* msg, M4OSA_ERR err) + * @brief This function implements the trace for debug tests + * @note This function is to be called in the debug macros only. + * This implementation uses printf. + * @param line (IN): the line number in the source file + * @param file (IN): the source file name + * @param level (IN): the debug level + * @param msg (IN): the error message + * @param err (IN): the return value (error code) + * @return none + ************************************************************************ +*/ + +M4OSAL_TRACE_EXPORT_TYPE void M4OSA_DebugTrace(M4OSA_Int32 line, + M4OSA_Char* file, + M4OSA_Int32 level, + M4OSA_Char* cond, + M4OSA_Char* msg, + M4OSA_ERR err) +{ + M4OSA_Int32 i; + + /* try to "indent" the resulting traces depending on the level */ + for (i =0 ; i < level; i ++) + { + printf(" "); + } + +#ifdef NO_FILE + printf("Error: %li, on %s: %s\n",err,cond,msg); +#else /* NO_FILE */ + printf("Error: %li, on %s: %s Line %lu in: %s\n",err,cond,msg,line,file); +#endif /* NO_FILE */ + +} + +M4OSAL_TRACE_EXPORT_TYPE M4OSA_Void M4OSA_DEBUG_traceFunction(M4OSA_UInt32 line, + M4OSA_Char* fileName, + M4OSA_UInt32 level, + M4OSA_Char* stringCondition, + M4OSA_Char* message, + M4OSA_ERR returnedError) +{ + M4OSA_DebugTrace(line, fileName, level, stringCondition, message, returnedError); +} + diff --git a/libvideoeditor/osal/src/M4PSW_MemoryInterface.c b/libvideoeditor/osal/src/M4PSW_MemoryInterface.c new file mode 100755 index 0000000..1dd4d3a --- /dev/null +++ b/libvideoeditor/osal/src/M4PSW_MemoryInterface.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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 M4PSW_MemoryInterface.c + * @brief Memory Interface + * @note Implementation of the osal memory functions + ************************************************************************* +*/ + +#include <stdlib.h> +#include <memory.h> + +#include <time.h> +#include "M4OSA_Memory.h" +#ifndef M4VPS_ADVANCED_MEMORY_MANAGER +/** + ************************************************************************ + * @fn M4OSA_MemAddr32 M4OSA_malloc(M4OSA_UInt32 size, + * M4OSA_CoreID coreID, + * M4OSA_Char* string) + * @brief this function allocates a memory block (at least 32 bits aligned) + * @note + * @param size (IN): size of allocated block in bytes + * @param coreID (IN): identification of the caller component + * @param string (IN): description of the allocated block (null terminated) + * @return address of the allocated block, M4OSA_NULL if no memory available + ************************************************************************ +*/ + +M4OSA_MemAddr32 M4OSA_malloc(M4OSA_UInt32 size, + M4OSA_CoreID coreID, + M4OSA_Char* string) +{ + M4OSA_MemAddr32 Address = M4OSA_NULL; + + /** + * If size is 0, malloc on WIN OS allocates a zero-length item in + * the heap and returns a valid pointer to that item. + * On other platforms, malloc could returns an invalid pointer + * So, DON'T allocate memory of 0 byte */ + if (size == 0) + { + return Address; + } + + if (size%4 != 0) + { + size = size + 4 - (size%4); + } + + Address = (M4OSA_MemAddr32) malloc(size); + + return Address; +} + + +/** + ************************************************************************ + * @fn M4OSA_Void M4OSA_free(M4OSA_MemAddr32 address) + * @brief this function free the provided memory block + * @note As in stlib.h, this function does nothing if address is NULL. + * @param address (IN): address of the block to free + * @return none + ************************************************************************ +*/ + +M4OSA_Void M4OSA_free (M4OSA_MemAddr32 address) +{ + free(address); +} + + +/** + ************************************************************************ + * @fn M4OSA_Void M4OSA_memset(M4OSA_MemAddr8 block, + * M4OSA_UInt32 size, + * M4OSA_UInt8 value) + * @brief this function initializes the provided memory block with value + * @note + * @param block (IN): address of block to fill + * @param size (IN): size of the provided block + * @param value (IN): value used for initialization + * @return none + ************************************************************************ +*/ + +M4OSA_Void M4OSA_memset(M4OSA_MemAddr8 block, + M4OSA_UInt32 size, + M4OSA_UInt8 value) +{ + memset((void*)block, value, size); +} + + +/** + ************************************************************************ + * @fn M4OSA_Void M4OSA_memcpy(M4OSA_MemAddr8 outputBlock, + * M4OSA_MemAddr8 inputBlock, + * M4OSA_UInt32 size) + * @brief this function copies 'size' bytes from inputBlock to outputBlock + * @note + * @param outputBlock (IN): address of block to fill + * @param inputBlock (IN): address of the input block + * @param size (IN): size of the block to copy (in bytes) + * @return none + ************************************************************************ +*/ + +M4OSA_Void M4OSA_memcpy(M4OSA_MemAddr8 outputBlock, + M4OSA_MemAddr8 inputBlock, + M4OSA_UInt32 size) +{ + memcpy((void*)outputBlock, (void*)inputBlock, size); +} + +/** + ************************************************************************ + * @fn M4OSA_MemAddr8 M4OSA_memmove(M4OSA_MemAddr8 outputBlock, M4OSA_MemAddr8 inputBlock, M4OSA_UInt32 size) + * @brief this function moves 'size' bytes from inputBlock to outputBlock + * unlike M4OSA_memcpy, the two buffers can have an overlap. + * @note increment memcpy byte number (François VALETTE) + * @param outputBlock (IN): address of block to fill + * @param inputBlock (IN): address of the input block + * @param size (IN): size of the block to copy (in bytes) + * @return address of the output block, i.e. the first parameter + ************************************************************************ +*/ +M4OSA_MemAddr8 M4OSA_memmove(M4OSA_MemAddr8 outputBlock, + M4OSA_MemAddr8 inputBlock, + M4OSA_UInt32 size) +{ + return memmove((void*)outputBlock, (void*)inputBlock, size); +} + +/** + ************************************************************************ + * @fn M4OSA_Int32 M4OSA_memcmp(M4OSA_MemAddr8 address1, M4OSA_MemAddr8 address2, M4OSA_UInt32 size) + * @brief this function compares the first 'size' bytes of address1 and + 'address2' and return a value indicating their relationship. + * @note + * @param address1 (IN): memory address 1 + * @param address2 (IN): memory address 2 + * @param size (IN): size of the block to compare (in bytes) + * @return +1, if first bytes of adress1 are smaller than those of address2 + * @return 0, if both blocks are identical + * @return -1, if first bytes of address1 are bigger than those of address2 + ************************************************************************ +*/ + +M4OSA_Int32 M4OSA_memcmp(M4OSA_MemAddr8 address1, + M4OSA_MemAddr8 address2, + M4OSA_UInt32 size) +{ + M4OSA_Int32 i32_result = memcmp(address1, address2, size); + if (i32_result > 0) { + return 1; + } + else if (i32_result < 0) { + return((M4OSA_Int32)-1); + } + return 0; +} + + + + +#endif + diff --git a/libvideoeditor/osal/src/M4PSW_Trace.c b/libvideoeditor/osal/src/M4PSW_Trace.c new file mode 100755 index 0000000..ef39d82 --- /dev/null +++ b/libvideoeditor/osal/src/M4PSW_Trace.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * 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 M4PSW_Trace.c + * @brief Trace function for trace macros + * @note This file gives the implementation of the trace function used + * in the trace instrumentation macros + ************************************************************************ +*/ + + +#include <stdio.h> /*for printf */ +#include <stdarg.h> /* ANSI C macros and defs for variable args */ +#include "utils/Log.h" + +#include "M4OSA_Types.h" +#include "M4OSA_Debug.h" + +#define NO_FILE /* suppresses the file name print out */ + +#define MAX_STRING_SIZE 1024 + +/** + ************************************************************************ + * void M4OSA_Trace(M4OSA_Int32 line, M4OSA_Char* file ,M4OSA_Int32 level, + * M4OSA_Char* format, ...) + * @brief This function implements the trace for debug tests + * @note This implementation uses printf. First the variables are retrieved using + * ANSI C defs and macros which enable to access a variable number of arguments. + * Then the printf is done (with some ornemental adds). + * @param level (IN): the debug level + * @param format (IN): the "printf" formated string + * @param ... (IN): as many parameters as required ... + * @return none + ************************************************************************ +*/ + +M4OSAL_TRACE_EXPORT_TYPE void M4OSA_Trace(M4OSA_Int32 line, M4OSA_Char* file , + M4OSA_Int32 level, M4OSA_Char* format, ...) +{ + M4OSA_Char message[MAX_STRING_SIZE]; + M4OSA_Int32 i; + va_list marker; /* pointer to list of arguments */ + + /* get the var arguments into the string message to be able to print */ + va_start(marker,format); /* set ptr to first argument in the list of arguments passed to the function */ + vsprintf((char *)message, (const char *)format,marker ); /* formats and writes the data into message */ + va_end(marker); /* reset pointer to NULL */ + + /* do the actual print */ +#ifdef NO_FILE + __android_log_print(ANDROID_LOG_INFO, "LifeVibesTrace", "%s", (char*)message); +#else /* NO_FILE */ + __android_log_print(ANDROID_LOG_INFO, "LifeVibesTrace", "%s", "%s at %lu in %s", + (char *)message, line, file); +#endif /* NO_FILE */ + +} + +M4OSAL_TRACE_EXPORT_TYPE M4OSA_Void M4OSA_TRACE_traceFunction(M4OSA_UInt32 line, + M4OSA_Char* fileName, + M4OSA_CoreID coreID, + M4OSA_UInt32 level, + M4OSA_Char* stringMsg, ...) +{ + M4OSA_Char message[MAX_STRING_SIZE]; + M4OSA_Int32 i; + va_list marker; /* pointer to list of arguments */ + + /* get the var arguments into the string message to be able to print */ + va_start(marker,stringMsg); /* set ptr to first argument in the list of arguments passed to the function */ + vsprintf((char *)message, (const char *)stringMsg,marker ); /* formats and writes the data into message */ + va_end(marker); /* reset pointer to NULL */ + + /* do the actual print */ +#ifdef NO_FILE + __android_log_print(ANDROID_LOG_INFO, "LifeVibesTrace", "%s", (char*)message); +#else /* NO_FILE */ + __android_log_print(ANDROID_LOG_INFO, "LifeVibesTrace", "%s", "%s at %lu in %s", + (char *)message, line, (char*)file); +#endif /* NO_FILE */ + +} + |