/*
* Copyright (C) 2000-2001 Marc Wandschneider <mw@kiltdown.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* For more information look at the file COPYRIGHT in this package
*
*/
#include <ILifetime.h>
#include <basetypes.h>
#include <stdio.h>
#include <istream.h>
#include "filestream.h"
/**
*=-------------------------------------------------------------------------=
* FileStream::FileStream
*=-------------------------------------------------------------------------=
* create a new object
*
* Notes:
*/
FileStream::FileStream()
{
/**
* we're alive, so have at least one ref
*/
m_cref = 1;
m_file = NULL;
}
/**
*=-------------------------------------------------------------------------=
* FileStream::~FileStream
*=-------------------------------------------------------------------------=
* destroy the object and delete and resources we're using, such as file
* handles
*
* Notes:
*/
FileStream::~FileStream()
{
/**
* we're done -- kill the file descriptor if we've got one
*
* UNDONE: marcw, 2.6.2000 ASSERT on refcounts
*/
if (m_file != NULL)
fclose(m_file);
m_file = NULL;
}
/**
*=-------------------------------------------------------------------------=
* FileStream::create
*=-------------------------------------------------------------------------=
* static creation method -- use this method to instantiate a new object
* and it'll create all the required resources.
*
* Parameters:
* char * - [in] filename to open
* BOOL - [in] whether the stream is to be read-only or not
* FileStream ** - [out] resulting object created
*
* Output:
* BOOL - false if something wrong, errno is set
*
* Notes:
*/
BOOL FileStream::create(char *filename,
BOOL readOnly,
FileStream **ppout)
{
FileStream *frs = new FileStream();
if ((*ppout = frs) == NULL) return FALSE;
frs->m_readOnly = readOnly;
/**
* call the init function and return
*/
if (!frs->init(filename)) {
delete frs;
*ppout = NULL;
return FALSE;
}
return TRUE;
}
/**
*=-------------------------------------------------------------------------=
* FileStream::init
*=-------------------------------------------------------------------------=
* small little initalization routine that opens the file appropriately,
* depending on whether we're read only or not
*
* Parameters:
* char * - [in] filename to open
*
* Output:
* BOOL - false if error, errno set.
*
* Notes:
*/
BOOL FileStream::init(const char *filename)
{
const char *flags;
/**
* UNDONE: marcw, 2.6.2000 -- this will not allow appending to existing
* files -- we should investigate "r+"
*/
flags = m_readOnly ? "r" : "w+";
/**
* try to open the file they've given us
*/
m_file = fopen(filename, flags);
return m_file != NULL;
}
/**
*=-------------------------------------------------------------------------=
* FileStream::addRef [ILifeTime]
*=-------------------------------------------------------------------------=
* implementation of ILifeTime
*/
int FileStream::addRef(void)
{
return ++m_cref;
}
/**
*=-------------------------------------------------------------------------=
* FileStream::release [ILifeTime]
*=-------------------------------------------------------------------------=
* implementation of ILifeTime
*/
int FileStream::release(void)
{
m_cref--;
if (m_cref == 0) {
delete this;
return 0;
} else
return m_cref;
}
/**
*=-------------------------------------------------------------------------=
* FileStream::readData [ICharReadStream]
*=-------------------------------------------------------------------------=
* reads in the requested amount of data
*
* Parameters:
* int - [in] number of chars to read in
* char * - [in] where to put said data
*
* Output:
* int - number of chars read, or -1 if error, errno set
*
* Notes:
*/
int FileStream::readData(int count, char *pdata)
{
return readData(count, (BYTE *)pdata);
}
/**
*=-------------------------------------------------------------------------=
* FileStream::readLine [ICharReadStream]
*=-------------------------------------------------------------------------=
* reads in a line of text from the input stream, putting the resulting
* string in the given buffer. the newline is retained, and the string is
* terminated with a '\0' character
*
* Parameters:
* int - [in] max number of chars to write
* char * - [in] where to put the characters
*
* Output:
* int - -1 means an error occurred
* 0 means EOF
* 1 means all is well
*
* Notes:
* this routine reads in at most one less than the first parameter
* number of characters to ensure that there is room for the \0
* character. This routine is but a thin wrapper for fgets().
*/
int FileStream::readLine(int count, char *pdata)
{
char *p = fgets(pdata, count, m_file);
if (p)
return 1;
else
return ferror(m_file) ? -1 : 0;
}
/**
*=-------------------------------------------------------------------------=
* FileStream::readChar [ICharReadStream]
*=-------------------------------------------------------------------------=
* reads the next character from the input stream. This routine wraps the
* Std C routine fgetc
*
* Parameters:
* char * - [out] where to put the char we got
*
* Output:
* int - -1 means an error occurred,
* 0 means EOF
* 1 means all is well
*
* Notes:
*/
int FileStream::readChar(char *pc)
{
int i = fgetc(m_file);
if (i == 0) {
return feof(m_file) ? 0 : -1;
}
*pc = (char)i;
return 1;
}
/**
*=-------------------------------------------------------------------------=
* FileStream::seek [ICharReadStream]
*=-------------------------------------------------------------------------=
* seeks to the given point, from the given starting reference point. This
* routine basically wraps the stdio 'fseek' routine.
*
* Parameters:
* SEEKPOINT - [in] where to start the seek from. See the
* SEEKPOINT enumeration in istream.h
* int - [in] an offset from the seek starting point
*
* Output:
* BOOL - FALSE on failure, TRUE on success
*
* Notes:
*/
BOOL FileStream::seek(SEEKPOINT start, int offset)
{
int whence;
switch (start) {
case SEEKPOINT_BEGIN:
whence = SEEK_SET;
break;
case SEEKPOINT_CURRENT:
whence = SEEK_CUR;
break;
case SEEKPOINT_END:
whence = SEEK_END;
break;
}
return fseek(m_file, offset, whence) == 0;
}
/**
*=-------------------------------------------------------------------------=
* FileStream::readData [IByteReadStream]
*=-------------------------------------------------------------------------=
* reads in the requested amount of data
*
* Parameters:
* int - [in] number of BYTEs to read in
* char * - [in] where to put said data
*
* Output:
* int - number of BYTEs read, or -1 if error, errno set
*
* Notes:
*/
int FileStream::readData(int count, BYTE *pdata)
{
int c;
if (m_file == NULL) {
// UNDONE: ASSERT & set errno
return -1;
}
/**
* param checking
*/
if (count < 0 || pdata == NULL)
return -1;
c = fread(pdata, sizeof(BYTE), count, m_file);
/**
* if we didn't read any chars, then return 0 if there truly weren't any
* to read, or -1 if it was an error
*/
if (c == 0)
return feof(m_file) ? 0 : -1;
return c;
}
/**
*=-------------------------------------------------------------------------=
* FileStream::writeData [ICharWriteStream]
*=-------------------------------------------------------------------------=
* writes out the given chars
*
* Parameters:
* int - [in] number of chars to write out
* char * - [in] buffer holding chars to write out
*
* Output:
* int - number of chars written, or -1 for error,
* errno is set
*
* Notes:
*/
int FileStream::writeData(int count, char *pdata)
{
return writeData(count, (BYTE *)pdata);
}
/**
*=-------------------------------------------------------------------------=
* FileStream::writeLine [ICharWriteStream]
*=-------------------------------------------------------------------------=
* writes out the given null-terminated line of data, adding on a newline
* character at the end of input. This routine wraps the fputs routine
* in the C runtime libraries and adds a '\n'
*
* Parameters:
* char * - [in] null-terminated string to write out
*
* Output:
* BOOL - TRUE means success, FALSE means the data couldn't
* be written out
*
* Notes:
*/
BOOL FileStream::writeLine(char *pline)
{
int result = fputs(pline, m_file);
if (result == EOF) return FALSE;
return fputc('\n', m_file) == '\n';
}
/**
*=-------------------------------------------------------------------------=
* FileStream::writeData [IByteWriteStream]
*=-------------------------------------------------------------------------=
* writes out the given BYTES
*
* Parameters:
* int - [in] number of BYTEs to write out
* char * - [in] buffer holding BYTEs to write out
*
* Output:
* int - number of BYTEs written, or -1 for error,
* errno is set
*
* Notes:
*/
int FileStream::writeData(int count, BYTE *pdata)
{
int c;
if (m_file == NULL) {
// UNDONE: marcw, 9/19/2000: ASSERT & set errno
return -1;
}
/**
* param checking
*/
if (count < 0 || pdata == NULL)
return -1;
c = fwrite(pdata, sizeof(BYTE), count, m_file);
/**
* errors, errno is set
*/
if (c < count)
return -1;
return c;
}
syntax highlighted by Code2HTML, v. 0.9.1