Added File:setBuffer/getBuffer, File:flush, and File:getMode.

This commit is contained in:
Alex Szpakowski
2013-06-27 06:26:20 -03:00
parent 186bcae7cb
commit 8fbf43fcc3
6 changed files with 237 additions and 28 deletions
+20 -1
View File
@@ -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
+39 -1
View File
@@ -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
+80 -5
View File
@@ -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;
+17 -11
View File
@@ -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
+77 -10
View File
@@ -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