Merge pull request #7492 from IntelOrca/refactor/ziparchive

Improve IZipArchive so that it is more C++
This commit is contained in:
Ted John 2018-05-07 17:21:20 +01:00 committed by GitHub
commit 0df569f0e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 190 additions and 216 deletions

View File

@ -1,4 +1,4 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
#pragma region Copyright (c) 2014-2018 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
@ -21,6 +21,7 @@
#include <sys/stat.h>
#endif
#include <fstream>
#include "File.h"
#include "FileStream.hpp"
#include "String.hpp"
@ -50,12 +51,23 @@ namespace File
return platform_file_move(srcPath.c_str(), dstPath.c_str());
}
void * ReadAllBytes(const std::string &path, size_t * length)
std::vector<uint8> ReadAllBytes(const std::string_view& path)
{
void * result = nullptr;
std::vector<uint8> result;
FileStream fs = FileStream(path, FILE_MODE_OPEN);
uint64 fsize = fs.GetLength();
#if defined(_WIN32) && !defined(__MINGW32__)
auto pathW = String::ToUtf16(path.data());
std::ifstream fs(pathW, std::ios::in | std::ios::binary);
#else
std::ifstream fs(path.data(), std::ios::in | std::ios::binary);
#endif
if (!fs.is_open())
{
throw IOException("Unable to open " + std::string(path.data()));
}
fs.seekg(0, std::ios::end);
auto fsize = (size_t)fs.tellg();
if (fsize > SIZE_MAX)
{
std::string message = String::StdFormat("'%s' exceeds maximum length of %lld bytes.", SIZE_MAX);
@ -63,9 +75,11 @@ namespace File
}
else
{
result = fs.ReadArray<uint8>((size_t)fsize);
result.resize(fsize);
fs.seekg(0);
fs.read((char *)result.data(), result.size());
fs.exceptions(fs.failbit);
}
*length = (size_t)fsize;
return result;
}
@ -78,12 +92,11 @@ namespace File
std::vector<std::string> ReadAllLines(const std::string &path)
{
std::vector<std::string> lines;
size_t length;
char * data = (char *)ReadAllBytes(path, &length);
char * lineStart = data;
char * ch = data;
auto data = ReadAllBytes(path);
auto lineStart = (const char *)data.data();
auto ch = lineStart;
char lastC = 0;
for (size_t i = 0; i < length; i++)
for (size_t i = 0; i < data.size(); i++)
{
char c = *ch;
if (c == '\n' && lastC == '\r')
@ -102,8 +115,6 @@ namespace File
// Last line
lines.emplace_back(lineStart, ch - lineStart);
Memory::Free(data);
return lines;
}
@ -134,19 +145,6 @@ namespace File
}
} // namespace File
bool readentirefile(const utf8 * path, void * * outBuffer, size_t * outLength)
{
try
{
*outBuffer = File::ReadAllBytes(String::ToStd(path), outLength);
return true;
}
catch (const std::exception &)
{
return false;
}
}
bool writeentirefile(const utf8 * path, const void * buffer, size_t length)
{
try

View File

@ -17,6 +17,7 @@
#pragma once
#include <string>
#include <string_view>
#include <vector>
#include "../common.h"
@ -26,7 +27,7 @@ namespace File
bool Copy(const std::string &srcPath, const std::string &dstPath, bool overwrite);
bool Delete(const std::string &path);
bool Move(const std::string &srcPath, const std::string &dstPath);
void * ReadAllBytes(const std::string &path, size_t * length);
std::vector<uint8> ReadAllBytes(const std::string_view& path);
void WriteAllBytes(const std::string &path, const void * buffer, size_t length);
std::vector<std::string> ReadAllLines(const std::string &path);
uint64 GetLastModified(const std::string &path);

View File

@ -1,4 +1,4 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
#pragma region Copyright (c) 2014-2018 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
@ -17,26 +17,26 @@
#ifndef __ANDROID__
#include <zip.h>
#include "IStream.hpp"
#include "MemoryStream.h"
#include "Zip.h"
class ZipArchive final : public IZipArchive
{
private:
zip_t * _zip;
ZIP_ACCESS _access;
zip_t * _zip;
ZIP_ACCESS _access;
std::vector<std::vector<uint8>> _writeBuffers;
public:
ZipArchive(const utf8 * path, ZIP_ACCESS access)
ZipArchive(const std::string_view& path, ZIP_ACCESS access)
{
sint32 zipOpenMode = ZIP_RDONLY;
if (access == ZIP_ACCESS_WRITE)
auto zipOpenMode = ZIP_RDONLY;
if (access == ZIP_ACCESS::WRITE)
{
zipOpenMode = ZIP_CREATE;
}
sint32 error;
_zip = zip_open(path, zipOpenMode, &error);
_zip = zip_open(path.data(), zipOpenMode, &error);
if (_zip == nullptr)
{
throw IOException("Unable to open zip file.");
@ -55,10 +55,15 @@ public:
return zip_get_num_files(_zip);
}
const utf8 * GetFileName(size_t index) const override
std::string GetFileName(size_t index) const override
{
const utf8 * name = zip_get_name(_zip, index, ZIP_FL_ENC_GUESS);
return name;
std::string result;
auto name = zip_get_name(_zip, index, ZIP_FL_ENC_GUESS);
if (name != nullptr)
{
result = name;
}
return result;
}
uint64 GetFileSize(size_t index) const override
@ -74,51 +79,41 @@ public:
}
}
void * GetFileData(const utf8 * path, size_t * outSize) const override
std::vector<uint8> GetFileData(const std::string_view& path) const override
{
void * data = nullptr;
size_t index = (size_t)zip_name_locate(_zip, path, 0);
uint64 dataSize = GetFileSize(index);
std::vector<uint8> result;
auto index = (size_t)zip_name_locate(_zip, path.data(), 0);
auto dataSize = GetFileSize(index);
if (dataSize > 0 && dataSize < SIZE_MAX)
{
zip_file_t * zipFile = zip_fopen(_zip, path, 0);
auto zipFile = zip_fopen(_zip, path.data(), 0);
if (zipFile != nullptr)
{
data = Memory::Allocate<void>((size_t)dataSize);
uint64 readBytes = zip_fread(zipFile, data, dataSize);
result.resize((size_t)dataSize);
uint64 readBytes = zip_fread(zipFile, result.data(), dataSize);
if (readBytes != dataSize)
{
SafeFree(data);
dataSize = 0;
result.clear();
result.shrink_to_fit();
}
zip_fclose(zipFile);
}
}
if (outSize != nullptr) *outSize = (size_t)dataSize;
return data;
return result;
}
IStream * GetFileStream(const utf8 * path) const override
void SetFileData(const std::string_view& path, std::vector<uint8>&& data) override
{
IStream * stream = nullptr;
size_t dataSize;
void * data = GetFileData(path, &dataSize);
if (data != nullptr)
{
stream = new MemoryStream(data, dataSize, MEMORY_ACCESS::READ | MEMORY_ACCESS::OWNER);
}
return stream;
}
// Push buffer to an internal list as libzip requires access to it until the zip
// handle is closed.
_writeBuffers.push_back(std::move(data));
const auto& writeBuffer = *_writeBuffers.rbegin();
void SetFileData(const utf8 * path, void * data, size_t dataSize) override
{
zip_source_t * source = zip_source_buffer(_zip, data, dataSize, 0);
sint64 index = zip_name_locate(_zip, path, 0);
auto source = zip_source_buffer(_zip, writeBuffer.data(), writeBuffer.size(), 0);
auto index = zip_name_locate(_zip, path.data(), 0);
if (index == -1)
{
zip_add(_zip, path, source);
zip_add(_zip, path.data(), source);
}
else
{
@ -126,34 +121,34 @@ public:
}
}
void DeleteFile(const utf8 * path) override
void DeleteFile(const std::string_view& path) override
{
uint64 index = zip_name_locate(_zip, path, 0);
auto index = zip_name_locate(_zip, path.data(), 0);
zip_delete(_zip, index);
}
void RenameFile(const utf8 * path, const utf8 * newPath) override
void RenameFile(const std::string_view& path, const std::string_view& newPath) override
{
uint64 index = zip_name_locate(_zip, path, 0);
zip_file_rename(_zip, index, newPath, ZIP_FL_ENC_GUESS);
auto index = zip_name_locate(_zip, path.data(), 0);
zip_file_rename(_zip, index, newPath.data(), ZIP_FL_ENC_GUESS);
}
};
namespace Zip
{
IZipArchive * Open(const utf8 * path, ZIP_ACCESS access)
std::unique_ptr<IZipArchive> Open(const std::string_view& path, ZIP_ACCESS access)
{
return new ZipArchive(path, access);
return std::make_unique<ZipArchive>(path, access);
}
IZipArchive * TryOpen(const utf8 * path, ZIP_ACCESS access)
std::unique_ptr<IZipArchive> TryOpen(const std::string_view& path, ZIP_ACCESS access)
{
IZipArchive * result = nullptr;
std::unique_ptr<IZipArchive> result;
try
{
result = new ZipArchive(path, access);
result = std::make_unique<ZipArchive>(path, access);
}
catch (const std::exception &)
catch (const std::exception&)
{
}
return result;

View File

@ -1,4 +1,4 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
#pragma region Copyright (c) 2014-2018 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
@ -16,10 +16,11 @@
#pragma once
#include <memory>
#include <string_view>
#include <vector>
#include "../common.h"
interface IStream;
/**
* Represents a zip file.
*/
@ -27,33 +28,30 @@ interface IZipArchive
{
virtual ~IZipArchive() { }
virtual size_t GetNumFiles() const abstract;
virtual const utf8 * GetFileName(size_t index) const abstract;
virtual uint64 GetFileSize(size_t index) const abstract;
virtual void * GetFileData(const utf8 * path, size_t * outSize) const abstract;
virtual IStream * GetFileStream(const utf8 * path) const abstract;
virtual size_t GetNumFiles() const abstract;
virtual std::string GetFileName(size_t index) const abstract;
virtual uint64 GetFileSize(size_t index) const abstract;
virtual std::vector<uint8> GetFileData(const std::string_view& path) const abstract;
/**
* Creates or overwrites a file within the zip archive to the given data buffer.
* @param path The path of the file within the zip.
* @param data The data to write, this buffer must not be mutated or disposed until
* the zip archive has been disposed.
* @param dataSize The size of the data in bytes.
* @param data The data to write.
*/
virtual void SetFileData(const utf8 * path, void * data, size_t dataSize) abstract;
virtual void SetFileData(const std::string_view& path, std::vector<uint8>&& data) abstract;
virtual void DeleteFile(const utf8 * path) abstract;
virtual void RenameFile(const utf8 * path, const utf8 * newPath) abstract;
virtual void DeleteFile(const std::string_view& path) abstract;
virtual void RenameFile(const std::string_view& path, const std::string_view& newPath) abstract;
};
enum ZIP_ACCESS
enum class ZIP_ACCESS
{
ZIP_ACCESS_READ,
ZIP_ACCESS_WRITE,
READ,
WRITE,
};
namespace Zip
{
IZipArchive * Open(const utf8 * path, ZIP_ACCESS zipAccess);
IZipArchive * TryOpen(const utf8 * path, ZIP_ACCESS zipAccess);
std::unique_ptr<IZipArchive> Open(const std::string_view& path, ZIP_ACCESS zipAccess);
std::unique_ptr<IZipArchive> TryOpen(const std::string_view& path, ZIP_ACCESS zipAccess);
}

View File

@ -20,30 +20,31 @@
#include <jni.h>
#include "IStream.hpp"
#include "Zip.h"
#include "MemoryStream.h"
class ZipArchive final : public IZipArchive {
class ZipArchive final : public IZipArchive
{
private:
jobject _zip;
public:
ZipArchive(const utf8 *path, ZIP_ACCESS access) {
ZipArchive(const std::string_view& path, ZIP_ACCESS access)
{
// retrieve the JNI environment.
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
jclass jniClass = env->FindClass("website/openrct2/ZipArchive");
jmethodID constructor = env->GetMethodID(jniClass, "<init>", "(Ljava/lang/String;)V");
jstring jniPath = env->NewStringUTF(path);
jstring jniPath = env->NewStringUTF(path.data());
// TODO: Catch exceptions. Should probably be done on Java side, and just return null from a static method
jobject zip = env->NewObject(jniClass, constructor, jniPath);
_zip = env->NewGlobalRef(zip);
}
~ZipArchive() override {
~ZipArchive() override
{
// retrieve the JNI environment.
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
@ -55,7 +56,8 @@ public:
env->DeleteGlobalRef(_zip);
}
size_t GetNumFiles() const override {
size_t GetNumFiles() const override
{
// retrieve the JNI environment.
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
@ -65,7 +67,8 @@ public:
return (size_t) env->CallIntMethod(_zip, fileCountMethod);
}
const utf8 *GetFileName(size_t index) const override {
std::string GetFileName(size_t index) const override
{
// retrieve the JNI environment.
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
@ -86,8 +89,8 @@ public:
return string;
}
uint64 GetFileSize(size_t index) const override {
uint64 GetFileSize(size_t index) const override
{
// retrieve the JNI environment.
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
@ -97,58 +100,57 @@ public:
return (size_t) env->CallLongMethod(_zip, fileSizeMethod, (jint) index);
}
void *GetFileData(const utf8 *path, size_t *outSize) const override {
std::vector<uint8> GetFileData(const std::string_view& path) const override
{
// retrieve the JNI environment.
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
jclass zipClass = env->GetObjectClass(_zip);
jstring javaPath = env->NewStringUTF(path);
jstring javaPath = env->NewStringUTF(path.data());
jmethodID indexMethod = env->GetMethodID(zipClass, "getFileIndex", "(Ljava/lang/String;)I");
jint index = env->CallIntMethod(_zip, indexMethod, javaPath);
jmethodID fileMethod = env->GetMethodID(zipClass, "getFile", "(I)J");
jlong ptr = env->CallLongMethod(_zip, fileMethod, index);
*outSize = this->GetFileSize(index);
return reinterpret_cast<void *>(ptr);
auto dataPtr = reinterpret_cast<uint8 *>(ptr);
auto dataSize = this->GetFileSize(index);
return std::vector<uint8>(dataPtr, dataPtr + dataSize);
}
IStream *GetFileStream(const utf8 *path) const override {
IStream * stream = nullptr;
size_t dataSize;
void * data = GetFileData(path, &dataSize);
if (data != nullptr)
{
stream = new MemoryStream(data, dataSize, MEMORY_ACCESS::READ | MEMORY_ACCESS::OWNER);
}
return stream;
}
void SetFileData(const utf8 *path, void *data, size_t dataSize) override {
void void SetFileData(const std::string_view& path, std::vector<uint8>&& data) override
{
STUB();
}
void DeleteFile(const utf8 *path) override {
void DeleteFile(const std::string_view&) override
{
STUB();
}
void RenameFile(const utf8 *path, const utf8 *newPath) override {
void RenameFile(const std::string_view&, const std::string_view&) override
{
STUB();
}
};
namespace Zip {
IZipArchive *Open(const utf8 *path, ZIP_ACCESS access) {
namespace Zip
{
std::unique_ptr<IZipArchive> Open(const std::string_view& path, ZIP_ACCESS access)
{
return new ZipArchive(path, access);
}
IZipArchive *TryOpen(const utf8 *path, ZIP_ACCESS access) {
IZipArchive *result = nullptr;
try {
std::unique_ptr<IZipArchive> TryOpen(const std::string_view path, ZIP_ACCESS access)
{
std::unique_ptr<IZipArchive> result;
try
{
result = new ZipArchive(path, access);
}
catch (const std::exception &) {
catch (const std::exception&)
{
}
return result;
}

View File

@ -1,4 +1,4 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
#pragma region Copyright (c) 2014-2018 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
@ -16,6 +16,7 @@
#include "../audio/audio.h"
#include "../Cheats.h"
#include "../core/File.h"
#include "../core/Math.hpp"
#include "../core/String.hpp"
#include "../core/Util.hpp"
@ -90,21 +91,18 @@ rct_track_td6 * track_design_open(const utf8 * path)
{
log_verbose("track_design_open(\"%s\")", path);
uint8 * buffer;
size_t bufferLength;
if (readentirefile(path, (void **) &buffer, &bufferLength))
try
{
if (!sawyercoding_validate_track_checksum(buffer, bufferLength))
auto buffer = File::ReadAllBytes(path);
if (!sawyercoding_validate_track_checksum(buffer.data(), buffer.size()))
{
log_error("Track checksum failed. %s", path);
free(buffer);
return nullptr;
}
// Decode the track data
uint8 * decoded = (uint8 *) malloc(0x10000);
size_t decodedLength = sawyercoding_decode_td6(buffer, decoded, bufferLength);
free(buffer);
size_t decodedLength = sawyercoding_decode_td6(buffer.data(), decoded, buffer.size());
decoded = (uint8 *) realloc(decoded, decodedLength);
if (decoded == nullptr)
{
@ -122,6 +120,10 @@ rct_track_td6 * track_design_open(const utf8 * path)
}
}
}
catch (const std::exception& e)
{
log_error("Unable to load track design: %s", e.what());
}
return nullptr;
}

View File

@ -492,17 +492,15 @@ private:
auto directory = Path::GetDirectory(dstPath);
platform_ensure_directory_exists(directory.c_str());
size_t length;
auto mpdat = (uint8 *)(File::ReadAllBytes(srcPath, &length));
auto mpdat = File::ReadAllBytes(srcPath);
// Rotate each byte of mp.dat left by 4 bits to convert
for (size_t i = 0; i < length; i++)
for (size_t i = 0; i < mpdat.size(); i++)
{
mpdat[i] = rol8(mpdat[i], 4);
}
File::WriteAllBytes(dstPath, mpdat, length);
Memory::FreeArray(mpdat, length);
File::WriteAllBytes(dstPath, mpdat.data(), mpdat.size());
}
void AddScenario(const scenario_index_entry &entry)

View File

@ -14,6 +14,7 @@
*****************************************************************************/
#pragma endregion
#include <memory>
#include <vector>
#include "../common.h"
#include "../core/Collections.hpp"
@ -39,8 +40,8 @@ static std::vector<utf8 *> GetSaves(const utf8 * path);
static std::vector<utf8 *> GetSaves(IZipArchive * zip);
static std::vector<TitleCommand> LegacyScriptRead(utf8 * script, size_t scriptLength, std::vector<utf8 *> saves);
static void LegacyScriptGetLine(IStream * stream, char * parts);
static void * ReadScriptFile(const utf8 * path, size_t * outSize);
static utf8 * LegacyScriptWrite(TitleSequence * seq);
static std::vector<uint8> ReadScriptFile(const utf8 * path);
static std::string LegacyScriptWrite(TitleSequence * seq);
TitleSequence * CreateTitleSequence()
{
@ -51,8 +52,7 @@ TitleSequence * CreateTitleSequence()
TitleSequence * LoadTitleSequence(const utf8 * path)
{
size_t scriptLength;
utf8 * script;
std::vector<uint8> script;
std::vector<utf8 *> saves;
bool isZip;
@ -61,33 +61,30 @@ TitleSequence * LoadTitleSequence(const utf8 * path)
const utf8 * ext = Path::GetExtension(path);
if (String::Equals(ext, TITLE_SEQUENCE_EXTENSION))
{
IZipArchive * zip = Zip::TryOpen(path, ZIP_ACCESS_READ);
auto zip = std::unique_ptr<IZipArchive>(Zip::TryOpen(path, ZIP_ACCESS::READ));
if (zip == nullptr)
{
Console::Error::WriteLine("Unable to open '%s'", path);
return nullptr;
}
script = (utf8 *)zip->GetFileData("script.txt", &scriptLength);
if (script == nullptr)
script = zip->GetFileData("script.txt");
if (script.empty())
{
Console::Error::WriteLine("Unable to open script.txt in '%s'", path);
delete zip;
return nullptr;
}
saves = GetSaves(zip);
saves = GetSaves(zip.get());
isZip = true;
delete zip;
}
else
{
utf8 scriptPath[MAX_PATH];
String::Set(scriptPath, sizeof(scriptPath), path);
Path::Append(scriptPath, sizeof(scriptPath), "script.txt");
script = (utf8 *)ReadScriptFile(scriptPath, &scriptLength);
if (script == nullptr)
script = ReadScriptFile(scriptPath);
if (script.empty())
{
Console::Error::WriteLine("Unable to open '%s'", scriptPath);
return nullptr;
@ -97,8 +94,7 @@ TitleSequence * LoadTitleSequence(const utf8 * path)
isZip = false;
}
std::vector<TitleCommand> commands = LegacyScriptRead(script, scriptLength, saves);
Memory::Free(script);
auto commands = LegacyScriptRead((utf8 *)script.data(), script.size(), saves);
TitleSequence * seq = CreateTitleSequence();
seq->Name = Path::GetFileNameWithoutExtension(path);
@ -135,13 +131,17 @@ TitleSequenceParkHandle * TitleSequenceGetParkHandle(TitleSequence * seq, size_t
const utf8 * filename = seq->Saves[index];
if (seq->IsZip)
{
IZipArchive * zip = Zip::TryOpen(seq->Path, ZIP_ACCESS_READ);
auto zip = std::unique_ptr<IZipArchive>(Zip::TryOpen(seq->Path, ZIP_ACCESS::READ));
if (zip != nullptr)
{
auto data = zip->GetFileData(filename);
auto dataForMs = Memory::Allocate<uint8>(data.size());
std::copy_n(data.data(), data.size(), dataForMs);
auto ms = new MemoryStream(dataForMs, data.size(), MEMORY_ACCESS::READ | MEMORY_ACCESS::OWNER);
handle = Memory::Allocate<TitleSequenceParkHandle>();
handle->Stream = zip->GetFileStream(filename);
handle->Stream = ms;
handle->HintPath = String::Duplicate(filename);
delete zip;
} else {
Console::Error::WriteLine("Failed to open zipped path '%s' from zip '%s'", filename, seq->Path);
}
@ -185,34 +185,26 @@ void TitleSequenceCloseParkHandle(TitleSequenceParkHandle * handle)
bool TitleSequenceSave(TitleSequence * seq)
{
bool success = false;
utf8 * script = LegacyScriptWrite(seq);
if (seq->IsZip)
try
{
IZipArchive * zip = Zip::TryOpen(seq->Path, ZIP_ACCESS_WRITE);
zip->SetFileData("script.txt", script, String::SizeOf(script));
delete zip;
success = true;
auto script = LegacyScriptWrite(seq);
if (seq->IsZip)
{
auto fdata = std::vector<uint8>(script.begin(), script.end());
auto zip = Zip::Open(seq->Path, ZIP_ACCESS::WRITE);
zip->SetFileData("script.txt", std::move(fdata));
}
else
{
auto scriptPath = Path::Combine(seq->Path, "script.txt");
File::WriteAllBytes(scriptPath, script.data(), script.size());
}
return true;
}
else
catch (const std::exception &)
{
utf8 scriptPath[MAX_PATH];
String::Set(scriptPath, sizeof(scriptPath), seq->Path);
Path::Append(scriptPath, sizeof(scriptPath), "script.txt");
try
{
auto fs = FileStream(scriptPath, FILE_MODE_WRITE);
fs.Write(script, String::SizeOf(script));
success = true;
}
catch (const std::exception &)
{
}
return false;
}
Memory::Free(script);
return success;
}
bool TitleSequenceAddPark(TitleSequence * seq, const utf8 * path, const utf8 * name)
@ -240,18 +232,14 @@ bool TitleSequenceAddPark(TitleSequence * seq, const utf8 * path, const utf8 * n
{
try
{
size_t fsize;
void * fdata = File::ReadAllBytes(path, &fsize);
IZipArchive * zip = Zip::TryOpen(seq->Path, ZIP_ACCESS_WRITE);
auto fdata = File::ReadAllBytes(path);
auto zip = Zip::TryOpen(seq->Path, ZIP_ACCESS::WRITE);
if (zip == nullptr)
{
Console::Error::WriteLine("Unable to open '%s'", seq->Path);
return false;
}
zip->SetFileData(name, fdata, fsize);
delete zip;
Memory::Free(fdata);
zip->SetFileData(name, std::move(fdata));
}
catch (const std::exception &ex)
{
@ -280,14 +268,13 @@ bool TitleSequenceRenamePark(TitleSequence * seq, size_t index, const utf8 * nam
utf8 * oldRelativePath = seq->Saves[index];
if (seq->IsZip)
{
IZipArchive * zip = Zip::TryOpen(seq->Path, ZIP_ACCESS_WRITE);
auto zip = Zip::TryOpen(seq->Path, ZIP_ACCESS::WRITE);
if (zip == nullptr)
{
Console::Error::WriteLine("Unable to open '%s'", seq->Path);
return false;
}
zip->RenameFile(oldRelativePath, name);
delete zip;
}
else
{
@ -317,14 +304,13 @@ bool TitleSequenceRemovePark(TitleSequence * seq, size_t index)
utf8 * relativePath = seq->Saves[index];
if (seq->IsZip)
{
IZipArchive * zip = Zip::TryOpen(seq->Path, ZIP_ACCESS_WRITE);
auto zip = Zip::TryOpen(seq->Path, ZIP_ACCESS::WRITE);
if (zip == nullptr)
{
Console::Error::WriteLine("Unable to open '%s'", seq->Path);
return false;
}
zip->DeleteFile(relativePath);
delete zip;
}
else
{
@ -391,8 +377,8 @@ static std::vector<utf8 *> GetSaves(IZipArchive * zip)
size_t numFiles = zip->GetNumFiles();
for (size_t i = 0; i < numFiles; i++)
{
const utf8 * name = zip->GetFileName(i);
const utf8 * ext = Path::GetExtension(name);
auto name = zip->GetFileName(i);
auto ext = Path::GetExtension(name);
if (String::Equals(ext, ".sv6", true) ||
String::Equals(ext, ".sc6", true))
{
@ -566,29 +552,25 @@ static void LegacyScriptGetLine(IStream * stream, char * parts)
}
}
static void * ReadScriptFile(const utf8 * path, size_t * outSize)
static std::vector<uint8> ReadScriptFile(const utf8 * path)
{
void * buffer = nullptr;
size_t size = 0;
std::vector<uint8> result;
try
{
auto fs = FileStream(path, FILE_MODE_OPEN);
size = (size_t)fs.GetLength();
buffer = Memory::Allocate<void>(size);
fs.Read(buffer, size);
auto size = (size_t)fs.GetLength();
result.resize(size);
fs.Read(result.data(), size);
}
catch (const std::exception &)
{
Memory::Free(buffer);
buffer = nullptr;
size = 0;
result.clear();
result.shrink_to_fit();
}
*outSize = size;
return buffer;
return result;
}
static utf8 * LegacyScriptWrite(TitleSequence * seq)
static std::string LegacyScriptWrite(TitleSequence * seq)
{
utf8 buffer[128];
auto sb = StringBuilder(128);
@ -663,8 +645,7 @@ static utf8 * LegacyScriptWrite(TitleSequence * seq)
sb.Append("\n");
}
utf8 * result = sb.StealString();
return result;
return sb.GetBuffer();
}
bool TitleSequenceIsLoadCommand(const TitleCommand * command)

View File

@ -34,7 +34,6 @@ void path_set_extension(utf8 *path, const utf8 *newExtension, size_t size);
void path_append_extension(utf8 *path, const utf8 *newExtension, size_t size);
void path_remove_extension(utf8 *path);
void path_end_with_separator(utf8 *path, size_t size);
bool readentirefile(const utf8 *path, void **outBuffer, size_t *outLength);
bool writeentirefile(const utf8 * path, const void * buffer, size_t length);
bool sse41_available();