/*---------------------------------------------------------------------------*
* 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
}