summaryrefslogtreecommitdiff
path: root/portable/src/PANSIFileImpl.c
diff options
context:
space:
mode:
Diffstat (limited to 'portable/src/PANSIFileImpl.c')
-rw-r--r--portable/src/PANSIFileImpl.c449
1 files changed, 449 insertions, 0 deletions
diff --git a/portable/src/PANSIFileImpl.c b/portable/src/PANSIFileImpl.c
new file mode 100644
index 0000000..6d9a261
--- /dev/null
+++ b/portable/src/PANSIFileImpl.c
@@ -0,0 +1,449 @@
+/*---------------------------------------------------------------------------*
+ * PANSIFileImpl.c *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * 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. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+#include "errno.h"
+#include "passert.h"
+#include "pendian.h"
+#include "PFileImpl.h"
+#include "PANSIFileImpl.h"
+#include "PFileSystem.h"
+#include "ESR_ReturnCode.h"
+#include "plog.h"
+#include "pmemory.h"
+#include "pstdio.h"
+#include "ptypes.h"
+
+#define MTAG NULL
+
+ESR_ReturnCode PANSIFileCreateImpl(const LCHAR* filename, ESR_BOOL isLittleEndian, PFile** self)
+{
+ PANSIFileImpl* impl = NULL;
+ ESR_ReturnCode rc;
+
+ impl = NEW(PANSIFileImpl, MTAG);
+ if (impl == NULL)
+ {
+ rc = ESR_OUT_OF_MEMORY;
+ PLogError(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+
+ PFileCreateImpl(&impl->Interface.Interface, filename, isLittleEndian);
+ impl->Interface.Interface.close = &PANSIFileCloseImpl;
+ impl->Interface.Interface.clearError = &PANSIFileClearErrorImpl;
+ impl->Interface.Interface.destroy = &PANSIFileDestroyImpl;
+ impl->Interface.Interface.fgetc = &PANSIFileFgetcImpl;
+ impl->Interface.Interface.fgets = &PANSIFileFgetsImpl;
+ impl->Interface.Interface.getPosition = &PANSIFileGetPositionImpl;
+ impl->Interface.Interface.hideMemoryAllocation = &PANSIFileHideMemoryAllocation;
+ impl->Interface.Interface.isEOF = &PANSIFileIsEOFImpl;
+ impl->Interface.Interface.isErrorSet = &PANSIFileIsErrorSetImpl;
+ impl->Interface.Interface.isOpen = &PANSIFileIsOpenImpl;
+ impl->Interface.Interface.open = &PANSIFileOpenImpl;
+ impl->Interface.Interface.read = &PANSIFileReadImpl;
+ impl->Interface.Interface.seek = &PANSIFileSeekImpl;
+ impl->Interface.Interface.flush = &PANSIFileFlushImpl;
+ impl->Interface.Interface.write = &PANSIFileWriteImpl;
+
+ impl->Interface.filename[0] = 0;
+ impl->value = NULL;
+
+ LSTRCAT(impl->Interface.filename, filename);
+ *self = &impl->Interface.Interface;
+ return ESR_SUCCESS;
+CLEANUP:
+ if (impl != NULL)
+ impl->Interface.Interface.destroy(&impl->Interface.Interface);
+ return rc;
+}
+
+ESR_ReturnCode PANSIFileDestroyImpl(PFile* self)
+{
+ ESR_ReturnCode rc;
+
+ CHK(rc, PFileDestroyImpl(self));
+ FREE(self);
+ return ESR_SUCCESS;
+CLEANUP:
+ return rc;
+}
+
+
+#ifdef USE_THREAD
+#define LOCK_MUTEX(rc, impl) \
+ if (impl->Interface.lock != NULL) \
+ CHKLOG(rc, PtrdMonitorLock(impl->Interface.lock));
+#else
+#define LOCK_MUTEX(rc, impl)
+#endif
+
+
+#ifdef USE_THREAD
+#define CLEANUP_AND_RETURN(rc, impl) \
+ if (impl->Interface.lock!=NULL) \
+ CHKLOG(rc, PtrdMonitorUnlock(impl->Interface.lock)); \
+ return ESR_SUCCESS; \
+ CLEANUP: \
+ if (impl->Interface.lock!=NULL) \
+ PtrdMonitorUnlock(impl->Interface.lock); \
+ return rc;
+#else
+#define CLEANUP_AND_RETURN(rc, impl) \
+ return ESR_SUCCESS; \
+ CLEANUP: \
+ return rc;
+#endif
+
+
+ESR_ReturnCode PANSIFileOpenImpl(PFile* self, const LCHAR* mode)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ if (impl->value != NULL)
+ {
+ rc = ESR_ALREADY_OPEN;
+ PLogError(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ impl->value = fopen(impl->Interface.filename, mode);
+
+ if (impl->value == NULL)
+ {
+ LCHAR path[P_PATH_MAX];
+ size_t len;
+
+ len = P_PATH_MAX;
+ CHKLOG(rc, PFileSystemGetcwd(path, &len));
+ rc = ESR_OPEN_ERROR;
+ /* PLOG_DBG_TRACE((L("%s: filename=%s, cwd=%s"), ESR_rc2str(rc), impl->Interface.filename, path)); */
+ PLogError(L("%s: filename=%s, cwd=%s"), ESR_rc2str(rc), impl->Interface.filename, path);
+ goto CLEANUP;
+ }
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileCloseImpl(PFile* self)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ if (fclose(impl->value) != 0)
+ {
+ rc = ESR_CLOSE_ERROR;
+ PLogMessage(L("%s: file %s, handle"), ESR_rc2str(rc), impl->Interface.filename, impl->value);
+ goto CLEANUP;
+ }
+ impl->value = NULL;
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileReadImpl(PFile* self, void* buffer, size_t size, size_t* count)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ if (count == NULL)
+ {
+ rc = ESR_INVALID_ARGUMENT;
+ PLogError(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+
+ if (size != 0 && *count != 0)
+ {
+ ESR_BOOL needToSwap;
+
+ *count = fread(buffer, size, *count, impl->value);
+ if (*count == 0 && ferror(impl->value))
+ {
+ rc = ESR_READ_ERROR;
+ PLogMessage(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+
+#ifdef __LITTLE_ENDIAN
+ needToSwap = !impl->Interface.littleEndian;
+#else
+ needToSwap = impl->Interface.littleEndian;
+#endif
+
+ if (needToSwap)
+ swap_byte_order(buffer, *count, size);
+ }
+ else
+ *count = 0;
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileWriteImpl(PFile* self, void* buffer, size_t size, size_t* count)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+ size_t requested = *count;
+
+ LOCK_MUTEX(rc, impl);
+ if (count == NULL)
+ {
+ rc = ESR_INVALID_ARGUMENT;
+ PLogError(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ if (size != 0 && *count != 0)
+ {
+ ESR_BOOL needToSwap;
+ void* temp;
+
+#ifdef __LITTLE_ENDIAN
+ needToSwap = !impl->Interface.littleEndian;
+#else
+ needToSwap = impl->Interface.littleEndian;
+#endif
+ if (needToSwap)
+ {
+ temp = MALLOC(*count * size, MTAG);
+ if (temp == NULL)
+ {
+ rc = ESR_OUT_OF_MEMORY;
+ PLogError(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ memcpy(temp, buffer, *count * size);
+
+ swap_byte_order(temp, *count, size);
+ }
+ else
+ temp = buffer;
+
+ *count = fwrite(temp, size, *count, impl->value);
+ if (needToSwap)
+ {
+ FREE(temp);
+ temp = NULL;
+ }
+
+ if (*count < requested)
+ {
+ rc = ESR_WRITE_ERROR;
+ PLogMessage(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ }
+ else
+ *count = 0;
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileFlushImpl(PFile* self)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ if (fflush(impl->value) != 0)
+ {
+ rc = ESR_FLUSH_ERROR;
+ PLogMessage(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileSeekImpl(PFile* self, long offset, int origin)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ if (fseek(impl->value, offset, origin) != 0)
+ {
+ rc = ESR_SEEK_ERROR;
+ PLogMessage(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileGetPositionImpl(PFile* self, size_t* position)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+ long pos;
+
+ LOCK_MUTEX(rc, impl);
+ pos = ftell(impl->value);
+ if (pos == -1)
+ {
+ switch (errno)
+ {
+ case EBADF:
+ rc = ESR_INVALID_STATE;
+ PLogError(L("%s: Got EBADF"), rc);
+ goto CLEANUP;
+ case EINVAL:
+ rc = ESR_INVALID_STATE;
+ PLogError(L("%s: Got EINVAL"), rc);
+ goto CLEANUP;
+ default:
+ rc = ESR_INVALID_STATE;
+ PLogError(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ }
+ *position = pos;
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileIsOpenImpl(PFile* self, ESR_BOOL* isOpen)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ if (isOpen == NULL)
+ {
+ rc = ESR_INVALID_ARGUMENT;
+ PLogError(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ *isOpen = impl->value != NULL;
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileIsEOFImpl(PFile* self, ESR_BOOL* isEof)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ if (isEof == NULL)
+ {
+ rc = ESR_INVALID_ARGUMENT;
+ PLogError(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+#ifdef NO_FEOF
+ {
+ long posCur; /* remember current file position */
+ long posEnd; /* end of file position */
+
+ posCur = ftell(impl->value);
+ fseek(impl->value, 0, SEEK_END);
+ posEnd = ftell(impl->value);
+ *isEof = (posCur == posEnd);
+ fseek(impl->value, posCur, SEEK_SET); /* restore position in file */
+ }
+#else
+ *isEof = feof(impl->value) != 0;
+#endif
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileIsErrorSetImpl(PFile* self, ESR_BOOL* isError)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ if (isError == NULL)
+ {
+ rc = ESR_INVALID_ARGUMENT;
+ PLogError(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ *isError = ferror(impl->value) != 0;
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileClearErrorImpl(PFile* self)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ clearerr(impl->value);
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileFgetsImpl(PFile* self, LCHAR* string, int n, LCHAR** result)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+ LCHAR* temp;
+
+ LOCK_MUTEX(rc, impl);
+ temp = fgets(string, n, impl->value);
+ if (result != NULL)
+ *result = temp;
+ if (temp == NULL && ferror(impl->value))
+ {
+ rc = ESR_INVALID_STATE;
+ PLogMessage(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileFgetcImpl(PFile* self, LINT* result)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ *result = fgetc(impl->value);
+ if (*result == PEOF && ferror(impl->value))
+ {
+ rc = ESR_INVALID_STATE;
+ PLogMessage(ESR_rc2str(rc));
+ goto CLEANUP;
+ }
+ CLEANUP_AND_RETURN(rc, impl);
+}
+
+ESR_ReturnCode PANSIFileHideMemoryAllocation(PFile* self)
+{
+ PANSIFileImpl* impl = (PANSIFileImpl*) self;
+ ESR_ReturnCode rc;
+
+ LOCK_MUTEX(rc, impl);
+ rc = PMemLogFree(self);
+ if (rc != ESR_SUCCESS)
+ {
+ pfprintf(PSTDERR, L("%s: PMemDumpLogFile() at %s:%d"), ESR_rc2str(rc), __FILE__, __LINE__);
+ goto CLEANUP;
+ }
+ rc = PMemLogFree(impl->Interface.filename);
+ if (rc != ESR_SUCCESS)
+ {
+ pfprintf(PSTDERR, L("%s: PMemDumpLogFile() at %s:%d"), ESR_rc2str(rc), __FILE__, __LINE__);
+ goto CLEANUP;
+ }
+#ifdef USE_THREAD
+ rc = PMemLogFree(impl->Interface.lock);
+ if (rc != ESR_SUCCESS)
+ {
+ pfprintf(PSTDERR, L("%s: PMemDumpLogFile() at %s:%d"), ESR_rc2str(rc), __FILE__, __LINE__);
+ goto CLEANUP;
+ }
+#endif
+ CLEANUP_AND_RETURN(rc, impl);
+}