// file: file.cpp
// author: Andrew Hynek
// contents: implementation of a simple file class
#include <stdio.h>
#include <string.h>
#include <time.h> // for awake.h (time_t)
#include "file.h"
#include "awake.h" // for MAX_STRING_LENGTH
#include "utils.h" // for log()
#include <new>
File::File()
{
fl = NULL;
*filename = '\0';
*mode = '\0';
}
File::File(const char *_filename, const char *_mode)
{
fl = NULL;
*filename = '\0';
*mode = '\0';
Open(_filename, _mode);
}
File::~File()
{
Close();
}
bool File::EoF() const
{
return feof(fl);
}
bool File::IsWriteable() const
{
return (IsOpen() && (strchr(mode, 'w') || strchr(mode, 'a')));
}
bool File::Open(const char *_filename, const char *_mode)
{
Close();
fl = fopen(_filename, _mode);
if (!fl)
return false;
memset(filename, 0, MAX_FILE_LENGTH);
strncpy(filename, _filename, MAX_FILE_LENGTH);
memset(mode, 0, 8);
strncpy(mode, _mode, 8);
line_num = 0;
return true;
}
bool File::Close()
{
if (IsOpen()) {
fclose(fl);
fl = NULL;
*filename = '\0';
*mode = '\0';
return true;
}
return false;
}
void File::Rewind()
{
rewind(fl);
line_num = 0;
}
int File::Seek(long offset, int origin)
{
return fseek(fl, offset, origin);
}
bool File::GetLine(char *buf, size_t buf_size, bool blank)
{
while (!feof(fl)) {
fgets(buf, buf_size, fl);
line_num++;
if (*buf && *buf != '*' && (blank ? TRUE : *buf != '\n')) {
char *ptr = strchr(buf, '\n');
if (ptr && ptr < (buf + buf_size))
*ptr = '\0';
break;
}
}
return (!feof(fl));
}
char *File::ReadString()
{
char buf[MAX_STRING_LENGTH+8];
char line[512+8];
size_t buf_len = 0;
bool skip_to_end = false, done = false;
memset(buf, 0, MAX_STRING_LENGTH+8);
while (!done) {
if (!GetLine(line, 512, FALSE)) {
log("Error: format error in %s, line %d: expecting ~-terminated string",
Filename(), LineNumber());
break;
}
char *ptr = strchr(line, '~');
// if we find '~', replace it with '\0' and break, otherwise cat "\r\n"
if (ptr) {
*ptr = '\0';
done = true;
} else
strcat(line, "\r\n");
size_t line_len = strlen(line);
if ((buf_len + line_len) >= (size_t)MAX_STRING_LENGTH) {
// we can handle this gracefully: just fill buf, then set skip_to_end
log("Error: string too long (%s, line %d) -- truncating",
Filename(), LineNumber());
strncpy(buf+buf_len, line, MAX_STRING_LENGTH - buf_len);
*(buf+MAX_STRING_LENGTH) = '\0';
strcat(buf, "\r\n");
// if line doesn't have the '~', then we need to find it later
skip_to_end = (strchr(line, '~') == NULL);
break;
}
strcat(buf, line);
buf_len += line_len;
}
if (skip_to_end) {
// if we're here, we need to find the '~'
while (!EoF()) {
if (!GetLine(line, 512, FALSE)) {
log("Error: format error in %s, line %d: expecting ~-termed string",
Filename(), LineNumber());
break;
}
if (strchr(line, '~') != NULL)
break;
}
}
if (buf_len > 0) {
char *res = new char[buf_len+1];
strcpy(res, buf);
return res;
}
return NULL;
}
int File::Print(const char *format, ...)
{
#ifdef vfprintf
va_list arg_list;
va_start(arg_list, format);
int res = vfprintf(fl, format, arg_list);
va_end(arg_list);
return res;
#else
return 0;
#endif
}