diff --git a/src/modules/filesystem/physfs/File.cpp b/src/modules/filesystem/physfs/File.cpp index 5d7670b73..0b2f47a34 100644 --- a/src/modules/filesystem/physfs/File.cpp +++ b/src/modules/filesystem/physfs/File.cpp @@ -151,8 +151,6 @@ int64 File::read(void *dst, int64 size) int64 max = (int64)PHYSFS_fileLength(file); size = (size == ALL) ? max : size; size = (size > max) ? max : size; - // Sadly, we'll have to clamp to 32 bits here - size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size; if (size < 0) throw love::Exception("Invalid read size."); @@ -160,6 +158,8 @@ int64 File::read(void *dst, int64 size) #ifdef LOVE_USE_PHYSFS_2_1 int64 read = PHYSFS_readBytes(file, dst, (PHYSFS_uint64) size); #else + // 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, (PHYSFS_uint32) size); #endif @@ -171,9 +171,6 @@ bool File::write(const void *data, int64 size) if (!file || (mode != MODE_WRITE && mode != MODE_APPEND)) throw love::Exception("File is not opened for writing."); - // Another clamp, for the time being. - size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size; - if (size < 0) throw love::Exception("Invalid write size."); @@ -181,6 +178,8 @@ bool File::write(const void *data, int64 size) #ifdef LOVE_USE_PHYSFS_2_1 int64 written = PHYSFS_writeBytes(file, data, (PHYSFS_uint64) size); #else + // Another clamp, for the time being. + size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size; int64 written = (int64) PHYSFS_write(file, data, 1, (PHYSFS_uint32) size); #endif diff --git a/src/modules/filesystem/wrap_Filesystem.cpp b/src/modules/filesystem/wrap_Filesystem.cpp index f6d03870c..319bc69e8 100644 --- a/src/modules/filesystem/wrap_Filesystem.cpp +++ b/src/modules/filesystem/wrap_Filesystem.cpp @@ -634,6 +634,22 @@ int w_setCRequirePath(lua_State *L) return 0; } +static void replaceAll(std::string &str, const std::string &substr, const std::string &replacement) +{ + std::vector locations; + size_t pos = 0; + size_t sublen = substr.length(); + + while ((pos = str.find(substr, pos)) != std::string::npos) + { + locations.push_back(pos); + pos += sublen; + } + + for (int i = (int) locations.size() - 1; i >= 0; i--) + str.replace(locations[i], sublen, replacement); +} + int loader(lua_State *L) { std::string modulename = luax_tostring(L, 1); @@ -647,9 +663,7 @@ int loader(lua_State *L) auto *inst = instance(); for (std::string element : inst->getRequirePath()) { - size_t pos = 0; - while ((pos = element.find('?', pos)) != std::string::npos) - element.replace(pos, 1, modulename); + replaceAll(element, "?", modulename); if (inst->isFile(element.c_str())) { @@ -665,14 +679,16 @@ int loader(lua_State *L) return 1; } -inline const char *library_extension() +static const char *library_extensions[] = { #ifdef LOVE_WINDOWS - return ".dll"; + ".dll" +#elif defined(LOVE_MACOSX) || defined(LOVE_IOS) + ".dylib", ".so" #else - return ".so"; + ".so" #endif -} +}; int extloader(lua_State *L) { @@ -694,25 +710,31 @@ int extloader(lua_State *L) void *handle = nullptr; auto *inst = instance(); - for (std::string element : inst->getCRequirePath()) + + for (const std::string &el : inst->getCRequirePath()) { - // Replace ?? with the filename and extension - size_t pos = element.find("??"); - if (pos != std::string::npos) - element.replace(pos, 2, tokenized_name + library_extension()); - // Or ? with just the filename - pos = element.find('?'); - if (pos != std::string::npos) - element.replace(pos, 1, tokenized_name); + for (const char *ext : library_extensions) + { + std::string element = el; - if (!inst->isFile(element.c_str())) - continue; + // Replace ?? with the filename and extension + replaceAll(element, "??", tokenized_name + ext); - // Now resolve the full path, as we're bypassing physfs for the next part. - element = inst->getRealDirectory(element.c_str()) + LOVE_PATH_SEPARATOR + element; + // And ? with just the filename + replaceAll(element, "?", tokenized_name); + + if (!inst->isFile(element.c_str())) + continue; + + // Now resolve the full path, as we're bypassing physfs for the next part. + std::string filepath = inst->getRealDirectory(element.c_str()) + LOVE_PATH_SEPARATOR + element; + + handle = SDL_LoadObject(filepath.c_str()); + // Can fail, for instance if it turned out the source was a zip + if (handle) + break; + } - handle = SDL_LoadObject(element.c_str()); - // Can fail, for instance if it turned out the source was a zip if (handle) break; }