mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
Added File:setBuffer/getBuffer, File:flush, and File:getMode.
This commit is contained in:
@@ -34,11 +34,21 @@ bool File::getConstant(const char *in, Mode &out)
|
|||||||
return modes.find(in, out);
|
return modes.find(in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool File::getConstant(Mode in, const char *&out)
|
bool File::getConstant(Mode in, const char *&out)
|
||||||
{
|
{
|
||||||
return modes.find(in, out);
|
return modes.find(in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
StringMap<File::Mode, File::MODE_MAX_ENUM>::Entry File::modeEntries[] =
|
StringMap<File::Mode, File::MODE_MAX_ENUM>::Entry File::modeEntries[] =
|
||||||
{
|
{
|
||||||
{"c", File::CLOSED},
|
{"c", File::CLOSED},
|
||||||
@@ -49,5 +59,14 @@ StringMap<File::Mode, File::MODE_MAX_ENUM>::Entry File::modeEntries[] =
|
|||||||
|
|
||||||
StringMap<File::Mode, File::MODE_MAX_ENUM> File::modes(File::modeEntries, sizeof(File::modeEntries));
|
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", File::BUFFER_NONE},
|
||||||
|
{"line", File::BUFFER_LINE},
|
||||||
|
{"full", File::BUFFER_FULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
StringMap<File::BufferMode, File::BUFFER_MAX_ENUM> File::bufferModes(File::bufferModeEntries, sizeof(File::bufferModeEntries));
|
||||||
|
|
||||||
} // filesystem
|
} // filesystem
|
||||||
} // love
|
} // love
|
||||||
|
|||||||
@@ -56,6 +56,14 @@ public:
|
|||||||
MODE_MAX_ENUM
|
MODE_MAX_ENUM
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum BufferMode
|
||||||
|
{
|
||||||
|
BUFFER_NONE,
|
||||||
|
BUFFER_LINE,
|
||||||
|
BUFFER_FULL,
|
||||||
|
BUFFER_MAX_ENUM
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to indicate ALL data in a file.
|
* Used to indicate ALL data in a file.
|
||||||
**/
|
**/
|
||||||
@@ -128,6 +136,12 @@ public:
|
|||||||
**/
|
**/
|
||||||
virtual bool write(const Data *data, int64 size = ALL) = 0;
|
virtual bool write(const Data *data, int64 size = ALL) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes the currently buffered file data to disk. Only applicable in
|
||||||
|
* write mode.
|
||||||
|
**/
|
||||||
|
virtual bool flush() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether we are currently at end-of-file.
|
* Checks whether we are currently at end-of-file.
|
||||||
*
|
*
|
||||||
@@ -150,6 +164,24 @@ public:
|
|||||||
**/
|
**/
|
||||||
virtual bool seek(uint64 pos) = 0;
|
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
|
||||||
|
* buffer's capacity is reached.
|
||||||
|
* In the BUFFER_LINE mode, the file will also write to disk if a newline is
|
||||||
|
* written.
|
||||||
|
*
|
||||||
|
* @param bufmode The buffer mode.
|
||||||
|
* @param size The size in bytes of the buffer.
|
||||||
|
**/
|
||||||
|
virtual bool setBuffer(BufferMode bufmode, int64 size) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param[out] size The size in bytes of the buffer.
|
||||||
|
* @return The current buffer mode.
|
||||||
|
**/
|
||||||
|
virtual BufferMode getBuffer(int64 &size) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current mode of the File.
|
* Gets the current mode of the File.
|
||||||
* @return The current mode of the File; CLOSED, READ, WRITE or APPEND.
|
* @return The current mode of the File; CLOSED, READ, WRITE or APPEND.
|
||||||
@@ -169,13 +201,19 @@ public:
|
|||||||
virtual std::string getExtension() const = 0;
|
virtual std::string getExtension() const = 0;
|
||||||
|
|
||||||
static bool getConstant(const char *in, Mode &out);
|
static bool getConstant(const char *in, Mode &out);
|
||||||
static bool getConstant(Mode in, const char *&out);
|
static bool getConstant(Mode in, const char *&out);
|
||||||
|
|
||||||
|
static bool getConstant(const char *in, BufferMode &out);
|
||||||
|
static bool getConstant(BufferMode in, const char *&out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static StringMap<Mode, MODE_MAX_ENUM>::Entry modeEntries[];
|
static StringMap<Mode, MODE_MAX_ENUM>::Entry modeEntries[];
|
||||||
static StringMap<Mode, MODE_MAX_ENUM> modes;
|
static StringMap<Mode, MODE_MAX_ENUM> modes;
|
||||||
|
|
||||||
|
static StringMap<BufferMode, BUFFER_MAX_ENUM>::Entry bufferModeEntries[];
|
||||||
|
static StringMap<BufferMode, BUFFER_MAX_ENUM> bufferModes;
|
||||||
|
|
||||||
}; // File
|
}; // File
|
||||||
|
|
||||||
} // filesystem
|
} // filesystem
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ extern bool hack_setupWriteDirectory();
|
|||||||
File::File(const std::string &filename)
|
File::File(const std::string &filename)
|
||||||
: filename(filename)
|
: filename(filename)
|
||||||
, file(0)
|
, file(0)
|
||||||
, mode(filesystem::File::CLOSED)
|
, mode(CLOSED)
|
||||||
|
, bufferMode(BUFFER_NONE)
|
||||||
|
, bufferSize(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +85,13 @@ bool File::open(Mode mode)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file != 0 && !setBuffer(bufferMode, bufferSize))
|
||||||
|
{
|
||||||
|
// Revert to buffer defaults if we don't successfully set the buffer.
|
||||||
|
bufferMode = BUFFER_NONE;
|
||||||
|
bufferSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return (file != 0);
|
return (file != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +178,10 @@ int64 File::read(void *dst, int64 size)
|
|||||||
// Sadly, we'll have to clamp to 32 bits here
|
// Sadly, we'll have to clamp to 32 bits here
|
||||||
size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
|
size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
|
||||||
|
|
||||||
int64 read = (int64)PHYSFS_read(file, dst, 1, (int) size);
|
if (size < 0)
|
||||||
|
throw love::Exception("Invalid read size.");
|
||||||
|
|
||||||
|
int64 read = (int64)PHYSFS_read(file, dst, 1, (PHYSFS_uint32) size);
|
||||||
|
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
@@ -182,13 +194,23 @@ bool File::write(const void *data, int64 size)
|
|||||||
// Another clamp, for the time being.
|
// Another clamp, for the time being.
|
||||||
size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
|
size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
|
||||||
|
|
||||||
|
if (size < 0)
|
||||||
|
throw love::Exception("Invalid write size.");
|
||||||
|
|
||||||
// Try to write.
|
// Try to write.
|
||||||
int64 written = static_cast<int64>(PHYSFS_write(file, data, 1, (int) size));
|
int64 written = static_cast<int64>(PHYSFS_write(file, data, 1, (PHYSFS_uint32) size));
|
||||||
|
|
||||||
// Check that correct amount of data was written.
|
// Check that correct amount of data was written.
|
||||||
if (written != size)
|
if (written != size)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Manually flush the buffer in BUFFER_LINE mode if we find a newline.
|
||||||
|
if (bufferMode == BUFFER_LINE && bufferSize > size)
|
||||||
|
{
|
||||||
|
if (memchr(data, '\n', (size_t) size) != NULL)
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,6 +219,14 @@ bool File::write(const Data *data, int64 size)
|
|||||||
return write(data->getData(), (size == ALL) ? data->getSize() : size);
|
return write(data->getData(), (size == ALL) ? data->getSize() : size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool File::flush()
|
||||||
|
{
|
||||||
|
if (!file || (mode != WRITE && mode != APPEND))
|
||||||
|
throw love::Exception("File is not opened for writing.");
|
||||||
|
|
||||||
|
return PHYSFS_flush(file) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef LOVE_WINDOWS
|
#ifdef LOVE_WINDOWS
|
||||||
// MSVC doesn't like the 'this' keyword
|
// MSVC doesn't like the 'this' keyword
|
||||||
// well, we'll use 'that'.
|
// well, we'll use 'that'.
|
||||||
@@ -226,7 +256,7 @@ int64 File::tell()
|
|||||||
if (file == 0)
|
if (file == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return (int64)PHYSFS_tell(file);
|
return (int64) PHYSFS_tell(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool File::seek(uint64 pos)
|
bool File::seek(uint64 pos)
|
||||||
@@ -234,11 +264,56 @@ bool File::seek(uint64 pos)
|
|||||||
if (file == 0)
|
if (file == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!PHYSFS_seek(file, (PHYSFS_uint64)pos))
|
if (!PHYSFS_seek(file, (PHYSFS_uint64) pos))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool File::setBuffer(BufferMode bufmode, int64 size)
|
||||||
|
{
|
||||||
|
// No negativity allowed!
|
||||||
|
if (size < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If the file isn't open, we'll make sure the buffer values are set in
|
||||||
|
// File::open.
|
||||||
|
if (file == 0 || mode == CLOSED)
|
||||||
|
{
|
||||||
|
bufferMode = bufmode;
|
||||||
|
bufferSize = size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
switch (bufmode)
|
||||||
|
{
|
||||||
|
case BUFFER_NONE:
|
||||||
|
default:
|
||||||
|
ret = PHYSFS_setBuffer(file, 0);
|
||||||
|
size = 0;
|
||||||
|
break;
|
||||||
|
case BUFFER_LINE:
|
||||||
|
case BUFFER_FULL:
|
||||||
|
ret = PHYSFS_setBuffer(file, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bufferMode = bufmode;
|
||||||
|
bufferSize = size;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
File::BufferMode File::getBuffer(int64 &size) const
|
||||||
|
{
|
||||||
|
size = bufferSize;
|
||||||
|
return bufferMode;
|
||||||
|
}
|
||||||
|
|
||||||
std::string File::getFilename() const
|
std::string File::getFilename() const
|
||||||
{
|
{
|
||||||
return filename;
|
return filename;
|
||||||
|
|||||||
@@ -43,17 +43,6 @@ namespace physfs
|
|||||||
|
|
||||||
class File : public love::filesystem::File
|
class File : public love::filesystem::File
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
|
|
||||||
// filename
|
|
||||||
std::string filename;
|
|
||||||
|
|
||||||
// PHYSFS File handle.
|
|
||||||
PHYSFS_file *file;
|
|
||||||
|
|
||||||
// The current mode of the file.
|
|
||||||
Mode mode;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,13 +63,30 @@ public:
|
|||||||
int64 read(void *dst, int64 size);
|
int64 read(void *dst, int64 size);
|
||||||
bool write(const void *data, int64 size);
|
bool write(const void *data, int64 size);
|
||||||
bool write(const Data *data, int64 size = ALL);
|
bool write(const Data *data, int64 size = ALL);
|
||||||
|
bool flush();
|
||||||
bool eof();
|
bool eof();
|
||||||
int64 tell();
|
int64 tell();
|
||||||
bool seek(uint64 pos);
|
bool seek(uint64 pos);
|
||||||
|
bool setBuffer(BufferMode bufmode, int64 size);
|
||||||
|
BufferMode getBuffer(int64 &size) const;
|
||||||
Mode getMode() const;
|
Mode getMode() const;
|
||||||
std::string getFilename() const;
|
std::string getFilename() const;
|
||||||
std::string getExtension() const;
|
std::string getExtension() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// filename
|
||||||
|
std::string filename;
|
||||||
|
|
||||||
|
// PHYSFS File handle.
|
||||||
|
PHYSFS_File *file;
|
||||||
|
|
||||||
|
// The current mode of the file.
|
||||||
|
Mode mode;
|
||||||
|
|
||||||
|
BufferMode bufferMode;
|
||||||
|
int64 bufferSize;
|
||||||
|
|
||||||
}; // File
|
}; // File
|
||||||
|
|
||||||
} // physfs
|
} // physfs
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ int w_File_read(lua_State *L)
|
|||||||
int w_File_write(lua_State *L)
|
int w_File_write(lua_State *L)
|
||||||
{
|
{
|
||||||
File *file = luax_checkfile(L, 1);
|
File *file = luax_checkfile(L, 1);
|
||||||
bool result;
|
bool result = false;
|
||||||
|
|
||||||
if (lua_isstring(L, 2))
|
if (lua_isstring(L, 2))
|
||||||
{
|
{
|
||||||
@@ -156,6 +156,22 @@ int w_File_write(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int w_File_flush(lua_State *L)
|
||||||
|
{
|
||||||
|
File *file = luax_checkfile(L, 1);
|
||||||
|
bool success = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
success = file->flush();
|
||||||
|
}
|
||||||
|
catch (love::Exception &e)
|
||||||
|
{
|
||||||
|
return ioError(L, "%s", e.what());
|
||||||
|
}
|
||||||
|
luax_pushboolean(L, success);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int w_File_eof(lua_State *L)
|
int w_File_eof(lua_State *L)
|
||||||
{
|
{
|
||||||
File *file = luax_checkfile(L, 1);
|
File *file = luax_checkfile(L, 1);
|
||||||
@@ -191,16 +207,10 @@ int w_File_seek(lua_State *L)
|
|||||||
|
|
||||||
int w_File_lines(lua_State *L)
|
int w_File_lines(lua_State *L)
|
||||||
{
|
{
|
||||||
File *file;
|
File *file = luax_checkfile(L, 1);
|
||||||
|
|
||||||
if (luax_istype(L, 1, FILESYSTEM_FILE_T))
|
lua_pushnumber(L, 0); // File position.
|
||||||
{
|
luax_pushboolean(L, file->getMode() != File::CLOSED); // Save current file mode.
|
||||||
file = luax_checktype<File>(L, 1, "File", FILESYSTEM_FILE_T);
|
|
||||||
lua_pushnumber(L, 0); // File position.
|
|
||||||
luax_pushboolean(L, file->getMode() != File::CLOSED); // Save current file mode.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return luaL_error(L, "Expected File.");
|
|
||||||
|
|
||||||
if (file->getMode() != File::READ)
|
if (file->getMode() != File::READ)
|
||||||
{
|
{
|
||||||
@@ -222,6 +232,59 @@ int w_File_lines(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int w_File_setBuffer(lua_State *L)
|
||||||
|
{
|
||||||
|
File *file = luax_checkfile(L, 1);
|
||||||
|
const char *str = luaL_checkstring(L, 2);
|
||||||
|
int64 size = (int64) luaL_optnumber(L, 3, 0.0);
|
||||||
|
|
||||||
|
File::BufferMode bufmode;
|
||||||
|
if (!File::getConstant(str, bufmode))
|
||||||
|
return luaL_error(L, "Incorrect file buffer mode: %s", str);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
success = file->setBuffer(bufmode, size);
|
||||||
|
}
|
||||||
|
catch (love::Exception &e)
|
||||||
|
{
|
||||||
|
return ioError(L, "%s", e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
luax_pushboolean(L, success);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int w_File_getBuffer(lua_State *L)
|
||||||
|
{
|
||||||
|
File *file = luax_checkfile(L, 1);
|
||||||
|
int64 size = 0;
|
||||||
|
File::BufferMode bufmode = file->getBuffer(size);
|
||||||
|
const char *str = 0;
|
||||||
|
|
||||||
|
if (!File::getConstant(bufmode, str))
|
||||||
|
return ioError(L, "Unknown file buffer mode.");
|
||||||
|
|
||||||
|
lua_pushstring(L, str);
|
||||||
|
lua_pushnumber(L, (lua_Number) size);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int w_File_getMode(lua_State *L)
|
||||||
|
{
|
||||||
|
File *file = luax_checkfile(L, 1);
|
||||||
|
|
||||||
|
File::Mode mode = file->getMode();
|
||||||
|
const char *str = 0;
|
||||||
|
|
||||||
|
if (!File::getConstant(mode, str))
|
||||||
|
return ioError(L, "Unknown file mode.");
|
||||||
|
|
||||||
|
lua_pushstring(L, str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg functions[] =
|
static const luaL_Reg functions[] =
|
||||||
{
|
{
|
||||||
{ "getSize", w_File_getSize },
|
{ "getSize", w_File_getSize },
|
||||||
@@ -230,10 +293,14 @@ static const luaL_Reg functions[] =
|
|||||||
{ "isOpen", w_File_isOpen },
|
{ "isOpen", w_File_isOpen },
|
||||||
{ "read", w_File_read },
|
{ "read", w_File_read },
|
||||||
{ "write", w_File_write },
|
{ "write", w_File_write },
|
||||||
|
{ "flush", w_File_flush },
|
||||||
{ "eof", w_File_eof },
|
{ "eof", w_File_eof },
|
||||||
{ "tell", w_File_tell },
|
{ "tell", w_File_tell },
|
||||||
{ "seek", w_File_seek },
|
{ "seek", w_File_seek },
|
||||||
{ "lines", w_File_lines },
|
{ "lines", w_File_lines },
|
||||||
|
{ "setBuffer", w_File_setBuffer },
|
||||||
|
{ "getBuffer", w_File_getBuffer },
|
||||||
|
{ "getMode", w_File_getMode },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,10 +40,14 @@ int w_File_close(lua_State *L);
|
|||||||
int w_File_isOpen(lua_State *L);
|
int w_File_isOpen(lua_State *L);
|
||||||
int w_File_read(lua_State *L);
|
int w_File_read(lua_State *L);
|
||||||
int w_File_write(lua_State *L);
|
int w_File_write(lua_State *L);
|
||||||
|
int w_File_flush(lua_State *L);
|
||||||
int w_File_eof(lua_State *L);
|
int w_File_eof(lua_State *L);
|
||||||
int w_File_tell(lua_State *L);
|
int w_File_tell(lua_State *L);
|
||||||
int w_File_seek(lua_State *L);
|
int w_File_seek(lua_State *L);
|
||||||
int w_File_lines(lua_State *L);
|
int w_File_lines(lua_State *L);
|
||||||
|
int w_File_setBuffer(lua_State *L);
|
||||||
|
int w_File_getBuffer(lua_State *L);
|
||||||
|
int w_File_getMode(lua_State *L);
|
||||||
extern "C" int luaopen_file(lua_State *L);
|
extern "C" int luaopen_file(lua_State *L);
|
||||||
|
|
||||||
} // physfs
|
} // physfs
|
||||||
|
|||||||
Reference in New Issue
Block a user