mirror of
https://github.com/love2d/love.git
synced 2026-08-15 15:51:12 +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);
|
||||
}
|
||||
|
||||
bool File::getConstant(Mode in, const char *&out)
|
||||
bool File::getConstant(Mode in, const char *&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[] =
|
||||
{
|
||||
{"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::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
|
||||
} // love
|
||||
|
||||
@@ -56,6 +56,14 @@ public:
|
||||
MODE_MAX_ENUM
|
||||
};
|
||||
|
||||
enum BufferMode
|
||||
{
|
||||
BUFFER_NONE,
|
||||
BUFFER_LINE,
|
||||
BUFFER_FULL,
|
||||
BUFFER_MAX_ENUM
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to indicate ALL data in a file.
|
||||
**/
|
||||
@@ -128,6 +136,12 @@ public:
|
||||
**/
|
||||
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.
|
||||
*
|
||||
@@ -150,6 +164,24 @@ public:
|
||||
**/
|
||||
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.
|
||||
* @return The current mode of the File; CLOSED, READ, WRITE or APPEND.
|
||||
@@ -169,13 +201,19 @@ public:
|
||||
virtual std::string getExtension() const = 0;
|
||||
|
||||
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:
|
||||
|
||||
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;
|
||||
|
||||
}; // File
|
||||
|
||||
} // filesystem
|
||||
|
||||
@@ -39,7 +39,9 @@ extern bool hack_setupWriteDirectory();
|
||||
File::File(const std::string &filename)
|
||||
: filename(filename)
|
||||
, file(0)
|
||||
, mode(filesystem::File::CLOSED)
|
||||
, mode(CLOSED)
|
||||
, bufferMode(BUFFER_NONE)
|
||||
, bufferSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -83,6 +85,13 @@ bool File::open(Mode mode)
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -169,7 +178,10 @@ int64 File::read(void *dst, int64 size)
|
||||
// Sadly, we'll have to clamp to 32 bits here
|
||||
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;
|
||||
}
|
||||
@@ -182,13 +194,23 @@ bool File::write(const void *data, int64 size)
|
||||
// Another clamp, for the time being.
|
||||
size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
|
||||
|
||||
if (size < 0)
|
||||
throw love::Exception("Invalid write size.");
|
||||
|
||||
// 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.
|
||||
if (written != size)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -197,6 +219,14 @@ bool File::write(const Data *data, int64 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
|
||||
// MSVC doesn't like the 'this' keyword
|
||||
// well, we'll use 'that'.
|
||||
@@ -226,7 +256,7 @@ int64 File::tell()
|
||||
if (file == 0)
|
||||
return -1;
|
||||
|
||||
return (int64)PHYSFS_tell(file);
|
||||
return (int64) PHYSFS_tell(file);
|
||||
}
|
||||
|
||||
bool File::seek(uint64 pos)
|
||||
@@ -234,11 +264,56 @@ bool File::seek(uint64 pos)
|
||||
if (file == 0)
|
||||
return false;
|
||||
|
||||
if (!PHYSFS_seek(file, (PHYSFS_uint64)pos))
|
||||
if (!PHYSFS_seek(file, (PHYSFS_uint64) pos))
|
||||
return false;
|
||||
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
|
||||
{
|
||||
return filename;
|
||||
|
||||
@@ -43,17 +43,6 @@ namespace physfs
|
||||
|
||||
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:
|
||||
|
||||
/**
|
||||
@@ -74,13 +63,30 @@ public:
|
||||
int64 read(void *dst, int64 size);
|
||||
bool write(const void *data, int64 size);
|
||||
bool write(const Data *data, int64 size = ALL);
|
||||
bool flush();
|
||||
bool eof();
|
||||
int64 tell();
|
||||
bool seek(uint64 pos);
|
||||
bool setBuffer(BufferMode bufmode, int64 size);
|
||||
BufferMode getBuffer(int64 &size) const;
|
||||
Mode getMode() const;
|
||||
std::string getFilename() 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
|
||||
|
||||
} // physfs
|
||||
|
||||
@@ -122,7 +122,7 @@ int w_File_read(lua_State *L)
|
||||
int w_File_write(lua_State *L)
|
||||
{
|
||||
File *file = luax_checkfile(L, 1);
|
||||
bool result;
|
||||
bool result = false;
|
||||
|
||||
if (lua_isstring(L, 2))
|
||||
{
|
||||
@@ -156,6 +156,22 @@ int w_File_write(lua_State *L)
|
||||
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)
|
||||
{
|
||||
File *file = luax_checkfile(L, 1);
|
||||
@@ -191,16 +207,10 @@ int w_File_seek(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))
|
||||
{
|
||||
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.");
|
||||
lua_pushnumber(L, 0); // File position.
|
||||
luax_pushboolean(L, file->getMode() != File::CLOSED); // Save current file mode.
|
||||
|
||||
if (file->getMode() != File::READ)
|
||||
{
|
||||
@@ -222,6 +232,59 @@ int w_File_lines(lua_State *L)
|
||||
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[] =
|
||||
{
|
||||
{ "getSize", w_File_getSize },
|
||||
@@ -230,10 +293,14 @@ static const luaL_Reg functions[] =
|
||||
{ "isOpen", w_File_isOpen },
|
||||
{ "read", w_File_read },
|
||||
{ "write", w_File_write },
|
||||
{ "flush", w_File_flush },
|
||||
{ "eof", w_File_eof },
|
||||
{ "tell", w_File_tell },
|
||||
{ "seek", w_File_seek },
|
||||
{ "lines", w_File_lines },
|
||||
{ "setBuffer", w_File_setBuffer },
|
||||
{ "getBuffer", w_File_getBuffer },
|
||||
{ "getMode", w_File_getMode },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -40,10 +40,14 @@ int w_File_close(lua_State *L);
|
||||
int w_File_isOpen(lua_State *L);
|
||||
int w_File_read(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_tell(lua_State *L);
|
||||
int w_File_seek(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);
|
||||
|
||||
} // physfs
|
||||
|
||||
Reference in New Issue
Block a user