| /*---------------------------------------------------------------------------* |
| * PFile.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 "LCHAR.h" |
| #include "pendian.h" |
| #include "PFile.h" |
| #include "PFileSystem.h" |
| #include "plog.h" |
| #include "pstdio.h" |
| |
| |
| ESR_ReturnCode PFileDestroy(PFile* self) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->destroy(self); |
| } |
| |
| ESR_ReturnCode PFileOpen(PFile* self, const LCHAR* mode) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->open(self, mode); |
| } |
| |
| ESR_ReturnCode PFileClose(PFile* self) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->close(self); |
| } |
| |
| ESR_ReturnCode PFileRead(PFile* self, void* buffer, size_t size, size_t* count) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->read(self, buffer, size, count); |
| } |
| |
| ESR_ReturnCode PFileWrite(PFile* self, void* buffer, size_t size, size_t* count) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->write(self, buffer, size, count); |
| } |
| |
| ESR_ReturnCode PFileFlush(PFile* self) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->flush(self); |
| } |
| |
| ESR_ReturnCode PFileSeek(PFile* self, long offset, int origin) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->seek(self, offset, origin); |
| } |
| |
| |
| ESR_ReturnCode PFileGetPosition(PFile* self, size_t* position) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->getPosition(self, position); |
| } |
| |
| ESR_ReturnCode PFileIsOpen(PFile* self, ESR_BOOL* isOpen) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->isOpen(self, isOpen); |
| } |
| |
| ESR_ReturnCode PFileIsEOF(PFile* self, ESR_BOOL* isEof) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->isEOF(self, isEof); |
| } |
| |
| ESR_ReturnCode PFileGetFilename(PFile* self, LCHAR* filename, size_t* len) |
| { |
| ESR_ReturnCode rc; |
| |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| rc = self->getFilename(self, filename, len); |
| return rc; |
| } |
| |
| ESR_ReturnCode PFileIsErrorSet(PFile* self, ESR_BOOL* isError) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->isErrorSet(self, isError); |
| } |
| |
| ESR_ReturnCode PFileClearError(PFile* self) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->clearError(self); |
| } |
| |
| ESR_ReturnCode PFileVfprintf(PFile* self, int* result, const LCHAR* format, va_list args) |
| { |
| ESR_ReturnCode rc; |
| |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| rc = self->vfprintf(self, result, format, args); |
| return rc; |
| } |
| |
| ESR_ReturnCode PFileFgetc(PFile* self, LINT* result) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->fgetc(self, result); |
| } |
| |
| ESR_ReturnCode PFileFgets(PFile* self, LCHAR* string, int n, LCHAR** result) |
| { |
| if (self == NULL) |
| { |
| PLogError(L("ESR_INVALID_ARGUMENT")); |
| return ESR_INVALID_ARGUMENT; |
| } |
| return self->fgets(self, string, n, result); |
| } |
| |
| ESR_ReturnCode PFileReadInt(PFile* self, int* value) |
| { |
| LCHAR number[MAX_INT_DIGITS+1]; |
| size_t i, bufferSize, count, totalRead = 0; |
| ESR_ReturnCode rc; |
| |
| /* Skip whitespace before token */ |
| do |
| { |
| count = pfread(number, sizeof(LCHAR), MAX_INT_DIGITS, self); |
| totalRead += count; |
| if (count < MAX_INT_DIGITS) |
| { |
| if (pferror(self)) |
| { |
| rc = ESR_READ_ERROR; |
| PLogError(ESR_rc2str(rc)); |
| goto CLEANUP; |
| } |
| else |
| { |
| rc = ESR_INVALID_STATE; |
| PLogError(L("%s: reached end of file before finding token"), ESR_rc2str(rc)); |
| goto CLEANUP; |
| } |
| } |
| /* locate first non-whitespace character */ |
| for (i = 0; i < count && LISSPACE(number[i]); ++i); |
| } |
| while (i == count); |
| bufferSize = count - i; |
| |
| /* Fill remainder of buffer */ |
| if (bufferSize < MAX_INT_DIGITS) |
| { |
| count = pfread(number + bufferSize, sizeof(LCHAR), MAX_INT_DIGITS - bufferSize, self); |
| bufferSize += count; |
| totalRead += count; |
| if (count < MAX_INT_DIGITS - bufferSize && pferror(self)) |
| { |
| rc = ESR_READ_ERROR; |
| PLogError(ESR_rc2str(rc)); |
| goto CLEANUP; |
| } |
| } |
| |
| /* locate first whitespace character */ |
| for (i = 0; i < bufferSize && !LISSPACE(number[i]); ++i); |
| if (i < bufferSize) |
| { |
| /* unread anything after the token */ |
| if (PFileSeek(self, - (int)(bufferSize - i), SEEK_CUR)) |
| { |
| rc = ESR_SEEK_ERROR; |
| PLogError(ESR_rc2str(rc)); |
| } |
| totalRead -= bufferSize - i; |
| number[i] = L('\0'); |
| } |
| |
| if (number[0] != L('-') && !LISDIGIT(number[0])) |
| { |
| rc = ESR_INVALID_STATE; |
| PLogError(L("%s: token was not number (%s)"), ESR_rc2str(rc), number); |
| goto CLEANUP; |
| } |
| |
| CHKLOG(rc, lstrtoi(number, value, 10)); |
| return rc; |
| CLEANUP: |
| if (PFileSeek(self, - (int) count, SEEK_CUR)) |
| PLogError(L("ESR_SEEK_ERROR")); |
| return rc; |
| } |
| |
| ESR_ReturnCode PFileReadLCHAR(PFile* self, LCHAR* value, size_t len) |
| { |
| size_t i, bufferSize, count, totalRead = 0; |
| ESR_ReturnCode rc = ESR_SUCCESS; |
| |
| /* Skip whitespace before token */ |
| do |
| { |
| count = pfread(value, sizeof(LCHAR), len, self); |
| totalRead += count; |
| if (count < len) |
| { |
| if (pferror(self)) |
| { |
| rc = ESR_READ_ERROR; |
| PLogError(ESR_rc2str(rc)); |
| goto CLEANUP; |
| } |
| else |
| { |
| rc = ESR_INVALID_STATE; |
| PLogError(L("%s: reached end of file before finding token"), ESR_rc2str(rc)); |
| goto CLEANUP; |
| } |
| } |
| /* locate first non-whitespace character */ |
| for (i = 0; i < count && LISSPACE(value[i]); ++i); |
| } |
| while (i == count); |
| bufferSize = count - i; |
| |
| /* Fill remainder of buffer */ |
| if (bufferSize < len) |
| { |
| count = pfread(value + bufferSize, sizeof(LCHAR), len - bufferSize, self); |
| bufferSize += count; |
| totalRead += count; |
| if (count < len - bufferSize && pferror(self)) |
| { |
| rc = ESR_READ_ERROR; |
| PLogError(ESR_rc2str(rc)); |
| goto CLEANUP; |
| } |
| } |
| |
| /* locate first whitespace character */ |
| for (i = 0; i < bufferSize && !LISSPACE(value[i]); ++i); |
| if (i < bufferSize) |
| { |
| /* unread anything after the token */ |
| if (PFileSeek(self, -(int)(bufferSize - i), SEEK_CUR)) |
| { |
| rc = ESR_SEEK_ERROR; |
| PLogError(ESR_rc2str(rc)); |
| } |
| totalRead -= bufferSize - i; |
| value[i] = L('\0'); |
| } |
| return rc; |
| CLEANUP: |
| if (PFileSeek(self, - (int) count, SEEK_CUR)) |
| PLogError(L("ESR_SEEK_ERROR")); |
| return rc; |
| } |
| |
| PFile* pfopen(const LCHAR* filename, const LCHAR* mode) |
| { |
| PFile* result; |
| ESR_ReturnCode rc; |
| ESR_BOOL isLittleEndian; |
| |
| #if __BYTE_ORDER==__LITTLE_ENDIAN |
| isLittleEndian = ESR_TRUE; |
| #else |
| isLittleEndian = ESR_FALSE; |
| #endif |
| |
| rc = PFileSystemCreatePFile(filename, isLittleEndian, &result); |
| if (rc != ESR_SUCCESS) |
| return NULL; |
| rc = result->open(result, mode); |
| if (rc != ESR_SUCCESS) |
| { |
| result->destroy(result); |
| return NULL; |
| } |
| return result; |
| } |
| |
| size_t pfread(void* buffer, size_t size, size_t count, PFile* stream) |
| { |
| ESR_ReturnCode rc; |
| |
| rc = PFileRead(stream, buffer, size, &count); |
| if (rc != ESR_SUCCESS) |
| return 0; |
| return count; |
| } |
| |
| size_t pfwrite(const void* buffer, size_t size, size_t count, PFile* stream) |
| { |
| ESR_ReturnCode rc; |
| |
| rc = PFileWrite(stream, buffer, size, &count); |
| if (rc != ESR_SUCCESS) |
| return 0; |
| return count; |
| } |
| |
| int pfclose(PFile* stream) |
| { |
| ESR_ReturnCode rc; |
| |
| rc = PFileDestroy(stream); |
| if (rc != ESR_SUCCESS) |
| return PEOF; |
| return 0; |
| } |
| |
| void prewind(PFile* stream) |
| { |
| PFileSeek(stream, 0, SEEK_SET); |
| } |
| |
| int pfseek(PFile* stream, long offset, int origin) |
| { |
| ESR_ReturnCode rc; |
| |
| rc = PFileSeek(stream, offset, origin); |
| if (rc != ESR_SUCCESS) |
| return 1; |
| return 0; |
| } |
| |
| long pftell(PFile* stream) |
| { |
| size_t result; |
| ESR_ReturnCode rc; |
| |
| rc = PFileGetPosition(stream, &result); |
| if (rc != ESR_SUCCESS) |
| return -1; |
| return result; |
| } |
| |
| int pfeof(PFile* stream) |
| { |
| ESR_BOOL eof; |
| |
| PFileIsEOF(stream, &eof); |
| if (!eof) |
| return 0; |
| return 1; |
| } |
| |
| int pferror(PFile* stream) |
| { |
| ESR_BOOL error; |
| |
| PFileIsErrorSet(stream, &error); |
| if (!error) |
| return 0; |
| return 1; |
| } |
| |
| void pclearerr(PFile* stream) |
| { |
| PFileClearError(stream); |
| } |
| |
| int pfflush(PFile* stream) |
| { |
| ESR_ReturnCode rc; |
| |
| rc = PFileFlush(stream); |
| if (rc != ESR_SUCCESS) |
| return PEOF; |
| return 0; |
| } |
| |
| LCHAR* pfgets(LCHAR* string, int n, PFile* self) |
| { |
| LCHAR* result; |
| ESR_ReturnCode rc; |
| |
| rc = PFileFgets(self, string, n, &result); |
| if (rc != ESR_SUCCESS) |
| return NULL; |
| return result; |
| } |
| |
| LINT pfgetc(PFile* self) |
| { |
| LINT result; |
| ESR_ReturnCode rc; |
| |
| rc = PFileFgetc(self, &result); |
| if (rc != ESR_SUCCESS) |
| return PEOF; |
| return result; |
| } |
| |
| int pfprintf(PFile* stream, const LCHAR* format, ...) |
| { |
| #ifdef FINAL_RELEASE |
| return 0; |
| #else |
| va_list args; |
| int result; |
| ESR_ReturnCode rc; |
| |
| va_start(args, format); |
| rc = PFileVfprintf(stream, &result, format, args); |
| va_end(args); |
| if (rc != ESR_SUCCESS) |
| return -1; |
| return result; |
| #endif |
| } |
| |
| int pvfprintf(PFile* stream, const LCHAR* format, va_list argptr) |
| { |
| #ifdef FINAL_RELEASE |
| return 0; |
| #else |
| int result; |
| ESR_ReturnCode rc; |
| |
| rc = PFileVfprintf(stream, &result, format, argptr); |
| if (rc != ESR_SUCCESS) |
| return -1; |
| return result; |
| #endif |
| } |
| |
| int pprintf(const LCHAR* format, ...) |
| { |
| #ifdef FINAL_RELEASE |
| return 0; |
| #else |
| va_list args; |
| int result; |
| ESR_ReturnCode rc; |
| |
| va_start(args, format); |
| rc = PFileVfprintf(PSTDOUT, &result, format, args); |
| va_end(args); |
| if (rc != ESR_SUCCESS) |
| return -1; |
| return result; |
| #endif |
| } |