File objects inherit from Stream.

This commit is contained in:
Alex Szpakowski
2022-04-21 19:53:27 -03:00
parent 1e85893abb
commit d5865e160c
13 changed files with 156 additions and 174 deletions
+1 -1
View File
@@ -420,7 +420,7 @@ Message *Event::convert(const SDL_Event &e)
}
else
{
auto *file = new love::filesystem::NativeFile(e.drop.file);
auto *file = new love::filesystem::NativeFile(e.drop.file, love::filesystem::File::MODE_CLOSED);
vargs.emplace_back(&love::filesystem::NativeFile::type, file);
msg = new Message("filedropped", vargs);
file->release();
+20 -53
View File
@@ -25,12 +25,17 @@ namespace love
namespace filesystem
{
love::Type File::type("File", &Object::type);
love::Type File::type("File", &Stream::type);
File::~File()
{
}
FileData *File::read()
{
return read(getSize());
}
FileData *File::read(int64 size)
{
bool isopen = isOpen();
@@ -40,7 +45,6 @@ FileData *File::read(int64 size)
int64 max = getSize();
int64 cur = tell();
size = (size == ALL) ? max : size;
if (size < 0)
throw love::Exception("Invalid read size.");
@@ -54,7 +58,7 @@ FileData *File::read(int64 size)
if (cur + size > max)
size = max - cur;
FileData *fileData = new FileData(size, getFilename());
StrongRef<FileData> fileData(new FileData(size, getFilename()), Acquire::NORETAIN);
int64 bytesRead = read(fileData->getData(), size);
if (bytesRead < 0 || (bytesRead == 0 && bytesRead != size))
@@ -65,23 +69,18 @@ FileData *File::read(int64 size)
if (bytesRead < size)
{
FileData *tmpFileData = new FileData(bytesRead, getFilename());
StrongRef<FileData> tmpFileData(new FileData(bytesRead, getFilename()), Acquire::NORETAIN);
memcpy(tmpFileData->getData(), fileData->getData(), (size_t) bytesRead);
fileData->release();
fileData = tmpFileData;
}
if (!isopen)
close();
fileData->retain();
return fileData;
}
bool File::write(const Data *data, int64 size)
{
return write(data->getData(), (size == ALL) ? data->getSize() : size);
}
std::string File::getExtension() const
{
const std::string &filename = getFilename();
@@ -93,54 +92,22 @@ std::string File::getExtension() const
return std::string();
}
bool File::getConstant(const char *in, Mode &out)
STRINGMAP_CLASS_BEGIN(File, File::Mode, File::MODE_MAX_ENUM, mode)
{
return modes.find(in, out);
{ "c", File::MODE_CLOSED },
{ "r", File::MODE_READ },
{ "w", File::MODE_WRITE },
{ "a", File::MODE_APPEND },
}
STRINGMAP_CLASS_END(File, File::Mode, File::MODE_MAX_ENUM, mode)
bool File::getConstant(Mode in, const char *&out)
STRINGMAP_CLASS_BEGIN(File, File::BufferMode, File::BUFFER_MAX_ENUM, bufferMode)
{
return modes.find(in, out);
{ "none", File::BUFFER_NONE },
{ "line", File::BUFFER_LINE },
{ "full", File::BUFFER_FULL },
}
std::vector<std::string> File::getConstants(Mode)
{
return modes.getNames();
}
bool File::getConstant(const char *in, BufferMode &out)
{
return bufferModes.find(in, out);
}
bool File::getConstant(BufferMode in, const char *&out)
{
return bufferModes.find(in, out);
}
std::vector<std::string> File::getConstants(BufferMode)
{
return bufferModes.getNames();
}
StringMap<File::Mode, File::MODE_MAX_ENUM>::Entry File::modeEntries[] =
{
{ "c", MODE_CLOSED },
{ "r", MODE_READ },
{ "w", MODE_WRITE },
{ "a", MODE_APPEND },
};
StringMap<File::Mode, File::MODE_MAX_ENUM> File::modes(File::modeEntries, sizeof(File::modeEntries));
StringMap<File::BufferMode, File::BUFFER_MAX_ENUM>::Entry File::bufferModeEntries[] =
{
{ "none", BUFFER_NONE },
{ "line", BUFFER_LINE },
{ "full", BUFFER_FULL },
};
StringMap<File::BufferMode, File::BUFFER_MAX_ENUM> File::bufferModes(File::bufferModeEntries, sizeof(File::bufferModeEntries));
STRINGMAP_CLASS_END(File, File::BufferMode, File::BUFFER_MAX_ENUM, bufferMode)
} // filesystem
} // love
+15 -78
View File
@@ -27,6 +27,7 @@
// LOVE
#include "common/Data.h"
#include "common/Object.h"
#include "common/Stream.h"
#include "common/StringMap.h"
#include "common/int.h"
#include "FileData.h"
@@ -40,7 +41,7 @@ namespace filesystem
* A File interface, providing generic means of reading from and
* writing to files.
**/
class File : public Object
class File : public Stream
{
public:
@@ -66,16 +67,19 @@ public:
BUFFER_MAX_ENUM
};
/**
* Used to indicate ALL data in a file.
**/
static const int64 ALL = -1;
/**
* Destructor.
**/
virtual ~File();
// Implements Stream.
bool isReadable() const override { return getMode() == MODE_READ; }
bool isWritable() const override { return getMode() == MODE_WRITE || getMode() == MODE_APPEND; }
bool isSeekable() const override { return isOpen(); }
using Stream::read;
using Stream::write;
/**
* Opens the file in a certain mode.
*
@@ -96,53 +100,14 @@ public:
**/
virtual bool isOpen() const = 0;
/**
* Gets the size of the file.
*
* @return The size of the file.
**/
virtual int64 getSize() = 0;
/**
* Reads data from the file and allocates a Data object.
*
* @param size The number of bytes to attempt reading, or -1 for EOF.
* @param size The number of bytes to attempt reading.
* @return A newly allocated Data object.
**/
virtual FileData *read(int64 size = ALL);
/**
* Reads data into the destination buffer.
*
* @param dst The destination buffer.
* @param size The number of bytes to attempt reading.
* @return The number of bytes actually read.
**/
virtual int64 read(void *dst, int64 size) = 0;
/**
* Writes data into the File.
*
* @param data The source buffer.
* @param size The size of the buffer.
* @return True of success, false otherwise.
**/
virtual bool write(const void *data, int64 size) = 0;
/**
* Writes a Data object into the File.
*
* @param data The data object to write into the file.
* @param size The number of bytes to attempt writing, or -1 for everything.
* @return True of success, false otherwise.
**/
virtual bool write(const Data *data, int64 size = ALL);
/**
* Flushes the currently buffered file data to disk. Only applicable in
* write mode.
**/
virtual bool flush() = 0;
FileData *read(int64 size) override;
FileData *read();
/**
* Checks whether we are currently at end-of-file.
@@ -151,21 +116,6 @@ public:
**/
virtual bool isEOF() = 0;
/**
* Gets the current position in the File.
*
* @return The current byte position in the File.
**/
virtual int64 tell() = 0;
/**
* Seeks to a certain position in the File.
*
* @param pos The byte position in the file.
* @return True on success, false otherwise.
**/
virtual bool seek(uint64 pos) = 0;
/**
* Sets the buffering mode for the file. When buffering is enabled, the file
* will not write to disk (or will pre-load data if in read mode) until the
@@ -202,21 +152,8 @@ public:
**/
virtual std::string getExtension() const;
static bool getConstant(const char *in, Mode &out);
static bool getConstant(Mode in, const char *&out);
static std::vector<std::string> getConstants(Mode);
static bool getConstant(const char *in, BufferMode &out);
static bool getConstant(BufferMode in, const char *&out);
static std::vector<std::string> getConstants(BufferMode);
private:
static StringMap<Mode, MODE_MAX_ENUM>::Entry modeEntries[];
static StringMap<Mode, MODE_MAX_ENUM> modes;
static StringMap<BufferMode, BUFFER_MAX_ENUM>::Entry bufferModeEntries[];
static StringMap<BufferMode, BUFFER_MAX_ENUM> bufferModes;
STRINGMAP_CLASS_DECLARE(Mode);
STRINGMAP_CLASS_DECLARE(BufferMode);
}; // File
+3 -2
View File
@@ -167,7 +167,7 @@ public:
/**
* Creates a new file.
**/
virtual File *newFile(const char *filename) const = 0;
virtual File *newFile(const char *filename, File::Mode = File::MODE_CLOSED) const = 0;
/**
* Creates a new FileData object. Data will be copied.
@@ -239,7 +239,8 @@ public:
* @param filename The name of the file to read from.
* @param size The size in bytes of the data to read.
**/
virtual FileData *read(const char *filename, int64 size = File::ALL) const = 0;
virtual FileData *read(const char *filename, int64 size) const = 0;
virtual FileData *read(const char *filename) const = 0;
/**
* Write data to a file.
+30 -4
View File
@@ -39,13 +39,14 @@ namespace filesystem
love::Type NativeFile::type("NativeFile", &File::type);
NativeFile::NativeFile(const std::string &filename)
NativeFile::NativeFile(const std::string &filename, Mode mode)
: filename(filename)
, file(nullptr)
, mode(MODE_CLOSED)
, bufferMode(BUFFER_NONE)
, bufferSize(0)
{
open(mode);
}
NativeFile::~NativeFile()
@@ -54,10 +55,28 @@ NativeFile::~NativeFile()
close();
}
NativeFile::NativeFile(const NativeFile &other)
: filename(other.filename)
, file(nullptr)
, mode(MODE_CLOSED)
, bufferMode(other.bufferMode)
, bufferSize(other.bufferSize)
{
open(other.mode);
}
NativeFile *NativeFile::clone()
{
return new NativeFile(*this);
}
bool NativeFile::open(Mode newmode)
{
if (newmode == MODE_CLOSED)
{
close();
return true;
}
// File already open?
if (file != nullptr)
@@ -197,15 +216,22 @@ int64 NativeFile::tell()
#endif
}
bool NativeFile::seek(uint64 pos)
bool NativeFile::seek(int64 pos, SeekOrigin origin)
{
if (file == nullptr)
return false;
int forigin = SEEK_SET;
if (origin == SEEKORIGIN_CURRENT)
forigin = SEEK_CUR;
else if (origin == SEEKORIGIN_END)
forigin = SEEK_END;
// TODO
#ifdef LOVE_WINDOWS
return _fseeki64(file, (int64) pos, SEEK_SET) == 0;
return _fseeki64(file, pos, forigin) == 0;
#else
return fseeko(file, (off_t) pos, SEEK_SET) == 0;
return fseeko(file, (off_t) pos, forigin) == 0;
#endif
}
+12 -7
View File
@@ -39,22 +39,25 @@ public:
static love::Type type;
NativeFile(const std::string &filename);
NativeFile(const std::string &filename, Mode mode);
virtual ~NativeFile();
// Implements Stream.
NativeFile *clone() override;
int64 read(void* dst, int64 size) override;
bool write(const void* data, int64 size) override;
bool flush() override;
int64 getSize() override;
int64 tell() override;
bool seek(int64 pos, SeekOrigin origin) override;
// Implements File.
using File::read;
using File::write;
bool open(Mode mode) override;
bool close() override;
bool isOpen() const override;
int64 getSize() override;
int64 read(void *dst, int64 size) override;
bool write(const void *data, int64 size) override;
bool flush() override;
bool isEOF() override;
int64 tell() override;
bool seek(uint64 pos) override;
bool setBuffer(BufferMode bufmode, int64 size) override;
BufferMode getBuffer(int64 &size) const override;
Mode getMode() const override;
@@ -62,6 +65,8 @@ public:
private:
NativeFile(const NativeFile &other);
static const char *getModeString(Mode mode);
std::string filename;
+32 -6
View File
@@ -41,13 +41,24 @@ static bool setupWriteDirectory()
return fs != nullptr && fs->setupWriteDirectory();
}
File::File(const std::string &filename)
File::File(const std::string &filename, Mode mode)
: filename(filename)
, file(nullptr)
, mode(MODE_CLOSED)
, bufferMode(BUFFER_NONE)
, bufferSize(0)
{
open(mode);
}
File::File(const File &other)
: filename(other.filename)
, file(nullptr)
, mode(MODE_CLOSED)
, bufferMode(other.bufferMode)
, bufferSize(other.bufferSize)
{
open(other.mode);
}
File::~File()
@@ -56,10 +67,18 @@ File::~File()
close();
}
File *File::clone()
{
return new File(*this);
}
bool File::open(Mode mode)
{
if (mode == MODE_CLOSED)
{
close();
return true;
}
if (!PHYSFS_isInit())
throw love::Exception("PhysFS is not initialized.");
@@ -151,10 +170,6 @@ int64 File::read(void *dst, int64 size)
if (!file || mode != MODE_READ)
throw love::Exception("File is not opened for reading.");
int64 max = (int64)PHYSFS_fileLength(file);
size = (size == ALL) ? max : size;
size = (size > max) ? max : size;
if (size < 0)
throw love::Exception("Invalid read size.");
@@ -207,8 +222,19 @@ int64 File::tell()
return (int64) PHYSFS_tell(file);
}
bool File::seek(uint64 pos)
bool File::seek(int64 pos, SeekOrigin origin)
{
if (file != nullptr)
{
if (origin == SEEKORIGIN_CURRENT)
pos += tell();
else if (origin == SEEKORIGIN_END)
pos += getSize();
}
if (pos < 0)
return false;
return file != nullptr && PHYSFS_seek(file, (PHYSFS_uint64) pos) != 0;
}
+12 -7
View File
@@ -46,23 +46,26 @@ public:
* Constructs an File with the given ilename.
* @param filename The relative filepath of the file to load.
**/
File(const std::string &filename);
File(const std::string &filename, Mode mode);
virtual ~File();
// Implements Stream.
File *clone() override;
int64 read(void* dst, int64 size) override;
bool write(const void* data, int64 size) override;
bool flush() override;
int64 getSize() override;
bool seek(int64 pos, SeekOrigin origin) override;
int64 tell() override;
// Implements love::filesystem::File.
using love::filesystem::File::read;
using love::filesystem::File::write;
bool open(Mode mode) override;
bool close() override;
bool isOpen() const override;
int64 getSize() override;
virtual int64 read(void *dst, int64 size) override;
bool write(const void *data, int64 size) override;
bool flush() override;
bool isEOF() override;
int64 tell() override;
bool seek(uint64 pos) override;
bool setBuffer(BufferMode bufmode, int64 size) override;
BufferMode getBuffer(int64 &size) const override;
Mode getMode() const override;
@@ -70,6 +73,8 @@ public:
private:
File(const File &other);
// filename
std::string filename;
+13 -11
View File
@@ -496,9 +496,9 @@ bool Filesystem::unmount(Data *data)
return false;
}
love::filesystem::File *Filesystem::newFile(const char *filename) const
love::filesystem::File *Filesystem::newFile(const char *filename, File::Mode mode) const
{
return new File(filename);
return new File(filename, mode);
}
std::string Filesystem::getFullCommonPath(CommonPath path)
@@ -793,19 +793,23 @@ bool Filesystem::remove(const char *file)
FileData *Filesystem::read(const char *filename, int64 size) const
{
File file(filename);
file.open(File::MODE_READ);
File file(filename, File::MODE_READ);
// close() is called in the File destructor.
return file.read(size);
}
FileData* Filesystem::read(const char* filename) const
{
File file(filename, File::MODE_READ);
// close() is called in the File destructor.
return file.read();
}
void Filesystem::write(const char *filename, const void *data, int64 size) const
{
File file(filename);
file.open(File::MODE_WRITE);
File file(filename, File::MODE_WRITE);
// close() is called in the File destructor.
if (!file.write(data, size))
@@ -814,9 +818,7 @@ void Filesystem::write(const char *filename, const void *data, int64 size) const
void Filesystem::append(const char *filename, const void *data, int64 size) const
{
File file(filename);
file.open(File::MODE_APPEND);
File file(filename, File::MODE_APPEND);
// close() is called in the File destructor.
if (!file.write(data, size))
+3 -2
View File
@@ -71,7 +71,7 @@ public:
bool unmount(CommonPath path) override;
bool unmountFullPath(const char *fullpath) override;
love::filesystem::File *newFile(const char *filename) const override;
love::filesystem::File *newFile(const char *filename, File::Mode mode = File::MODE_CLOSED) const override;
std::string getFullCommonPath(CommonPath path) override;
const char *getWorkingDirectory() override;
@@ -88,7 +88,8 @@ public:
bool remove(const char *file) override;
FileData *read(const char *filename, int64 size = File::ALL) const override;
FileData *read(const char *filename, int64 size) const override;
FileData *read(const char *filename) const override;
void write(const char *filename, const void *data, int64 size) const override;
void append(const char *filename, const void *data, int64 size) const override;
+3 -1
View File
@@ -121,10 +121,12 @@ int w_File_read(lua_State *L)
startidx = 3;
}
int64 size = (int64) luaL_optnumber(L, startidx, (lua_Number) File::ALL);
int64 size = (int64) luaL_optnumber(L, startidx, -1);
try
{
if (size < 0)
size = file->getSize();
d.set(file->read(size), Acquire::NORETAIN);
}
catch (love::Exception &e)
+10 -2
View File
@@ -343,6 +343,11 @@ Data *luax_getdata(lua_State *L, int idx)
return data;
}
bool luax_cangetfile(lua_State *L, int idx)
{
return lua_isstring(L, idx) || luax_istype(L, idx, File::type);
}
bool luax_cangetfiledata(lua_State *L, int idx)
{
return lua_isstring(L, idx) || luax_istype(L, idx, File::type) || luax_istype(L, idx, FileData::type);
@@ -557,12 +562,15 @@ int w_read(lua_State *L)
}
const char *filename = luaL_checkstring(L, startidx + 0);
int64 len = (int64) luaL_optinteger(L, startidx + 1, File::ALL);
int64 len = (int64) luaL_optinteger(L, startidx + 1, -1);
FileData *data = nullptr;
try
{
data = instance()->read(filename, len);
if (len >= 0)
data = instance()->read(filename, len);
else
data = instance()->read(filename);
}
catch (love::Exception &e)
{
+2
View File
@@ -40,7 +40,9 @@ namespace filesystem
**/
FileData *luax_getfiledata(lua_State *L, int idx);
bool luax_cangetfiledata(lua_State *L, int idx);
File *luax_getfile(lua_State *L, int idx);
bool luax_cangetfile(lua_State *L, int idx);
Data *luax_getdata(lua_State *L, int idx);
bool luax_cangetdata(lua_State *L, int idx);