Initial Mercurial commit.

This commit is contained in:
rude
2009-07-26 15:46:49 +02:00
commit dcb3dfd83d
417 changed files with 124060 additions and 0 deletions
+208
View File
@@ -0,0 +1,208 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "File.h"
// STD
#include <string.h>
// LOVE
#include "Filesystem.h"
#include "FileData.h"
namespace love
{
namespace filesystem
{
namespace physfs
{
extern bool hack_setupWriteDirectory();
File::File(std::string filename)
: filename(filename), file(0), mode(filesystem::File::CLOSED)
{
}
File::~File()
{
}
bool File::open(Mode mode)
{
// Check whether the write directory is set.
if((mode == APPEND || mode == WRITE) && (PHYSFS_getWriteDir() == 0))
if(!hack_setupWriteDirectory())
return false;
// File already open?
if(file != 0)
return false;
this->mode = mode;
switch(mode)
{
case READ:
file = PHYSFS_openRead(filename.c_str());
break;
case APPEND:
file = PHYSFS_openAppend(filename.c_str());
break;
case WRITE:
file = PHYSFS_openWrite(filename.c_str());
break;
case CLOSED:
// Heh. Case closed.
return true;
}
return (file != 0);
}
bool File::close()
{
if(!PHYSFS_close(file))
return false;
mode = CLOSED;
file = 0;
return true;
}
unsigned int File::getSize()
{
// If the file is closed, open it to
// check the size.
if(file == 0)
{
open(READ);
unsigned int size = (unsigned int)PHYSFS_fileLength(file);
close();
return size;
}
return (unsigned int)PHYSFS_fileLength(file);
}
Data * File::read(int size)
{
bool isOpen = (file != 0);
if(!isOpen)
open(READ);
int max = (int)PHYSFS_fileLength(file);
size = (size == ALL) ? max : size;
size = (size > max) ? max : size;
FileData * fileData = new FileData(size, getFilename());
read(fileData->getData(), size);
if(!isOpen)
close();
return fileData;
}
int File::read(void * dst, int size)
{
bool isOpen = (file != 0);
if(!isOpen)
open(READ);
int max = (int)PHYSFS_fileLength(file);
size = (size == ALL) ? max : size;
size = (size > max) ? max : size;
int read = (int)PHYSFS_read(file, dst, 1, size);
if(!isOpen)
close();
return read;
}
bool File::write(const void * data, int size)
{
// Try to write.
int written = static_cast<int>(PHYSFS_write(file, data, 1, size));
// Check that correct amount of data was written.
if(written != size)
return false;
return true;
}
bool File::write(const Data * data, int size)
{
return write(data->getData(), (size == ALL) ? data->getSize() : size);
}
bool File::eof()
{
if(file == 0 || PHYSFS_eof(file))
return true;
return false;
}
int File::tell()
{
if(file == 0)
return -1;
return (int)PHYSFS_tell(file);
}
bool File::seek(int pos)
{
if(file == 0)
return false;
if(!PHYSFS_seek(file, (PHYSFS_uint64)pos))
return false;
return true;
}
std::string File::getFilename() const
{
return filename;
}
std::string File::getExtension() const
{
std::string::size_type idx = filename.rfind('.');
if(idx != std::string::npos)
return filename.substr(idx+1);
else
return std::string();
}
filesystem::File::Mode File::getMode()
{
return mode;
}
} // physfs
} // filesystem
} // love
+84
View File
@@ -0,0 +1,84 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_FILESYSTEM_PHYSFS_FILE_H
#define LOVE_FILESYSTEM_PHYSFS_FILE_H
// LOVE
#include <filesystem/File.h>
// PhysFS
#include <physfs.h>
// STD
#include <string>
namespace love
{
namespace filesystem
{
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:
/**
* Constructs an File with the given source and filename.
* @param source The source from which to load the file. (Archive or directory)
* @param filename The relative filepath of the file to load from the source.
**/
File(std::string filename);
virtual ~File();
// Implements love::filesystem::File.
bool open(Mode mode);
bool close();
unsigned int getSize();
Data * read(int size = ALL);
int read(void * dst, int size);
bool write(const void * data, int size);
bool write(const Data * data, int size = ALL);
bool eof();
int tell();
bool seek(int pos);
Mode getMode();
std::string getFilename() const;
std::string getExtension() const;
}; // File
} // physfs
} // filesystem
} // love
#endif // LOVE_FILESYSTEM_PHYSFS_FILE_H
@@ -0,0 +1,66 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "FileData.h"
// STD
#include <iostream>
namespace love
{
namespace filesystem
{
namespace physfs
{
FileData::FileData(int size, const std::string & filename)
: data(new char[size]), size(size), filename(filename)
{
if(filename.rfind('.') != std::string::npos)
extension = filename.substr(filename.rfind('.')+1);
}
FileData::~FileData()
{
delete [] data;
}
void * FileData::getData() const
{
return (void*)data;
}
int FileData::getSize() const
{
return size;
}
const std::string & FileData::getFilename() const
{
return filename;
}
const std::string & FileData::getExtension() const
{
return extension;
}
} // physfs
} // filesystem
} // love
+68
View File
@@ -0,0 +1,68 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_FILESYSTEM_PHYSFS_FILE_DATA_H
#define LOVE_FILESYSTEM_PHYSFS_FILE_DATA_H
// LOVE
#include <filesystem/FileData.h>
namespace love
{
namespace filesystem
{
namespace physfs
{
class FileData : public love::filesystem::FileData
{
private:
// The actual data.
char * data;
// Size of the data.
int size;
// The filename used for error purposes.
std::string filename;
// The extension (without dot). Used to identify file type.
std::string extension;
public:
FileData(int size, const std::string & filename);
virtual ~FileData();
// Implements Data.
void * getData() const;
int getSize() const;
const std::string & getFilename() const;
const std::string & getExtension() const;
}; // FileData
} // physfs
} // filesystem
} // love
#endif // LOVE_FILESYSTEM_PHYSFS_FILE_DATA_H
@@ -0,0 +1,497 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "Filesystem.h"
// Physfs
#include <physfs.h>
namespace love
{
namespace filesystem
{
namespace physfs
{
Filesystem::Filesystem()
: open_count(0), buffer(0)
{
// TODO: love.exe << fail
if(!PHYSFS_init("love.exe"))
throw Exception(PHYSFS_getLastError());
}
Filesystem::~Filesystem()
{
PHYSFS_deinit();
}
const char * Filesystem::getName() const
{
return "love.filesystem.physfs";
}
bool Filesystem::setIdentity( const char * ident )
{
// Check whether save directory is already set.
if(!save_identity.empty() || PHYSFS_getWriteDir() != 0)
return false;
// Store the save directory.
save_identity = std::string(ident);
// Generate the relative path to the game save folder.
save_path_relative = std::string(LOVE_APPDATA_FOLDER LOVE_PATH_SEPARATOR) + save_identity;
// Generate the full path to the game save folder.
save_path_full = std::string(getAppdataDirectory()) + std::string(LOVE_PATH_SEPARATOR);
save_path_full += save_path_relative;
std::cout << save_path_full << std::endl;
// We now have something like:
// save_identity: game
// save_path_relative: ./LOVE/game
// save_path_full: C:\Documents and Settings\user\Application Data/LOVE/game
// Try to add the save directory to the search path.
// (No error on fail, it means that the path doesn't exist).
PHYSFS_addToSearchPath(save_path_full.c_str(), 1);
return true;
}
bool Filesystem::setSource(const char * source)
{
// Check whether directory is already set.
if(!game_source.empty())
return false;
// Add the directory.
if(!PHYSFS_addToSearchPath(source, 0))
return false;
// Save the game source.
game_source = std::string(source);
return true;
}
bool Filesystem::setupWriteDirectory()
{
// These must all be set.
if(save_identity.empty() || save_path_full.empty() || save_path_relative.empty())
return false;
// Set the appdata folder as writable directory.
// (We must create the save folder before mounting it).
if(!PHYSFS_setWriteDir(getAppdataDirectory()))
return false;
// Create the save folder. (We're now "at" %APPDATA%).
if(!mkdir(save_path_relative.c_str()))
{
PHYSFS_setWriteDir(0); // Clear the write directory in case of error.
return false;
}
// Set the final write directory.
if(!PHYSFS_setWriteDir(save_path_full.c_str()))
return false;
// Add the directory. (Well not be readded if already present).
if(!PHYSFS_addToSearchPath(save_path_full.c_str(), 1))
{
PHYSFS_setWriteDir(0); // Clear the write directory in case of error.
return false;
}
return true;
}
File * Filesystem::newFile(const char *filename)
{
return new File(filename);
}
FileData * Filesystem::newFileData(void * data, int size, const char * filename)
{
FileData * fd = new FileData(size, std::string(filename));
// Copy the data into
memcpy(fd->getData(), data, size);
return fd;
}
const char * Filesystem::getWorkingDirectory()
{
#ifdef LOVE_WINDOWS
_getcwd(cwdbuffer, _MAX_PATH);
#else
char * temp = getcwd(cwdbuffer, MAXPATHLEN);
if(temp == 0)
return 0;
#endif
return cwdbuffer;
}
const char * Filesystem::getUserDirectory()
{
return PHYSFS_getUserDir();
}
const char * Filesystem::getAppdataDirectory()
{
#ifdef LOVE_WINDOWS
return getenv("APPDATA");
#else
return getUserDirectory();
#endif
}
const char * Filesystem::getSaveDirectory()
{
return save_path_full.c_str();
}
bool Filesystem::exists(const char * file)
{
if(PHYSFS_exists(file))
return true;
return false;
}
bool Filesystem::isDirectory(const char * file)
{
if(PHYSFS_isDirectory(file))
return true;
return false;
}
bool Filesystem::isFile(const char * file)
{
return exists(file) && !isDirectory(file);
}
bool Filesystem::mkdir(const char * file)
{
if(PHYSFS_getWriteDir() == 0 && !setupWriteDirectory())
return false;
if(!PHYSFS_mkdir(file))
return false;
return true;
}
bool Filesystem::remove(const char * file)
{
if(PHYSFS_getWriteDir() == 0 && !setupWriteDirectory())
return false;
if(!PHYSFS_delete(file))
return false;
return true;
}
int Filesystem::read(lua_State * L)
{
// The file to read from. The file must either be created
// on-the-fly, or passed as a parameter.
File * file;
if(lua_isstring(L, 1))
{
// Create the file.
file = newFile(lua_tostring(L, 1));
file->open(File::READ);
}
else
return luaL_error(L, "Expected filename.");
// Optionally, the caller can specify whether to read
// the whole file, or just a part of it.
int count = luaL_optint(L, 2, file->getSize());
// Read the data.
Data * data = file->read(count);
// Error check.
if(data == 0)
return luaL_error(L, "File could not be read.");
// Close and delete the file, if we created it.
// (I.e. if the first parameter is a string).
if(lua_isstring(L, 1))
file->release();
// Push the string.
lua_pushlstring(L, (char*)data->getData(), data->getSize());
// Push the size.
lua_pushinteger(L, data->getSize());
// Lua has a copy now, so we can free it.
data->release();
return 2;
}
int Filesystem::write(lua_State * L)
{
// The file to write to. The file must either be created
// on-the-fly, or passed as a parameter.
File * file;
// We know for sure that the second parameter must be a
// a string, so let's check that first.
if(!lua_isstring(L, 2))
return luaL_error(L, "Second argument must be a string.");
// The third paramter must be a number to indicate the size of
// the data.
if(!lua_isnumber(L, 3))
return luaL_error(L, "Third argument must be a number.");
if(lua_isstring(L, 1))
{
// Create the file.
file = newFile(lua_tostring(L, 1));
}
else
return luaL_error(L, "Expected filename.");
// Get the current mode of the file.
File::Mode mode = file->getMode();
if(mode == File::CLOSED)
{
// It should be possible to use append mode, but
// normal File::Mode::Write is the default.
int mode = luaL_optint(L, 4, File::WRITE);
// Open the file.
if(!file->open((File::Mode)mode))
return luaL_error(L, "Could not open file.");
}
size_t length = 0;
const char * input = lua_tolstring(L, 2, &length);
// Get how much we should write. Length of string default.
length = luaL_optint(L, 3, length);
// Write the data.
bool success = file->write(input, length);
// Close and delete the file, if we created
// it in this function.
if(lua_isstring(L, 1))
{
// Kill the file if "we" created it.
file->close();
file->release();
}
if(!success)
return luaL_error(L, "Data could not be written.");
lua_pushboolean(L, success);
return 1;
}
int Filesystem::enumerate(lua_State * L)
{
int n = lua_gettop(L);
if( n != 1 )
return luaL_error(L, "Function requires a single parameter.");
int type = lua_type(L, 1);
if(type != LUA_TSTRING)
return luaL_error(L, "Function requires parameter of type string.");
const char * dir = lua_tostring(L, 1);
char **rc = PHYSFS_enumerateFiles(dir);
char **i;
int index = 1;
lua_newtable(L);
for (i = rc; *i != 0; i++)
{
lua_pushinteger(L, index);
lua_pushstring(L, *i);
lua_settable(L, -3);
index++;
}
PHYSFS_freeList(rc);
return 1;
}
int Filesystem::lines(lua_State * L)
{
File * file;
if(lua_isstring(L, 1))
{
file = newFile(lua_tostring(L, 1));
if(!file->open(File::READ))
return luaL_error(L, "Could not open file %s.\n", lua_tostring(L, 1));
lua_pop(L, 1);
luax_newtype(L, "File", LOVE_FILESYSTEM_FILE_BITS, file, false);
lua_pushboolean(L, 1); // 1 = autoclose.
}
else
return luaL_error(L, "Expected filename.");
// Reset the file position.
if(!file->seek(0))
return luaL_error(L, "File does not appear to be open.\n");
lua_pushcclosure(L, lines_i, 2);
return 1;
}
int Filesystem::lines_i(lua_State * L)
{
// We're using a 1k buffer.
const static int bufsize = 8;
static char buf[bufsize];
File * file = luax_checktype<File>(L, lua_upvalueindex(1), "File", LOVE_FILESYSTEM_FILE_BITS);
int close = (int)lua_tointeger(L, lua_upvalueindex(2));
// Find the next newline.
// pos must be at the start of the line we're trying to find.
int pos = file->tell();
int newline = -1;
int totalread = 0;
while(!file->eof())
{
int current = file->tell();
int read = file->read(buf, bufsize);
totalread += read;
if(read < 0)
return luaL_error(L, "Readline failed!");
for(int i = 0;i<read;i++)
{
if(buf[i] == '\n')
{
newline = current+i;
break;
}
}
if(newline > 0)
break;
}
// Special case for the last "line".
if(newline <= 0 && file->eof() && totalread > 0)
newline = pos + totalread;
// We've got a newline.
if(newline > 0)
{
// Ok, we've got a line.
int linesize = (newline-pos);
// Allocate memory for the string.
char * str = new char[linesize];
// Read it.
file->seek(pos);
if(file->read(str, linesize) == -1)
return luaL_error(L, "Read error.");
if(str[linesize-1]=='\r')
linesize -= 1;
lua_pushlstring(L, str, linesize);
// Free the memory. Lua has a copy now.
delete[] str;
// Set the beginning of the next line.
if(!file->eof())
file->seek(newline+1);
return 1;
}
if(close)
{
file->close();
file->release();
}
// else: (newline <= 0)
return 0;
}
int Filesystem::load(lua_State * L)
{
// Need only one arg.
luax_assert_argc(L, 1, 1);
// Must be string.
if(!lua_isstring(L, -1))
return luaL_error(L, "The argument must be a string.");
const char * filename = lua_tostring(L, -1);
// The file must exist.
if(!exists(filename))
return luaL_error(L, "File %s does not exist.", filename);
// Create the file.
File * file = newFile(filename);
file->open(File::READ);
// Get the data from the file.
Data * data = file->read();
int status = luaL_loadbuffer(L, (const char *)data->getData(), data->getSize(), filename);
data->release();
file->release();
// Load the chunk, but don't run it.
switch (status)
{
case LUA_ERRMEM:
return luaL_error(L, "Memory allocation error: %s\n", lua_tostring(L, -1));
case LUA_ERRSYNTAX:
return luaL_error(L, "Syntax error: %s\n", lua_tostring(L, -1));
default: // success
return 1;
}
}
} // physfs
} // filesystem
} // love
+267
View File
@@ -0,0 +1,267 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_FILESYSTEM_PHYSFS_FILESYSTEM_H
#define LOVE_FILESYSTEM_PHYSFS_FILESYSTEM_H
// STD
#include <cstring>
#include <iostream>
#include <string>
// LOVE
#include <common/Module.h>
#include <common/config.h>
#include <common/constants.h>
// Module
#include "File.h"
#include "FileData.h"
// For great CWD. (Current Working Directory)
// Using this instead of boost::filesystem which totally
// cramped our style.
#ifdef LOVE_WINDOWS
# include <direct.h>
#else
# include <sys/param.h>
# include <unistd.h>
#endif
// In Windows, we would like to use "LOVE" as the
// application folder, but in Linux, we like .love.
#ifdef LOVE_WINDOWS
# define LOVE_APPDATA_FOLDER "LOVE"
# define LOVE_PATH_SEPARATOR "/"
# define LOVE_MAX_PATH _MAX_PATH
#else
# define LOVE_APPDATA_FOLDER ".love"
# define LOVE_PATH_SEPARATOR "/"
# define LOVE_MAX_PATH MAXPATHLEN
#endif
namespace love
{
namespace filesystem
{
namespace physfs
{
class Filesystem : public Module
{
private:
// Counts open files.
int open_count;
// Pointer used for file reads.
char * buffer;
// Buffer used for getcwd in Linux.
char cwdbuffer[LOVE_MAX_PATH];
// This name will be used to create the folder
// in the appdata/userdata folder.
std::string save_identity;
// Full and relative paths of the game save folder.
// (Relative to the %APPDATA% folder, meaning that the
// relative string will look something like: ./LOVE/game)
std::string save_path_relative, save_path_full;
// The full path to the source of the game.
std::string game_source;
protected:
public:
Filesystem();
~Filesystem();
const char * getName() const;
/**
* This sets up the save directory. If the
* it is already set up, nothing happens.
* @return True on success, false otherwise.
**/
bool setupWriteDirectory();
/**
* Sets the name of the save folder.
* @param ident The name of the game. Will be used to
* to create the folder in the LOVE data folder.
**/
bool setIdentity(const char * ident);
/**
* Sets the path to the game source.
* This can only be set once.
* @param source Path to a directory or a .love-file.
**/
bool setSource(const char * source);
/**
* Creates a new file.
**/
File * newFile(const char* filename);
/**
* Creates a new FileData object. Data will be copied.
* @param data Pointer to the data.
* @param size The size of the data.
* @param filename The full filename used to file type identification.
**/
FileData * newFileData(void * data, int size, const char * filename);
/**
* Gets the current working directory.
**/
const char * getWorkingDirectory();
/**
* Gets the user home directory.
**/
const char * getUserDirectory();
/**
* Gets the APPDATA directory. On Windows, this is the folder
* in the %APPDATA% enviroment variable. On Linux, this is the
* user home folder.
**/
const char * getAppdataDirectory();
/**
* Gets the full path of the save folder.
**/
const char * getSaveDirectory();
/**
* Checks whether a file exists in the current search path
* or not.
* @param file The filename to check.
**/
bool exists(const char * file);
/**
* Checks if an existing file really is a directory.
* @param file The filename to check.
**/
bool isDirectory(const char * file);
/**
* Checks if an existing file really is a file,
* and not a directory.
* @param file The filename to check.
**/
bool isFile(const char * file);
/**
* Creates a directory. Write dir must be set.
* @param file The directory to create.
**/
bool mkdir(const char * file);
/**
* Removes a file (or directory).
* @param file The file or directory to remove.
**/
bool remove(const char * file);
/**
* Opens a file for reading or writing. (Depends
* on the mode chosen at the time of creation).
* @param file The file to open.
* @param mode The mode to open the file in.
**/
bool open(File * file, File::Mode mode);
/**
* Closes a file.
* @param file The file to close.
**/
bool close(File * file);
/**
* Reads count bytes from an open file.
* The first parameter is either a File or
* a string. An optional second parameter specified the
* max number of bytes to read.
**/
int read(lua_State * L);
/**
* Write the bytes in data to the file. File
* must be opened for write.
* The first parameter is either a File or
* a string.
**/
int write(lua_State * L);
/**
* Check if end-of-file is reached.
* @return True if EOF, false otherwise.
**/
bool eof(File * file);
/**
* Gets the current position in a file.
* @param file An open File.
**/
int tell(File * file);
/**
* Seek to a position within a file.
* @param pos The position to seek to.
**/
bool seek(File * file, int pos);
/**
* This "native" method returns a table of all
* files in a given directory.
**/
int enumerate(lua_State * L);
/**
* Returns an iterator which iterates over
* lines in files.
**/
int lines(lua_State * L);
/**
* The line iterator function.
**/
static int lines_i(lua_State * L);
/**
* Loads a file without running it. The loaded
* chunk is returned as a function.
* @param filename The filename of the file to load.
* @return A function.
**/
int load(lua_State * L);
}; // Filesystem
} // physfs
} // filesystem
} // love
#endif // LOVE_FILESYSTEM_PHYSFS_FILESYSTEM_H
+225
View File
@@ -0,0 +1,225 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "wrap_File.h"
namespace love
{
namespace filesystem
{
namespace physfs
{
File * luax_checkfile(lua_State * L, int idx)
{
return luax_checktype<File>(L, idx, "File", LOVE_FILESYSTEM_FILE_BITS);
}
int _wrap_File_getSize(lua_State * L)
{
File * t = luax_checkfile(L, 1);
lua_pushinteger(L, t->getSize());
return 1;
}
int _wrap_File_open(lua_State * L)
{
File * file = luax_checkfile(L, 1);
int mode = luaL_optint(L, 2, File::READ);
lua_pushboolean(L, file->open((File::Mode)mode) ? 1 : 0);
return 1;
}
int _wrap_File_close(lua_State * L)
{
File * file = luax_checkfile(L, 1);
lua_pushboolean(L, file->close() ? 1 : 0);
return 1;
}
int _wrap_File_read(lua_State * L)
{
File * file = luax_checkfile(L, 1);
Data * d = file->read(luaL_optint(L, 2, file->getSize()));
lua_pushlstring(L, (const char*) d->getData(), d->getSize());
lua_pushnumber(L, d->getSize());
d->release();
return 2;
}
int _wrap_File_write(lua_State * L)
{
File * file = luax_checkfile(L, 1);
bool result;
if ( file->getMode() == File::CLOSED )
return luaL_error(L, "File is not open.");
if ( lua_isstring(L, 2) )
result = file->write(lua_tostring(L, 2), luaL_optint(L, 3, lua_objlen(L, 2)));
else
return luaL_error(L, "String expected.");
lua_pushboolean(L, result);
return 1;
}
int _wrap_File_eof(lua_State * L)
{
File * file = luax_checkfile(L, 1);
lua_pushboolean(L, file->eof() ? 1 : 0);
return 1;
}
int _wrap_File_tell(lua_State * L)
{
File * file = luax_checkfile(L, 1);
lua_pushinteger(L, file->tell());
return 1;
}
int _wrap_File_seek(lua_State * L)
{
File * file = luax_checkfile(L, 1);
int pos = luaL_checkinteger(L, 2);
lua_pushboolean(L, file->seek(pos) ? 1 : 0);
return 1;
}
//yes, the following two are copy-pasted and slightly edited
int _wrap_File_lines(lua_State * L)
{
File * file;
if(luax_istype(L, 1, LOVE_FILESYSTEM_FILE_BITS))
{
file = luax_checktype<File>(L, 1, "File", LOVE_FILESYSTEM_FILE_BITS);
lua_pushboolean(L, 0); // 0 = do not close.
}
else
return luaL_error(L, "Expected file handle.");
// Reset the file position.
if(!file->seek(0))
return luaL_error(L, "File does not appear to be open.\n");
lua_pushcclosure(L, lines_i, 2);
return 1;
}
int lines_i(lua_State * L)
{
// We're using a 1k buffer.
const static int bufsize = 1024;
static char buf[bufsize];
File * file = luax_checktype<File>(L, lua_upvalueindex(1), "File", LOVE_FILESYSTEM_FILE_BITS);
int close = (int)lua_tointeger(L, lua_upvalueindex(2));
// Find the next newline.
// pos must be at the start of the line we're trying to find.
int pos = file->tell();
int newline = -1;
int totalread = 0;
while(!file->eof())
{
int current = file->tell();
int read = file->read(buf, bufsize);
totalread += read;
if(read < 0)
return luaL_error(L, "Readline failed!");
for(int i = 0;i<read;i++)
{
if(buf[i] == '\n')
{
newline = current+i;
break;
}
}
if(newline > 0)
break;
}
// Special case for the last "line".
if(newline <= 0 && file->eof() && totalread > 0)
newline = pos + totalread;
// We've got a newline.
if(newline > 0)
{
// Ok, we've got a line.
int linesize = (newline-pos);
// Allocate memory for the string.
char * str = new char[linesize];
// Read it.
file->seek(pos);
if(file->read(str, linesize) == -1)
return luaL_error(L, "Read error.");
if(str[linesize-1]=='\r')
linesize -= 1;
lua_pushlstring(L, str, linesize);
// Free the memory. Lua has a copy now.
delete[] str;
// Set the beginning of the next line.
if(!file->eof())
file->seek(newline+1);
return 1;
}
if(close)
{
file->close();
file->release();
}
// else: (newline <= 0)
return 0;
}
const luaL_Reg wrap_File_functions[] = {
{ "getSize", _wrap_File_getSize },
{ "open", _wrap_File_open },
{ "close", _wrap_File_close },
{ "read", _wrap_File_read },
{ "write", _wrap_File_write },
{ "eof", _wrap_File_eof },
{ "tell", _wrap_File_tell },
{ "seek", _wrap_File_seek },
{ "lines", _wrap_File_lines },
{ 0, 0 }
};
int wrap_File_open(lua_State * L)
{
luax_register_type(L, "File", wrap_File_functions);
return 0;
}
} // physfs
} // filesystem
} // love
+50
View File
@@ -0,0 +1,50 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_H
#define LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_H
// LOVE
#include <common/runtime.h>
#include "File.h"
namespace love
{
namespace filesystem
{
namespace physfs
{
File * luax_checkfile(lua_State * L, int idx);
int _wrap_File_getSize(lua_State * L);
int _wrap_File_open(lua_State * L);
int _wrap_File_close(lua_State * L);
int _wrap_File_read(lua_State * L);
int _wrap_File_write(lua_State * L);
int _wrap_File_eof(lua_State * L);
int _wrap_File_tell(lua_State * L);
int _wrap_File_seek(lua_State * L);
int _wrap_File_lines(lua_State * L);
int lines_i(lua_State * L);
int wrap_File_open(lua_State * L);
} // physfs
} // filesystem
} // love
#endif // LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_H
@@ -0,0 +1,70 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "wrap_FileData.h"
#include <common/wrap_Data.h>
namespace love
{
namespace filesystem
{
namespace physfs
{
FileData * luax_checkfiledata(lua_State * L, int idx)
{
return luax_checktype<FileData>(L, idx, "FileData", LOVE_FILESYSTEM_FILE_DATA_BITS);
}
int _wrap_FileData_getFilename(lua_State * L)
{
FileData * t = luax_checkfiledata(L, 1);
lua_pushstring(L, t->getFilename().c_str());
return 1;
}
int _wrap_FileData_getExtension(lua_State * L)
{
FileData * t = luax_checkfiledata(L, 1);
lua_pushstring(L, t->getExtension().c_str());
return 1;
}
const luaL_Reg wrap_FileData_functions[] = {
// Data
{ "getPointer", _wrap_Data_getPointer },
{ "getSize", _wrap_Data_getSize },
{ "getFilename", _wrap_FileData_getFilename },
{ "getExtension", _wrap_FileData_getExtension },
{ 0, 0 }
};
int wrap_FileData_open(lua_State * L)
{
luax_register_type(L, "FileData", wrap_FileData_functions);
return 0;
}
} // physfs
} // filesystem
} // love
@@ -0,0 +1,43 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_DATA_H
#define LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_DATA_H
// LOVE
#include <common/runtime.h>
#include "FileData.h"
namespace love
{
namespace filesystem
{
namespace physfs
{
FileData * luax_checkfiledata(lua_State * L, int idx);
int _wrap_FileData_getFilename(lua_State * L);
int _wrap_FileData_getExtension(lua_State * L);
int wrap_FileData_open(lua_State * L);
} // physfs
} // filesystem
} // love
#endif // LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_DATA_H
@@ -0,0 +1,252 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
// LOVE
#include "wrap_Filesystem.h"
namespace love
{
namespace filesystem
{
namespace physfs
{
static Filesystem * instance = 0;
bool hack_setupWriteDirectory()
{
if(instance != 0)
return instance->setupWriteDirectory();
return false;
}
int _wrap_setIdentity(lua_State * L)
{
const char * arg = luaL_checkstring(L, 1);
if(!instance->setIdentity(arg))
return luaL_error(L, "Could not set write directory.");
return 0;
}
int _wrap_setSource(lua_State * L)
{
const char * arg = luaL_checkstring(L, 1);
if(!instance->setSource(arg))
return luaL_error(L, "Could not set source.");
return 0;
}
int _wrap_newFile(lua_State * L)
{
const char * filename = luaL_checkstring(L, 1);
File * t = instance->newFile(filename);
luax_newtype(L, "File", LOVE_FILESYSTEM_FILE_BITS, (void*)t);
return 1;
}
int _wrap_newFileData(lua_State * L)
{
if(!lua_isstring(L, 1))
return luaL_error(L, "String expected.");
if(!lua_isstring(L, 2))
return luaL_error(L, "String expected.");
size_t length = 0;
const char * str = lua_tolstring(L, 1, &length);
const char * filename = lua_tostring(L, 2);
FileData * t = instance->newFileData((void*)str, (int)length, filename);
luax_newtype(L, "FileData", LOVE_FILESYSTEM_FILE_DATA_BITS, (void*)t);
return 1;
}
int _wrap_getWorkingDirectory(lua_State * L)
{
lua_pushstring(L, instance->getWorkingDirectory());
return 1;
}
int _wrap_getUserDirectory(lua_State * L)
{
lua_pushstring(L, instance->getUserDirectory());
return 1;
}
int _wrap_getAppdataDirectory(lua_State * L)
{
lua_pushstring(L, instance->getAppdataDirectory());
return 1;
}
int _wrap_getSaveDirectory(lua_State * L)
{
lua_pushstring(L, instance->getSaveDirectory());
return 1;
}
int _wrap_exists(lua_State * L)
{
const char * arg = luaL_checkstring(L, 1);
lua_pushboolean(L, instance->exists(arg) ? 1 : 0);
return 1;
}
int _wrap_isDirectory(lua_State * L)
{
const char * arg = luaL_checkstring(L, 1);
lua_pushboolean(L, instance->isDirectory(arg) ? 1 : 0);
return 1;
}
int _wrap_isFile(lua_State * L)
{
const char * arg = luaL_checkstring(L, 1);
lua_pushboolean(L, instance->isFile(arg) ? 1 : 0);
return 1;
}
int _wrap_mkdir(lua_State * L)
{
const char * arg = luaL_checkstring(L, 1);
lua_pushboolean(L, instance->mkdir(arg) ? 1 : 0);
return 1;
}
int _wrap_remove(lua_State * L)
{
const char * arg = luaL_checkstring(L, 1);
lua_pushboolean(L, instance->remove(arg) ? 1 : 0);
return 1;
}
int _wrap_read(lua_State * L)
{
return instance->read(L);
}
int _wrap_write(lua_State * L)
{
return instance->write(L);
}
int _wrap_enumerate(lua_State * L)
{
return instance->enumerate(L);
}
int _wrap_lines(lua_State * L)
{
return instance->lines(L);
}
int _wrap_load(lua_State * L)
{
return instance->load(L);
}
int loader(lua_State * L)
{
const char * filename = lua_tostring(L, -1);
std::string tmp(filename);
int size = tmp.size();
if(size <= 4 || strcmp(filename + (size-4), ".lua") != 0)
tmp.append(".lua");
for(int i=0;i<size-4;i++)
{
if(tmp[i] == '.')
{
tmp[i] = '/';
}
}
// Check whether file exists.
if(!instance->exists(tmp.c_str()))
{
lua_pushfstring(L, "\n\tno file \"%s\" in LOVE game directories.\n", tmp.c_str());
return 1;
}
lua_pop(L, 1);
lua_pushstring(L, tmp.c_str());
// Ok, load it.
return instance->load(L);
}
// List of functions to wrap.
const luaL_Reg wrap_Filesystem_functions[] = {
{ "setIdentity", _wrap_setIdentity },
{ "setSource", _wrap_setSource },
{ "newFile", _wrap_newFile },
{ "getWorkingDirectory", _wrap_getWorkingDirectory },
{ "getUserDirectory", _wrap_getUserDirectory },
{ "getAppdataDirectory", _wrap_getAppdataDirectory },
{ "getSaveDirectory", _wrap_getSaveDirectory },
{ "exists", _wrap_exists },
{ "isDirectory", _wrap_isDirectory },
{ "isFile", _wrap_isFile },
{ "mkdir", _wrap_mkdir },
{ "remove", _wrap_remove },
{ "read", _wrap_read },
{ "write", _wrap_write },
{ "enumerate", _wrap_enumerate },
{ "lines", _wrap_lines },
{ "load", _wrap_load },
{ 0, 0 }
};
const lua_CFunction wrap_Filesystem_types[] = {
wrap_File_open,
wrap_FileData_open,
0
};
int wrap_Filesystem_open(lua_State * L)
{
if(instance == 0)
{
try
{
instance = new Filesystem();
love::luax_register_searcher(L, loader);
}
catch(Exception & e)
{
return luaL_error(L, e.what());
}
}
luax_register_gc(L, "love.filesystem", instance);
return luax_register_module(L, wrap_Filesystem_functions, wrap_Filesystem_types);
}
} // physfs
} // filesystem
} // love
@@ -0,0 +1,66 @@
/**
* Copyright (c) 2006-2009 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_FILESYSTEM_PHYSFS_WRAP_FILESYSTEM_H
#define LOVE_FILESYSTEM_PHYSFS_WRAP_FILESYSTEM_H
// LOVE
#include "Filesystem.h"
#include "wrap_File.h"
#include "wrap_FileData.h"
namespace love
{
namespace filesystem
{
namespace physfs
{
bool hack_setupWriteDirectory();
int _wrap_setIdentity(lua_State * L);
int _wrap_setSource(lua_State * L);
int _wrap_newFile(lua_State * L);
int _wrap_newFileData(lua_State * L);
int _wrap_getWorkingDirectory(lua_State * L);
int _wrap_getUserDirectory(lua_State * L);
int _wrap_getAppdataDirectory(lua_State * L);
int _wrap_getSaveDirectory(lua_State * L);
int _wrap_exists(lua_State * L);
int _wrap_isDirectory(lua_State * L);
int _wrap_isFile(lua_State * L);
int _wrap_mkdir(lua_State * L);
int _wrap_remove(lua_State * L);
int _wrap_open(lua_State * L);
int _wrap_close(lua_State * L);
int _wrap_read(lua_State * L);
int _wrap_write(lua_State * L);
int _wrap_eof(lua_State * L);
int _wrap_tell(lua_State * L);
int _wrap_seek(lua_State * L);
int _wrap_enumerate(lua_State * L);
int _wrap_lines(lua_State * L);
int _wrap_load(lua_State * L);
int loader(lua_State * L);
int wrap_Filesystem_open(lua_State * L);
} // physfs
} // filesystem
} // love
#endif // LOVE_FILESYSTEM_PHYSFS_WRAP_FILESYSTEM_H