From 724bdbd296b445aca2853646bbd8a9a579f98d27 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 2 Jun 2014 00:22:41 -0300 Subject: [PATCH] love.graphics.newImage, love.image.newImageData, etc. no longer leave Lua-owned FileData objects floating around waiting to be GC'd when called with filename arguments, resulting in less memory use on startup (resolves issue #890.) Moved love.filesystem Lua wrapper code from src/modules/filesystem/physfs/ to src/modules/filesystem/. --- CMakeLists.txt | 12 +- .../love-framework.xcodeproj/project.pbxproj | 12 +- src/common/runtime.h | 14 +++ src/modules/audio/openal/Source.cpp | 1 + src/modules/audio/wrap_Audio.cpp | 5 +- src/modules/filesystem/physfs/File.cpp | 5 +- .../filesystem/{physfs => }/wrap_File.cpp | 7 +- .../filesystem/{physfs => }/wrap_File.h | 10 +- .../filesystem/{physfs => }/wrap_FileData.cpp | 3 - .../filesystem/{physfs => }/wrap_FileData.h | 12 +- .../{physfs => }/wrap_Filesystem.cpp | 108 +++++++++++++----- .../filesystem/{physfs => }/wrap_Filesystem.h | 23 ++-- src/modules/font/freetype/wrap_Font.cpp | 43 +++---- src/modules/graphics/opengl/wrap_Graphics.cpp | 62 +++++----- src/modules/graphics/opengl/wrap_Shader.cpp | 20 +--- src/modules/image/wrap_Image.cpp | 40 +++---- src/modules/sound/wrap_Sound.cpp | 15 +-- 17 files changed, 215 insertions(+), 177 deletions(-) rename src/modules/filesystem/{physfs => }/wrap_File.cpp (98%) rename src/modules/filesystem/{physfs => }/wrap_File.h (90%) rename src/modules/filesystem/{physfs => }/wrap_FileData.cpp (98%) rename src/modules/filesystem/{physfs => }/wrap_FileData.h (85%) rename src/modules/filesystem/{physfs => }/wrap_Filesystem.cpp (86%) rename src/modules/filesystem/{physfs => }/wrap_Filesystem.h (80%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 17cfaa157..c6df49b45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,6 +185,12 @@ set(LOVE_SRC_MODULE_FILESYSTEM_ROOT src/modules/filesystem/File.h src/modules/filesystem/FileData.cpp src/modules/filesystem/FileData.h + src/modules/filesystem/wrap_File.cpp + src/modules/filesystem/wrap_File.h + src/modules/filesystem/wrap_FileData.cpp + src/modules/filesystem/wrap_FileData.h + src/modules/filesystem/wrap_Filesystem.cpp + src/modules/filesystem/wrap_Filesystem.h ) set(LOVE_SRC_MODULE_FILESYSTEM_PHYSFS @@ -192,12 +198,6 @@ set(LOVE_SRC_MODULE_FILESYSTEM_PHYSFS src/modules/filesystem/physfs/File.h src/modules/filesystem/physfs/Filesystem.cpp src/modules/filesystem/physfs/Filesystem.h - src/modules/filesystem/physfs/wrap_File.cpp - src/modules/filesystem/physfs/wrap_File.h - src/modules/filesystem/physfs/wrap_FileData.cpp - src/modules/filesystem/physfs/wrap_FileData.h - src/modules/filesystem/physfs/wrap_Filesystem.cpp - src/modules/filesystem/physfs/wrap_Filesystem.h ) set(LOVE_SRC_MODULE_FILESYSTEM diff --git a/platform/macosx/love-framework.xcodeproj/project.pbxproj b/platform/macosx/love-framework.xcodeproj/project.pbxproj index b6ed48d4e..fe4381420 100644 --- a/platform/macosx/love-framework.xcodeproj/project.pbxproj +++ b/platform/macosx/love-framework.xcodeproj/project.pbxproj @@ -1554,12 +1554,6 @@ 47D46915001F342A3CD23E86 /* File.h */, 6DE3129F3A0B2D9C178118F3 /* Filesystem.cpp */, 219636CF6780074F7871463D /* Filesystem.h */, - 6C367AE309C453C412D91363 /* wrap_File.cpp */, - 52E15B702C40593D3BF431DF /* wrap_File.h */, - 597478A255B82B56488B4717 /* wrap_FileData.cpp */, - 3512460642B046876D687B22 /* wrap_FileData.h */, - 1E827AE8548C52493ED95629 /* wrap_Filesystem.cpp */, - 5DC271240F0119AE16FA1B8E /* wrap_Filesystem.h */, ); path = physfs; sourceTree = ""; @@ -1736,6 +1730,12 @@ 62370A494F9D6E2D570065EB /* FileData.cpp */, 54A13C2209F945671BC27974 /* FileData.h */, 64DD03B45BF6265723662DAF /* physfs */, + 6C367AE309C453C412D91363 /* wrap_File.cpp */, + 52E15B702C40593D3BF431DF /* wrap_File.h */, + 597478A255B82B56488B4717 /* wrap_FileData.cpp */, + 3512460642B046876D687B22 /* wrap_FileData.h */, + 1E827AE8548C52493ED95629 /* wrap_Filesystem.cpp */, + 5DC271240F0119AE16FA1B8E /* wrap_Filesystem.h */, ); path = filesystem; sourceTree = ""; diff --git a/src/common/runtime.h b/src/common/runtime.h index dae24f97c..3b7d4b282 100644 --- a/src/common/runtime.h +++ b/src/common/runtime.h @@ -489,6 +489,20 @@ Type luax_type(lua_State *L, int idx); return luaL_error(L, "%s", lua_tostring(L, -1)); \ } +#define EXCEPT_GUARD_FINALLY(A, B) \ +{ \ + bool should_error = false; \ + try { A } \ + catch (love::Exception &e) \ + { \ + should_error = true; \ + lua_pushstring(L, e.what()); \ + } \ + { B } \ + if (should_error) \ + return luaL_error(L, "%s", lua_tostring(L, -1)); \ +} + } // love #endif // LOVE_RUNTIME_H diff --git a/src/modules/audio/openal/Source.cpp b/src/modules/audio/openal/Source.cpp index 520edb7bb..20bf87fdd 100644 --- a/src/modules/audio/openal/Source.cpp +++ b/src/modules/audio/openal/Source.cpp @@ -658,6 +658,7 @@ int Source::streamAtomic(ALuint buffer, love::sound::Decoder *d) { // Get more sound data. int decoded = d->decode(); + decoded = decoded >= 0 ? decoded : 0; int fmt = getFormat(d->getChannels(), d->getBitDepth()); diff --git a/src/modules/audio/wrap_Audio.cpp b/src/modules/audio/wrap_Audio.cpp index 217c4f98e..3b3c48568 100644 --- a/src/modules/audio/wrap_Audio.cpp +++ b/src/modules/audio/wrap_Audio.cpp @@ -41,10 +41,7 @@ int w_getSourceCount(lua_State *L) int w_newSource(lua_State *L) { - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); - - if (luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) + if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) luax_convobj(L, 1, "sound", "newDecoder"); Source::Type stype = Source::TYPE_STREAM; diff --git a/src/modules/filesystem/physfs/File.cpp b/src/modules/filesystem/physfs/File.cpp index ce2ac50eb..95eafa800 100644 --- a/src/modules/filesystem/physfs/File.cpp +++ b/src/modules/filesystem/physfs/File.cpp @@ -31,11 +31,12 @@ namespace love { namespace filesystem { -namespace physfs -{ extern bool hack_setupWriteDirectory(); +namespace physfs +{ + File::File(const std::string &filename) : filename(filename) , file(0) diff --git a/src/modules/filesystem/physfs/wrap_File.cpp b/src/modules/filesystem/wrap_File.cpp similarity index 98% rename from src/modules/filesystem/physfs/wrap_File.cpp rename to src/modules/filesystem/wrap_File.cpp index d136e4b4d..28213008b 100644 --- a/src/modules/filesystem/physfs/wrap_File.cpp +++ b/src/modules/filesystem/wrap_File.cpp @@ -20,6 +20,8 @@ #include "wrap_File.h" +#include "physfs/Filesystem.h" + #include "common/Data.h" #include "common/Exception.h" #include "common/int.h" @@ -28,8 +30,6 @@ namespace love { namespace filesystem { -namespace physfs -{ int luax_ioError(lua_State *L, const char *fmt, ...) { @@ -242,7 +242,7 @@ int w_File_lines(lua_State *L) return luaL_error(L, "Could not open file."); } - lua_pushcclosure(L, Filesystem::lines_i, 3); + lua_pushcclosure(L, physfs::Filesystem::lines_i, 3); return 1; } @@ -323,6 +323,5 @@ extern "C" int luaopen_file(lua_State *L) return luax_register_type(L, "File", functions); } -} // physfs } // filesystem } // love diff --git a/src/modules/filesystem/physfs/wrap_File.h b/src/modules/filesystem/wrap_File.h similarity index 90% rename from src/modules/filesystem/physfs/wrap_File.h rename to src/modules/filesystem/wrap_File.h index a3d0b964d..d4bd65d74 100644 --- a/src/modules/filesystem/physfs/wrap_File.h +++ b/src/modules/filesystem/wrap_File.h @@ -18,20 +18,17 @@ * 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 +#ifndef LOVE_FILESYSTEM_WRAP_FILE_H +#define LOVE_FILESYSTEM_WRAP_FILE_H // LOVE #include "common/runtime.h" -#include "Filesystem.h" #include "File.h" namespace love { namespace filesystem { -namespace physfs -{ // Does not use lua_error, so it's safe to call in exception handling code. int luax_ioError(lua_State *L, const char *fmt, ...); @@ -53,8 +50,7 @@ int w_File_getBuffer(lua_State *L); int w_File_getMode(lua_State *L); extern "C" int luaopen_file(lua_State *L); -} // physfs } // filesystem } // love -#endif // LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_H +#endif // LOVE_FILESYSTEM_WRAP_FILE_H diff --git a/src/modules/filesystem/physfs/wrap_FileData.cpp b/src/modules/filesystem/wrap_FileData.cpp similarity index 98% rename from src/modules/filesystem/physfs/wrap_FileData.cpp rename to src/modules/filesystem/wrap_FileData.cpp index b50c8123b..3b78c47a5 100644 --- a/src/modules/filesystem/physfs/wrap_FileData.cpp +++ b/src/modules/filesystem/wrap_FileData.cpp @@ -26,8 +26,6 @@ namespace love { namespace filesystem { -namespace physfs -{ FileData *luax_checkfiledata(lua_State *L, int idx) { @@ -66,6 +64,5 @@ extern "C" int luaopen_filedata(lua_State *L) return luax_register_type(L, "FileData", w_FileData_functions); } -} // physfs } // filesystem } // love diff --git a/src/modules/filesystem/physfs/wrap_FileData.h b/src/modules/filesystem/wrap_FileData.h similarity index 85% rename from src/modules/filesystem/physfs/wrap_FileData.h rename to src/modules/filesystem/wrap_FileData.h index 2d46165fb..326387024 100644 --- a/src/modules/filesystem/physfs/wrap_FileData.h +++ b/src/modules/filesystem/wrap_FileData.h @@ -18,28 +18,24 @@ * 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 +#ifndef LOVE_FILESYSTEM_WRAP_FILE_DATA_H +#define LOVE_FILESYSTEM_WRAP_FILE_DATA_H // LOVE #include "common/runtime.h" - -#include "filesystem/FileData.h" +#include "FileData.h" namespace love { namespace filesystem { -namespace physfs -{ FileData *luax_checkfiledata(lua_State *L, int idx); int w_FileData_getFilename(lua_State *L); int w_FileData_getExtension(lua_State *L); extern "C" int luaopen_filedata(lua_State *L); -} // physfs } // filesystem } // love -#endif // LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_DATA_H +#endif // LOVE_FILESYSTEM_WRAP_FILE_DATA_H diff --git a/src/modules/filesystem/physfs/wrap_Filesystem.cpp b/src/modules/filesystem/wrap_Filesystem.cpp similarity index 86% rename from src/modules/filesystem/physfs/wrap_Filesystem.cpp rename to src/modules/filesystem/wrap_Filesystem.cpp index 77845ef12..38321f996 100644 --- a/src/modules/filesystem/physfs/wrap_Filesystem.cpp +++ b/src/modules/filesystem/wrap_Filesystem.cpp @@ -20,6 +20,10 @@ // LOVE #include "wrap_Filesystem.h" +#include "wrap_File.h" +#include "wrap_FileData.h" + +#include "physfs/Filesystem.h" // SDL #include @@ -28,10 +32,8 @@ namespace love { namespace filesystem { -namespace physfs -{ -static Filesystem *instance = 0; +static physfs::Filesystem *instance = 0; bool hack_setupWriteDirectory() { @@ -146,18 +148,73 @@ int w_newFile(lua_State *L) return 1; } +FileData *luax_getFileData(lua_State *L, int idx) +{ + FileData *data = nullptr; + File *file = nullptr; + + if (lua_isstring(L, idx)) + { + const char *filename = luaL_checkstring(L, idx); + file = instance->newFile(filename); + } + else if (luax_istype(L, idx, FILESYSTEM_FILE_T)) + { + file = luax_checkfile(L, idx); + file->retain(); + } + else if (luax_istype(L, idx, FILESYSTEM_FILE_DATA_T)) + { + data = luax_checkfiledata(L, idx); + data->retain(); + } + + if (!data && !file) + { + luaL_argerror(L, idx, "filename, File, or FileData expected"); + return nullptr; // Never reached. + } + + if (file) + { + bool should_error = false; + + // We don't use EXCEPT_GUARD_FINALLY because it returns int. + try + { + data = file->read(); + } + catch (love::Exception &e) + { + should_error = true; + lua_pushstring(L, e.what()); + } + + file->release(); + + if (should_error) + { + luaL_error(L, "%s", lua_tostring(L, -1)); + return nullptr; // Never reached. + } + } + + return data; +} + int w_newFileData(lua_State *L) { // Single argument: treat as filepath or File. if (lua_gettop(L) == 1) { + // We don't use luax_getFileData because we want to use an ioError. if (lua_isstring(L, 1)) luax_convobj(L, 1, "filesystem", "newFile"); // Get FileData from the File. if (luax_istype(L, 1, FILESYSTEM_FILE_T)) { - File *file = luax_checktype(L, 1, "File", FILESYSTEM_FILE_T); + File *file = luax_checkfile(L, 1); FileData *data = 0; try @@ -172,7 +229,7 @@ int w_newFileData(lua_State *L) return 1; } else - return luaL_argerror(L, 1, "string or File expected"); + return luaL_argerror(L, 1, "filename or File expected"); } size_t length = 0; @@ -369,7 +426,7 @@ int w_lines(lua_State *L) else return luaL_argerror(L, 1, "expected filename."); - lua_pushcclosure(L, Filesystem::lines_i, 1); + lua_pushcclosure(L, physfs::Filesystem::lines_i, 1); return 1; } @@ -576,32 +633,32 @@ int extloader(lua_State *L) // List of functions to wrap. static const luaL_Reg functions[] = { - { "init", w_init }, + { "init", w_init }, { "setFused", w_setFused }, { "isFused", w_isFused }, - { "setIdentity", w_setIdentity }, + { "setIdentity", w_setIdentity }, { "getIdentity", w_getIdentity }, - { "setSource", w_setSource }, + { "setSource", w_setSource }, { "getSource", w_getSource }, { "mount", w_mount }, { "unmount", w_unmount }, - { "newFile", w_newFile }, - { "getWorkingDirectory", w_getWorkingDirectory }, - { "getUserDirectory", w_getUserDirectory }, - { "getAppdataDirectory", w_getAppdataDirectory }, - { "getSaveDirectory", w_getSaveDirectory }, + { "newFile", w_newFile }, + { "getWorkingDirectory", w_getWorkingDirectory }, + { "getUserDirectory", w_getUserDirectory }, + { "getAppdataDirectory", w_getAppdataDirectory }, + { "getSaveDirectory", w_getSaveDirectory }, { "getSourceBaseDirectory", w_getSourceBaseDirectory }, - { "exists", w_exists }, - { "isDirectory", w_isDirectory }, - { "isFile", w_isFile }, - { "createDirectory", w_createDirectory }, - { "remove", w_remove }, - { "read", w_read }, - { "write", w_write }, + { "exists", w_exists }, + { "isDirectory", w_isDirectory }, + { "isFile", w_isFile }, + { "createDirectory", w_createDirectory }, + { "remove", w_remove }, + { "read", w_read }, + { "write", w_write }, { "append", w_append }, - { "getDirectoryItems", w_getDirectoryItems }, - { "lines", w_lines }, - { "load", w_load }, + { "getDirectoryItems", w_getDirectoryItems }, + { "lines", w_lines }, + { "load", w_load }, { "getLastModified", w_getLastModified }, { "getSize", w_getSize }, { "newFileData", w_newFileData }, @@ -619,7 +676,7 @@ extern "C" int luaopen_love_filesystem(lua_State *L) { if (instance == 0) { - EXCEPT_GUARD(instance = new Filesystem();) + EXCEPT_GUARD(instance = new physfs::Filesystem();) } else instance->retain(); @@ -638,6 +695,5 @@ extern "C" int luaopen_love_filesystem(lua_State *L) return luax_register_module(L, w); } -} // physfs } // filesystem } // love diff --git a/src/modules/filesystem/physfs/wrap_Filesystem.h b/src/modules/filesystem/wrap_Filesystem.h similarity index 80% rename from src/modules/filesystem/physfs/wrap_Filesystem.h rename to src/modules/filesystem/wrap_Filesystem.h index 711c5eb55..86fdf00dd 100644 --- a/src/modules/filesystem/physfs/wrap_Filesystem.h +++ b/src/modules/filesystem/wrap_Filesystem.h @@ -18,20 +18,26 @@ * 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 +#ifndef LOVE_FILESYSTEM_WRAP_FILESYSTEM_H +#define LOVE_FILESYSTEM_WRAP_FILESYSTEM_H // LOVE -#include "Filesystem.h" -#include "wrap_File.h" -#include "wrap_FileData.h" +#include "common/runtime.h" +#include "FileData.h" namespace love { namespace filesystem { -namespace physfs -{ + +/** + * Gets FileData at the specified index. If the index contains a filepath or + * a File object, the FileData will be created from that. + * Note that this function retains the FileData object (possibly by creating it), + * so a matching release() is required! + * May trigger a Lua error. + **/ +FileData *luax_getFileData(lua_State *L, int idx); bool hack_setupWriteDirectory(); int w_init(lua_State *L); @@ -69,8 +75,7 @@ int loader(lua_State *L); int extloader(lua_State *L); extern "C" LOVE_EXPORT int luaopen_love_filesystem(lua_State *L); -} // physfs } // filesystem } // love -#endif // LOVE_FILESYSTEM_PHYSFS_WRAP_FILESYSTEM_H +#endif // LOVE_FILESYSTEM_WRAP_FILESYSTEM_H diff --git a/src/modules/font/freetype/wrap_Font.cpp b/src/modules/font/freetype/wrap_Font.cpp index 935df7d1c..8be1bc1fd 100644 --- a/src/modules/font/freetype/wrap_Font.cpp +++ b/src/modules/font/freetype/wrap_Font.cpp @@ -25,6 +25,8 @@ #include "font/wrap_GlyphData.h" #include "font/wrap_Rasterizer.h" +#include "filesystem/wrap_Filesystem.h" + #include "TrueTypeRasterizer.h" namespace love @@ -34,31 +36,25 @@ namespace font namespace freetype { -static Font *instance = 0; +static Font *instance = nullptr; int w_newRasterizer(lua_State *L) { - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); + Rasterizer *t = nullptr; - Rasterizer *t = 0; - - EXCEPT_GUARD( - if (luax_istype(L, 1, IMAGE_IMAGE_DATA_T)) - { - love::image::ImageData *d = luax_checktype(L, 1, "ImageData", IMAGE_IMAGE_DATA_T); - const char *g = luaL_checkstring(L, 2); - std::string glyphs(g); - t = instance->newRasterizer(d, glyphs); - } - else if (luax_istype(L, 1, DATA_T)) - { - Data *d = luax_checkdata(L, 1); - int size = luaL_checkint(L, 2); - t = instance->newRasterizer(d, size); - } - ) + if (luax_istype(L, 1, IMAGE_IMAGE_DATA_T)) + { + love::image::ImageData *d = luax_checktype(L, 1, "ImageData", IMAGE_IMAGE_DATA_T); + const char *g = luaL_checkstring(L, 2); + std::string glyphs(g); + EXCEPT_GUARD(t = instance->newRasterizer(d, glyphs);) + } + else if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) + { + love::filesystem::FileData *d = love::filesystem::luax_getFileData(L, 1); + int size = luaL_checkint(L, 2); + EXCEPT_GUARD_FINALLY(t = instance->newRasterizer(d, size);, d->release();) + } luax_pushtype(L, "Rasterizer", FONT_RASTERIZER_T, t); return 1; @@ -67,13 +63,12 @@ int w_newRasterizer(lua_State *L) int w_newGlyphData(lua_State *L) { Rasterizer *r = luax_checkrasterizer(L, 1); - GlyphData *t = 0; + GlyphData *t = nullptr; // newGlyphData accepts a unicode character or a codepoint number. if (lua_type(L, 2) == LUA_TSTRING) { std::string glyph = luax_checkstring(L, 2); - EXCEPT_GUARD(t = instance->newGlyphData(r, glyph);) } else @@ -103,7 +98,7 @@ static const lua_CFunction types[] = extern "C" int luaopen_love_font(lua_State *L) { - if (instance == 0) + if (instance == nullptr) { EXCEPT_GUARD(instance = new Font();) } diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 1814cb2ef..26b272aaa 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -22,7 +22,9 @@ #include "OpenGL.h" #include "graphics/Texture.h" #include "image/ImageData.h" +#include "image/Image.h" #include "font/Rasterizer.h" +#include "filesystem/wrap_Filesystem.h" #include "scripts/graphics.lua.h" #include @@ -161,42 +163,52 @@ int w_newImage(lua_State *L) if (fstr != nullptr && !Image::getConstant(fstr, format)) return luaL_error(L, "Invalid Image format: %s", fstr); - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); + bool releasedata = false; - // Convert to ImageData/CompressedData, if necessary. - if (luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) + // Convert to ImageData / CompressedData, if necessary. + if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) { - // Determine whether to convert to ImageData or CompressedData. - luax_getfunction(L, "image", "isCompressed"); - lua_pushvalue(L, 1); - lua_call(L, 1, 1); + love::image::Image *image = (love::image::Image *) Module::findInstance("love.image."); + if (image == nullptr) + return luaL_error(L, "Cannot load images without the love.image module."); - bool compressed = luax_toboolean(L, -1); - lua_pop(L, 1); + love::filesystem::FileData *fdata = love::filesystem::luax_getFileData(L, 1); - if (compressed) - luax_convobj(L, 1, "image", "newCompressedData"); + if (image->isCompressed(fdata)) + { + EXCEPT_GUARD_FINALLY(cdata = image->newCompressedData(fdata);, fdata->release();) + } else - luax_convobj(L, 1, "image", "newImageData"); - } + { + EXCEPT_GUARD_FINALLY(data = image->newImageData(fdata);, fdata->release();) + } - if (luax_istype(L, 1, IMAGE_COMPRESSED_DATA_T)) + // Lua's GC won't release the image data, so we should do it ourselves. + releasedata = true; + } + else if (luax_istype(L, 1, IMAGE_COMPRESSED_DATA_T)) cdata = luax_checktype(L, 1, "CompressedData", IMAGE_COMPRESSED_DATA_T); else data = luax_checktype(L, 1, "ImageData", IMAGE_IMAGE_DATA_T); if (!data && !cdata) - return luaL_error(L, "Error creating image."); + return luaL_error(L, "Error creating image (could not load data.)"); // Create the image. Image *image = nullptr; - EXCEPT_GUARD( - if (cdata) - image = instance->newImage(cdata, format); - else if (data) - image = instance->newImage(data, format); + EXCEPT_GUARD_FINALLY( + { + if (cdata) + image = instance->newImage(cdata, format); + else if (data) + image = instance->newImage(data, format); + }, + { + if (releasedata && data) + data->release(); + else if (releasedata && cdata) + cdata->release(); + } ) if (image == nullptr) @@ -225,12 +237,8 @@ int w_newQuad(lua_State *L) int w_newFont(lua_State *L) { - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); - // Convert to Rasterizer, if necessary. - if (luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) + if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) { int idxs[] = {1, 2}; luax_convobj(L, idxs, 2, "font", "newRasterizer"); diff --git a/src/modules/graphics/opengl/wrap_Shader.cpp b/src/modules/graphics/opengl/wrap_Shader.cpp index ed3ee1ed5..c48249bb5 100644 --- a/src/modules/graphics/opengl/wrap_Shader.cpp +++ b/src/modules/graphics/opengl/wrap_Shader.cpp @@ -232,22 +232,10 @@ int w_Shader_sendMatrix(lua_State *L) lua_pop(L, 1 + dimension); } - bool should_error = false; - - try - { - shader->sendMatrix(name, dimension, values, count); - } - catch(love::Exception &e) - { - should_error = true; - lua_pushstring(L, e.what()); - } - - delete[] values; - - if (should_error) - return luaL_error(L, "%s", lua_tostring(L, -1)); + EXCEPT_GUARD_FINALLY( + { shader->sendMatrix(name, dimension, values, count); }, + { delete[] values; } + ) return 0; } diff --git a/src/modules/image/wrap_Image.cpp b/src/modules/image/wrap_Image.cpp index 93896f852..dec04c8f5 100644 --- a/src/modules/image/wrap_Image.cpp +++ b/src/modules/image/wrap_Image.cpp @@ -25,12 +25,14 @@ #include "magpie/Image.h" +#include "filesystem/wrap_Filesystem.h" + namespace love { namespace image { -static Image *instance = 0; +static Image *instance = nullptr; int w_newImageData(lua_State *L) { @@ -42,7 +44,7 @@ int w_newImageData(lua_State *L) if (w <= 0 || h <= 0) return luaL_error(L, "Invalid image size."); - ImageData *t = 0; + ImageData *t = nullptr; EXCEPT_GUARD(t = instance->newImageData(w, h);) luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t); @@ -50,15 +52,10 @@ int w_newImageData(lua_State *L) } // Case 2: File(Data). + love::filesystem::FileData *data = love::filesystem::luax_getFileData(L, 1); - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); - - love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); - - ImageData *t = 0; - EXCEPT_GUARD(t = instance->newImageData(data);) + ImageData *t = nullptr; + EXCEPT_GUARD_FINALLY(t = instance->newImageData(data);, data->release();) luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t); return 1; @@ -66,14 +63,10 @@ int w_newImageData(lua_State *L) int w_newCompressedData(lua_State *L) { - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); + love::filesystem::FileData *data = love::filesystem::luax_getFileData(L, 1); - love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); - - CompressedData *t = 0; - EXCEPT_GUARD(t = instance->newCompressedData(data);) + CompressedData *t = nullptr; + EXCEPT_GUARD_FINALLY(t = instance->newCompressedData(data);, data->release();) luax_pushtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, t); return 1; @@ -81,14 +74,9 @@ int w_newCompressedData(lua_State *L) int w_isCompressed(lua_State *L) { - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); - - love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); - - bool compressed = false; - EXCEPT_GUARD(compressed = instance->isCompressed(data);) + love::filesystem::FileData *data = love::filesystem::luax_getFileData(L, 1); + bool compressed = instance->isCompressed(data); + data->release(); luax_pushboolean(L, compressed); return 1; @@ -112,7 +100,7 @@ static const lua_CFunction types[] = extern "C" int luaopen_love_image(lua_State *L) { - if (instance == 0) + if (instance == nullptr) { EXCEPT_GUARD(instance = new love::image::magpie::Image();) } diff --git a/src/modules/sound/wrap_Sound.cpp b/src/modules/sound/wrap_Sound.cpp index d91641e00..d12a42d6c 100644 --- a/src/modules/sound/wrap_Sound.cpp +++ b/src/modules/sound/wrap_Sound.cpp @@ -20,6 +20,8 @@ #include "wrap_Sound.h" +#include "filesystem/wrap_Filesystem.h" + // Implementations. #include "lullaby/Sound.h" @@ -62,18 +64,13 @@ int w_newSoundData(lua_State *L) int w_newDecoder(lua_State *L) { - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); - - love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); - + love::filesystem::FileData *data = love::filesystem::luax_getFileData(L, 1); int bufferSize = luaL_optint(L, 2, Decoder::DEFAULT_BUFFER_SIZE); - Decoder *t = 0; - EXCEPT_GUARD(t = instance->newDecoder(data, bufferSize);) + Decoder *t = nullptr; + EXCEPT_GUARD_FINALLY(t = instance->newDecoder(data, bufferSize);, data->release();) - if (t == 0) + if (t == nullptr) return luaL_error(L, "Extension \"%s\" not supported.", data->getExtension().c_str()); luax_pushtype(L, "Decoder", SOUND_DECODER_T, t);