diff options
Diffstat (limited to 'portable/src/PANSIFileImpl.c')
-rw-r--r-- | portable/src/PANSIFileImpl.c | 449 |
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); +} |