scummvm/common/file.cpp

259 lines
4.9 KiB
C++
Raw Normal View History

2002-08-31 07:43:34 +00:00
/* ScummVM - Scumm Interpreter
* Copyright (C) 2002-2004 The ScummVM project
2002-08-31 07:43:34 +00:00
*
* 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; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*
*/
#include "common/file.h"
#include "common/util.h"
2002-08-31 07:43:34 +00:00
Common::StringList File::_defaultDirectories;
2003-01-09 14:50:35 +00:00
FILE *File::fopenNoCase(const char *filename, const char *directory, const char *mode) {
FILE *file;
char buf[512];
char *ptr;
assert(directory);
strcpy(buf, directory);
2003-06-27 05:11:16 +00:00
#ifdef WIN32
// Fix for Win98 issue related with game directory pointing to root drive ex. "c:\"
if ((buf[0] != 0) && (buf[1] == ':') && (buf[2] == '\\') && (buf[3] == 0)) {
buf[2] = 0;
}
#endif
// Determine the length of the dir name.
const int dirLen = strlen(buf);
if (dirLen > 0) {
#ifdef __MORPHOS__
if (buf[dirLen-1] != ':' && buf[dirLen-1] != '/') // prevent double /
#endif
2003-04-10 13:44:50 +00:00
2003-04-30 12:43:56 +00:00
#if !defined(__GP32__) && !defined(__PALM_OS__)
strcat(buf, "/");
2003-04-10 13:44:50 +00:00
#endif
}
strcat(buf, filename);
file = fopen(buf, mode);
if (file)
return file;
buf[dirLen] = 0;
if (buf[0] != 0) {
#ifdef __MORPHOS__
if (buf[strlen(buf) - 1] != ':' && buf[strlen(buf) - 1] != '/')
#endif
2003-04-30 12:43:56 +00:00
#ifndef __PALM_OS__
strcat(buf, "/"); // PALMOS
2003-04-30 12:43:56 +00:00
#endif
}
const int8 len = strlen(buf);
strcat(buf, filename);
//
// Try again, with file name converted to upper case
//
ptr = buf + len;
while (*ptr) {
*ptr = toupper(*ptr);
ptr++;
}
file = fopen(buf, mode);
if (file)
return file;
//
// Try again, with file name converted to lower case
//
ptr = buf + len;
while (*ptr) {
*ptr = tolower(*ptr);
ptr++;
}
file = fopen(buf, mode);
return NULL;
}
void File::addDefaultDirectory(const Common::String &directory) {
_defaultDirectories.push_back(directory);
}
void File::resetDefaultDirectories() {
_defaultDirectories.clear();
}
2002-08-31 07:43:34 +00:00
File::File() {
_handle = NULL;
_ioFailed = false;
_name = 0;
2002-08-31 07:43:34 +00:00
}
File::~File() {
close();
delete [] _name;
2002-08-31 07:43:34 +00:00
}
bool File::open(const char *filename, AccessMode mode, const char *directory) {
2002-08-31 07:43:34 +00:00
if (_handle) {
debug(2, "File %s already opened", filename);
return false;
}
if (filename == NULL || *filename == 0) {
return false;
}
if (mode != kFileReadMode && mode != kFileWriteMode) {
warning("Only read/write mode supported!");
return false;
}
clearIOFailed();
const char *modeStr = (mode == kFileReadMode) ? "rb" : "wb";
if (directory) {
_handle = fopenNoCase(filename, directory, modeStr);
} else {
Common::StringList::const_iterator x;
for (x = _defaultDirectories.begin(); _handle == NULL && x != _defaultDirectories.end(); ++x) {
_handle = fopenNoCase(filename, x->c_str(), modeStr);
}
}
if (_handle == NULL) {
if (mode == kFileReadMode)
debug(2, "File %s not found", filename);
else
debug(2, "File %s not opened", filename);
2002-08-31 07:43:34 +00:00
return false;
}
int len = strlen(filename);
2003-05-01 12:36:36 +00:00
if (_name != 0)
delete [] _name;
_name = new char[len+1];
memcpy(_name, filename, len+1);
2002-08-31 07:43:34 +00:00
return true;
}
void File::close() {
if (_handle)
fclose(_handle);
2002-08-31 09:55:58 +00:00
_handle = NULL;
}
2003-11-30 00:06:27 +00:00
bool File::isOpen() const {
2002-08-31 09:55:58 +00:00
return _handle != NULL;
2002-08-31 07:43:34 +00:00
}
2003-11-30 00:06:27 +00:00
bool File::ioFailed() const {
return _ioFailed != 0;
2002-08-31 07:43:34 +00:00
}
void File::clearIOFailed() {
_ioFailed = false;
2002-08-31 07:43:34 +00:00
}
bool File::eof() {
if (_handle == NULL) {
error("File is not open!");
return false;
}
return feof(_handle) != 0;
}
uint32 File::pos() {
if (_handle == NULL) {
error("File is not open!");
return 0;
}
return ftell(_handle);
}
uint32 File::size() {
if (_handle == NULL) {
error("File is not open!");
return 0;
}
uint32 oldPos = ftell(_handle);
fseek(_handle, 0, SEEK_END);
uint32 length = ftell(_handle);
fseek(_handle, oldPos, SEEK_SET);
return length;
}
void File::seek(int32 offs, int whence) {
2002-08-31 07:43:34 +00:00
if (_handle == NULL) {
error("File is not open!");
return;
}
if (fseek(_handle, offs, whence) != 0)
clearerr(_handle);
}
2002-10-22 11:34:21 +00:00
uint32 File::read(void *ptr, uint32 len) {
2002-08-31 07:43:34 +00:00
byte *ptr2 = (byte *)ptr;
uint32 real_len;
2002-08-31 07:43:34 +00:00
if (_handle == NULL) {
error("File is not open!");
2002-09-02 20:15:14 +00:00
return 0;
2002-08-31 07:43:34 +00:00
}
2002-10-22 11:34:21 +00:00
if (len == 0)
2002-09-02 20:15:14 +00:00
return 0;
2002-08-31 07:43:34 +00:00
real_len = fread(ptr2, 1, len, _handle);
if (real_len < len) {
2002-08-31 07:43:34 +00:00
clearerr(_handle);
_ioFailed = true;
2002-08-31 07:43:34 +00:00
}
return real_len;
2002-08-31 07:43:34 +00:00
}
uint32 File::write(const void *ptr, uint32 len) {
if (_handle == NULL) {
error("File is not open!");
return 0;
}
2002-10-22 11:35:45 +00:00
if (len == 0)
return 0;
if ((uint32)fwrite(ptr, 1, len, _handle) != len) {
clearerr(_handle);
_ioFailed = true;
}
2002-10-22 11:35:45 +00:00
return len;
}