mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-12 17:17:09 -04:00
Simplify ZIP reader api and make it a little bit faster in most cases
This commit is contained in:
parent
e6a49460eb
commit
4a9551e661
113
src/Deflate.c
113
src/Deflate.c
@ -1124,20 +1124,49 @@ void ZLib_MakeStream(struct Stream* stream, struct ZLibState* state, struct Stre
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------------ZipEntry---------------------------------------------------------*
|
||||
*--------------------------------------------------------ZipReader--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#define ZIP_MAXNAMELEN 512
|
||||
#define ZIP_MAX_ENTRIES 1024
|
||||
|
||||
/* Stores state for reading and processing entries in a .zip archive */
|
||||
struct ZipState {
|
||||
struct Stream* source;
|
||||
Zip_SelectEntry SelectEntry;
|
||||
Zip_ProcessEntry ProcessEntry;
|
||||
|
||||
/* Number of entries selected by SelectEntry */
|
||||
int usedEntries;
|
||||
/* Total number of entries in the archive */
|
||||
int totalEntries;
|
||||
/* Offset to central directory entries */
|
||||
cc_uint32 centralDirBeg;
|
||||
/* Data for each entry in the .zip archive */
|
||||
struct ZipEntry entries[ZIP_MAX_ENTRIES];
|
||||
};
|
||||
|
||||
static cc_result Zip_ReadLocalFileHeader(struct ZipState* state, struct ZipEntry* entry) {
|
||||
struct Stream* stream = state->input;
|
||||
struct Stream* stream = state->source;
|
||||
cc_uint8 header[26];
|
||||
cc_string path; char pathBuffer[ZIP_MAXNAMELEN];
|
||||
cc_uint32 compressedSize, uncompressedSize;
|
||||
int method, pathLen, extraLen;
|
||||
|
||||
cc_string path; char pathBuffer[ZIP_MAXNAMELEN];
|
||||
struct Stream portion, compStream;
|
||||
struct InflateState inflate;
|
||||
cc_result res;
|
||||
|
||||
if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
|
||||
pathLen = Stream_GetU16_LE(&header[22]);
|
||||
if (pathLen > ZIP_MAXNAMELEN) return ZIP_ERR_FILENAME_LEN;
|
||||
|
||||
/* NOTE: ZIP spec says path uses code page 437 for encoding */
|
||||
path = String_Init(pathBuffer, pathLen, pathLen);
|
||||
if ((res = Stream_Read(stream, (cc_uint8*)pathBuffer, pathLen))) return res;
|
||||
if (!state->SelectEntry(&path)) return 0;
|
||||
|
||||
extraLen = Stream_GetU16_LE(&header[24]);
|
||||
/* local file may have extra data before actual data (e.g. ZIP64) */
|
||||
if ((res = stream->Skip(stream, extraLen))) return res;
|
||||
|
||||
method = Stream_GetU16_LE(&header[4]);
|
||||
compressedSize = Stream_GetU32_LE(&header[14]);
|
||||
@ -1147,26 +1176,13 @@ static cc_result Zip_ReadLocalFileHeader(struct ZipState* state, struct ZipEntry
|
||||
if (!compressedSize) compressedSize = entry->CompressedSize;
|
||||
if (!uncompressedSize) uncompressedSize = entry->UncompressedSize;
|
||||
|
||||
pathLen = Stream_GetU16_LE(&header[22]);
|
||||
extraLen = Stream_GetU16_LE(&header[24]);
|
||||
if (pathLen > ZIP_MAXNAMELEN) return ZIP_ERR_FILENAME_LEN;
|
||||
|
||||
/* NOTE: ZIP spec says path uses code page 437 for encoding */
|
||||
path = String_Init(pathBuffer, pathLen, pathLen);
|
||||
if ((res = Stream_Read(stream, (cc_uint8*)pathBuffer, pathLen))) return res;
|
||||
state->_curEntry = entry;
|
||||
|
||||
if (!state->SelectEntry(&path)) return 0;
|
||||
/* local file may have extra data before actual data (e.g. ZIP64) */
|
||||
if ((res = stream->Skip(stream, extraLen))) return res;
|
||||
|
||||
if (method == 0) {
|
||||
Stream_ReadonlyPortion(&portion, stream, uncompressedSize);
|
||||
return state->ProcessEntry(&path, &portion, state);
|
||||
return state->ProcessEntry(&path, &portion, entry);
|
||||
} else if (method == 8) {
|
||||
Stream_ReadonlyPortion(&portion, stream, compressedSize);
|
||||
Inflate_MakeStream2(&compStream, &inflate, &portion);
|
||||
return state->ProcessEntry(&path, &compStream, state);
|
||||
return state->ProcessEntry(&path, &compStream, entry);
|
||||
} else {
|
||||
Platform_Log1("Unsupported.zip entry compression method: %i", &method);
|
||||
/* TODO: Should this be an error */
|
||||
@ -1175,15 +1191,15 @@ static cc_result Zip_ReadLocalFileHeader(struct ZipState* state, struct ZipEntry
|
||||
}
|
||||
|
||||
static cc_result Zip_ReadCentralDirectory(struct ZipState* state) {
|
||||
struct Stream* stream = state->input;
|
||||
struct Stream* stream = state->source;
|
||||
struct ZipEntry* entry;
|
||||
cc_uint8 header[42];
|
||||
|
||||
cc_string path; char pathBuffer[ZIP_MAXNAMELEN];
|
||||
int pathLen, extraLen, commentLen;
|
||||
cc_result res;
|
||||
if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
|
||||
|
||||
if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
|
||||
pathLen = Stream_GetU16_LE(&header[24]);
|
||||
if (pathLen > ZIP_MAXNAMELEN) return ZIP_ERR_FILENAME_LEN;
|
||||
|
||||
@ -1197,8 +1213,8 @@ static cc_result Zip_ReadCentralDirectory(struct ZipState* state) {
|
||||
if ((res = stream->Skip(stream, extraLen + commentLen))) return res;
|
||||
|
||||
if (!state->SelectEntry(&path)) return 0;
|
||||
if (state->_usedEntries >= ZIP_MAX_ENTRIES) return ZIP_ERR_TOO_MANY_ENTRIES;
|
||||
entry = &state->entries[state->_usedEntries++];
|
||||
if (state->usedEntries >= ZIP_MAX_ENTRIES) return ZIP_ERR_TOO_MANY_ENTRIES;
|
||||
entry = &state->entries[state->usedEntries++];
|
||||
|
||||
entry->CRC32 = Stream_GetU32_LE(&header[12]);
|
||||
entry->CompressedSize = Stream_GetU32_LE(&header[16]);
|
||||
@ -1208,14 +1224,14 @@ static cc_result Zip_ReadCentralDirectory(struct ZipState* state) {
|
||||
}
|
||||
|
||||
static cc_result Zip_ReadEndOfCentralDirectory(struct ZipState* state) {
|
||||
struct Stream* stream = state->input;
|
||||
struct Stream* stream = state->source;
|
||||
cc_uint8 header[18];
|
||||
|
||||
cc_result res;
|
||||
if ((res = Stream_Read(stream, header, sizeof(header)))) return res;
|
||||
|
||||
state->_totalEntries = Stream_GetU16_LE(&header[6]);
|
||||
state->_centralDirBeg = Stream_GetU32_LE(&header[12]);
|
||||
state->totalEntries = Stream_GetU16_LE(&header[6]);
|
||||
state->centralDirBeg = Stream_GetU32_LE(&header[12]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1225,48 +1241,43 @@ enum ZipSig {
|
||||
ZIP_SIG_LOCALFILEHEADER = 0x04034b50
|
||||
};
|
||||
|
||||
static cc_result Zip_DefaultProcessor(const cc_string* path, struct Stream* data, struct ZipState* s) { return 0; }
|
||||
static cc_bool Zip_DefaultSelector(const cc_string* path) { return true; }
|
||||
void Zip_Init(struct ZipState* state, struct Stream* input) {
|
||||
state->input = input;
|
||||
state->obj = NULL;
|
||||
state->ProcessEntry = Zip_DefaultProcessor;
|
||||
state->SelectEntry = Zip_DefaultSelector;
|
||||
}
|
||||
|
||||
cc_result Zip_Extract(struct ZipState* state) {
|
||||
struct Stream* stream = state->input;
|
||||
cc_result Zip_Extract(struct Stream* source, Zip_SelectEntry selector, Zip_ProcessEntry processor) {
|
||||
struct ZipState state;
|
||||
cc_uint32 stream_len;
|
||||
cc_uint32 sig = 0;
|
||||
int i, count;
|
||||
|
||||
cc_result res;
|
||||
if ((res = stream->Length(stream, &stream_len))) return res;
|
||||
if ((res = source->Length(source, &stream_len))) return res;
|
||||
|
||||
/* At -22 for nearly all zips, but try a bit further back in case of comment */
|
||||
count = min(257, stream_len);
|
||||
for (i = 22; i < count; i++) {
|
||||
res = stream->Seek(stream, stream_len - i);
|
||||
res = source->Seek(source, stream_len - i);
|
||||
if (res) return ZIP_ERR_SEEK_END_OF_CENTRAL_DIR;
|
||||
|
||||
if ((res = Stream_ReadU32_LE(stream, &sig))) return res;
|
||||
if ((res = Stream_ReadU32_LE(source, &sig))) return res;
|
||||
if (sig == ZIP_SIG_ENDOFCENTRALDIR) break;
|
||||
}
|
||||
|
||||
state.source = source;
|
||||
state.SelectEntry = selector;
|
||||
state.ProcessEntry = processor;
|
||||
|
||||
if (sig != ZIP_SIG_ENDOFCENTRALDIR) return ZIP_ERR_NO_END_OF_CENTRAL_DIR;
|
||||
res = Zip_ReadEndOfCentralDirectory(state);
|
||||
res = Zip_ReadEndOfCentralDirectory(&state);
|
||||
if (res) return res;
|
||||
|
||||
res = stream->Seek(stream, state->_centralDirBeg);
|
||||
res = source->Seek(source, state.centralDirBeg);
|
||||
if (res) return ZIP_ERR_SEEK_CENTRAL_DIR;
|
||||
state->_usedEntries = 0;
|
||||
state.usedEntries = 0;
|
||||
|
||||
/* Read all the central directory entries */
|
||||
for (i = 0; i < state->_totalEntries; i++) {
|
||||
if ((res = Stream_ReadU32_LE(stream, &sig))) return res;
|
||||
for (i = 0; i < state.totalEntries; i++) {
|
||||
if ((res = Stream_ReadU32_LE(source, &sig))) return res;
|
||||
|
||||
if (sig == ZIP_SIG_CENTRALDIR) {
|
||||
res = Zip_ReadCentralDirectory(state);
|
||||
res = Zip_ReadCentralDirectory(&state);
|
||||
if (res) return res;
|
||||
} else if (sig == ZIP_SIG_ENDOFCENTRALDIR) {
|
||||
break;
|
||||
@ -1276,15 +1287,15 @@ cc_result Zip_Extract(struct ZipState* state) {
|
||||
}
|
||||
|
||||
/* Now read the local file header entries */
|
||||
for (i = 0; i < state->_usedEntries; i++) {
|
||||
struct ZipEntry* entry = &state->entries[i];
|
||||
res = stream->Seek(stream, entry->LocalHeaderOffset);
|
||||
for (i = 0; i < state.usedEntries; i++) {
|
||||
struct ZipEntry* entry = &state.entries[i];
|
||||
res = source->Seek(source, entry->LocalHeaderOffset);
|
||||
if (res) return ZIP_ERR_SEEK_LOCAL_DIR;
|
||||
|
||||
if ((res = Stream_ReadU32_LE(stream, &sig))) return res;
|
||||
if ((res = Stream_ReadU32_LE(source, &sig))) return res;
|
||||
if (sig != ZIP_SIG_LOCALFILEHEADER) return ZIP_ERR_INVALID_LOCAL_DIR;
|
||||
|
||||
res = Zip_ReadLocalFileHeader(state, entry);
|
||||
res = Zip_ReadLocalFileHeader(&state, entry);
|
||||
if (res) return res;
|
||||
}
|
||||
return 0;
|
||||
|
@ -115,40 +115,15 @@ struct ZLibState { struct DeflateState Base; cc_uint32 Adler32; };
|
||||
/* ZLIB compression is ZLIB header, followed by DEFLATE compressed data, followed by ZLIB footer. */
|
||||
CC_API void ZLib_MakeStream(struct Stream* stream, struct ZLibState* state, struct Stream* underlying);
|
||||
|
||||
/* Minimal data needed to describe an entry in a .zip archive. */
|
||||
/* Minimal data needed to describe an entry in a .zip archive */
|
||||
struct ZipEntry { cc_uint32 CompressedSize, UncompressedSize, LocalHeaderOffset, CRC32; };
|
||||
#define ZIP_MAX_ENTRIES 1024
|
||||
struct ZipState;
|
||||
/* Callback function to process the data in a .zip archive entry */
|
||||
/* Return non-zero to indicate an error and stop further processing */
|
||||
/* NOTE: data stream MAY NOT be seekable (i.e. entry data might be compressed) */
|
||||
typedef cc_result (*Zip_ProcessEntry)(const cc_string* path, struct Stream* data, struct ZipEntry* entry);
|
||||
/* Predicate used to select which entries in a .zip archive get processed */
|
||||
/* NOTE: returning false entirely skips the entry (avoids pointless seek to entry) */
|
||||
typedef cc_bool (*Zip_SelectEntry)(const cc_string* path);
|
||||
|
||||
/* Stores state for reading and processing entries in a .zip archive. */
|
||||
struct ZipState {
|
||||
/* Source of the .zip archive data. Must be seekable. */
|
||||
struct Stream* input;
|
||||
/* Callback function to process the data in a .zip archive entry. */
|
||||
/* Return non-zero to indicate an error and stop further processing. */
|
||||
/* NOTE: data stream MAY NOT be seekable. (i.e. entry data might be compressed) */
|
||||
cc_result (*ProcessEntry)(const cc_string* path, struct Stream* data, struct ZipState* state);
|
||||
/* Predicate used to select which entries in a .zip archive get processed. */
|
||||
/* NOTE: returning false entirely skips the entry. (avoids pointless seek to entry) */
|
||||
cc_bool (*SelectEntry)(const cc_string* path);
|
||||
/* Generic object/pointer for ProcessEntry callback. */
|
||||
void* obj;
|
||||
|
||||
/* (internal) Number of entries selected by SelectEntry. */
|
||||
int _usedEntries;
|
||||
/* (internal) Total number of entries in the archive. */
|
||||
int _totalEntries;
|
||||
/* (internal) Offset to central directory entries. */
|
||||
cc_uint32 _centralDirBeg;
|
||||
/* (internal) Current entry being processed. */
|
||||
struct ZipEntry* _curEntry;
|
||||
/* Data for each entry in the .zip archive. */
|
||||
struct ZipEntry entries[ZIP_MAX_ENTRIES];
|
||||
};
|
||||
|
||||
/* Initialises .zip archive reader state to defaults. */
|
||||
CC_API void Zip_Init(struct ZipState* state, struct Stream* input);
|
||||
/* Reads and processes the entries in a .zip archive. */
|
||||
/* NOTE: Must have been initialised with Zip_Init first. */
|
||||
CC_API cc_result Zip_Extract(struct ZipState* state);
|
||||
CC_API cc_result Zip_Extract(struct Stream* source, Zip_SelectEntry selector, Zip_ProcessEntry processor);
|
||||
#endif
|
||||
|
@ -401,7 +401,7 @@ static cc_bool Launcher_SelectZipEntry(const cc_string* path) {
|
||||
String_CaselessEqualsConst(path, "terrain.png");
|
||||
}
|
||||
|
||||
static cc_result Launcher_ProcessZipEntry(const cc_string* path, struct Stream* data, struct ZipState* s) {
|
||||
static cc_result Launcher_ProcessZipEntry(const cc_string* path, struct Stream* data, struct ZipEntry* source) {
|
||||
struct Bitmap bmp;
|
||||
cc_result res;
|
||||
|
||||
@ -432,7 +432,6 @@ static cc_result Launcher_ProcessZipEntry(const cc_string* path, struct Stream*
|
||||
}
|
||||
|
||||
static void ExtractTexturePack(const cc_string* path) {
|
||||
struct ZipState state;
|
||||
struct Stream stream;
|
||||
cc_result res;
|
||||
|
||||
@ -440,10 +439,8 @@ static void ExtractTexturePack(const cc_string* path) {
|
||||
if (res == ReturnCode_FileNotFound) return;
|
||||
if (res) { Logger_SysWarn(res, "opening texture pack"); return; }
|
||||
|
||||
Zip_Init(&state, &stream);
|
||||
state.SelectEntry = Launcher_SelectZipEntry;
|
||||
state.ProcessEntry = Launcher_ProcessZipEntry;
|
||||
res = Zip_Extract(&state);
|
||||
res = Zip_Extract(&stream,
|
||||
Launcher_SelectZipEntry, Launcher_ProcessZipEntry);
|
||||
|
||||
if (res) { Logger_SysWarn(res, "extracting texture pack"); }
|
||||
/* No point logging error for closing readonly file */
|
||||
|
@ -399,6 +399,7 @@ static cc_result ZipWriter_WritePng(struct Stream* dst, struct ResourceZipEntry*
|
||||
"# fire\r\n" \
|
||||
"6 2 0 0 16 32 0"
|
||||
|
||||
/* The entries that are required to exist within default.zip */
|
||||
static struct ResourceZipEntry defaultZipEntries[] = {
|
||||
/* classic jar files */
|
||||
{ "char.png", RESOURCE_TYPE_DATA }, { "clouds.png", RESOURCE_TYPE_DATA },
|
||||
@ -429,13 +430,13 @@ CC_NOINLINE static struct ResourceZipEntry* ZipEntries_Find(const cc_string* nam
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static cc_result ZipEntry_ExtractData(struct ResourceZipEntry* e, struct ZipState* state, struct Stream* src) {
|
||||
cc_uint32 size = state->_curEntry->UncompressedSize;
|
||||
static cc_result ZipEntry_ExtractData(struct ResourceZipEntry* e, struct Stream* data, struct ZipEntry* source) {
|
||||
cc_uint32 size = source->UncompressedSize;
|
||||
e->value.data = Mem_TryAlloc(size, 1);
|
||||
e->size = size;
|
||||
|
||||
if (!e->value.data) return ERR_OUT_OF_MEMORY;
|
||||
return Stream_Read(src, e->value.data, size);
|
||||
return Stream_Read(data, e->value.data, size);
|
||||
}
|
||||
|
||||
|
||||
@ -444,6 +445,7 @@ static cc_result ModernPatcher_ExtractFiles(struct HttpRequest* req);
|
||||
static cc_result TerrainPatcher_Process(struct HttpRequest* req);
|
||||
static cc_result NewTextures_ExtractGui(struct HttpRequest* req);
|
||||
|
||||
/* URLs which data is downloaded from in order to generate the entries in default.zip */
|
||||
static struct ZipfileSource {
|
||||
const char* name;
|
||||
const char* url;
|
||||
@ -472,34 +474,30 @@ static cc_bool ClassicPatcher_SelectEntry(const cc_string* path) {
|
||||
return ZipEntries_Find(&name) != NULL;
|
||||
}
|
||||
|
||||
static cc_result ClassicPatcher_ProcessEntry(const cc_string* path, struct Stream* data, struct ZipState* state) {
|
||||
static cc_result ClassicPatcher_ProcessEntry(const cc_string* path, struct Stream* data, struct ZipEntry* source) {
|
||||
static const cc_string guiClassicPng = String_FromConst("gui_classic.png");
|
||||
struct ResourceZipEntry* entry;
|
||||
struct ResourceZipEntry* e;
|
||||
cc_string name;
|
||||
|
||||
name = *path;
|
||||
Utils_UNSAFE_GetFilename(&name);
|
||||
if (String_CaselessEqualsConst(&name, "gui.png")) name = guiClassicPng;
|
||||
|
||||
entry = ZipEntries_Find(&name);
|
||||
e = ZipEntries_Find(&name);
|
||||
|
||||
/* terrain.png requires special handling */
|
||||
if (String_CaselessEqualsConst(path, "terrain.png")) {
|
||||
return Png_Decode(&entry->value.bmp, data);
|
||||
return Png_Decode(&e->value.bmp, data);
|
||||
}
|
||||
return ZipEntry_ExtractData(entry, state, data);
|
||||
return ZipEntry_ExtractData(e, data, source);
|
||||
}
|
||||
|
||||
static cc_result ClassicPatcher_ExtractFiles(struct HttpRequest* req) {
|
||||
struct ZipState zip;
|
||||
struct Stream src;
|
||||
|
||||
Stream_ReadonlyMemory(&src, req->data, req->size);
|
||||
Zip_Init(&zip, &src);
|
||||
|
||||
zip.SelectEntry = ClassicPatcher_SelectEntry;
|
||||
zip.ProcessEntry = ClassicPatcher_ProcessEntry;
|
||||
return Zip_Extract(&zip);
|
||||
return Zip_Extract(&src,
|
||||
ClassicPatcher_SelectEntry, ClassicPatcher_ProcessEntry);
|
||||
}
|
||||
|
||||
/* the x,y of tiles in terrain.png which get patched */
|
||||
@ -577,8 +575,8 @@ static cc_result ModernPatcher_MakeAnimations(struct Stream* data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cc_result ModernPatcher_ProcessEntry(const cc_string* path, struct Stream* data, struct ZipState* state) {
|
||||
struct ResourceZipEntry* entry;
|
||||
static cc_result ModernPatcher_ProcessEntry(const cc_string* path, struct Stream* data, struct ZipEntry* source) {
|
||||
struct ResourceZipEntry* e;
|
||||
const struct TilePatch* tile;
|
||||
cc_string name;
|
||||
|
||||
@ -587,8 +585,8 @@ static cc_result ModernPatcher_ProcessEntry(const cc_string* path, struct Stream
|
||||
name = *path;
|
||||
Utils_UNSAFE_GetFilename(&name);
|
||||
|
||||
entry = ZipEntries_Find(&name);
|
||||
return ZipEntry_ExtractData(entry, state, data);
|
||||
e = ZipEntries_Find(&name);
|
||||
return ZipEntry_ExtractData(e, data, source);
|
||||
}
|
||||
|
||||
if (String_CaselessEqualsConst(path, "assets/minecraft/textures/blocks/fire_layer_1.png")) {
|
||||
@ -600,15 +598,11 @@ static cc_result ModernPatcher_ProcessEntry(const cc_string* path, struct Stream
|
||||
}
|
||||
|
||||
static cc_result ModernPatcher_ExtractFiles(struct HttpRequest* req) {
|
||||
struct ZipState zip;
|
||||
struct Stream src;
|
||||
|
||||
Stream_ReadonlyMemory(&src, req->data, req->size);
|
||||
Zip_Init(&zip, &src);
|
||||
|
||||
zip.SelectEntry = ModernPatcher_SelectEntry;
|
||||
zip.ProcessEntry = ModernPatcher_ProcessEntry;
|
||||
return Zip_Extract(&zip);
|
||||
return Zip_Extract(&src,
|
||||
ModernPatcher_SelectEntry, ModernPatcher_ProcessEntry);
|
||||
}
|
||||
|
||||
#ifdef CC_BUILD_MOBILE
|
||||
@ -617,18 +611,17 @@ static cc_result ModernPatcher_ExtractFiles(struct HttpRequest* req) {
|
||||
static cc_bool NewTextures_SelectEntry(const cc_string* path) {
|
||||
return String_CaselessEqualsConst(path, "gui.png") || String_CaselessEqualsConst(path, "touch.png");
|
||||
}
|
||||
static cc_result NewTextures_ProcessEntry(const cc_string* path, struct Stream* data, struct ZipState* state) {
|
||||
struct ResourceZipEntry* entry = ZipEntries_Find(path);
|
||||
return ZipEntry_ExtractData(entry, state, data);
|
||||
static cc_result NewTextures_ProcessEntry(const cc_string* path, struct Stream* data, struct ZipEntry* source) {
|
||||
struct ResourceZipEntry* e = ZipEntries_Find(path);
|
||||
return ZipEntry_ExtractData(e, data, source);
|
||||
}
|
||||
|
||||
static cc_result NewTextures_ExtractGui(struct HttpRequest* req) {
|
||||
struct ZipState zip;
|
||||
struct Stream src;
|
||||
|
||||
Stream_ReadonlyMemory(&src, req->data, req->size);
|
||||
Zip_Init(&zip, &src);
|
||||
|
||||
zip.input = &src;
|
||||
zip.SelectEntry = NewTextures_SelectEntry;
|
||||
zip.ProcessEntry = NewTextures_ProcessEntry;
|
||||
return Zip_Extract(&zip);
|
||||
@ -741,20 +734,17 @@ static cc_bool DefaultZip_SelectEntry(const cc_string* path) {
|
||||
static void DefaultZip_CountEntries(void) {
|
||||
static const cc_string path = String_FromConst("texpacks/default.zip");
|
||||
struct Stream stream;
|
||||
struct ZipState state;
|
||||
cc_result res;
|
||||
|
||||
res = Stream_OpenFile(&stream, &path);
|
||||
if (res == ReturnCode_FileNotFound) return;
|
||||
if (res) { Logger_SysWarn2(res, "opening", &path); return; }
|
||||
|
||||
if (res) { Logger_SysWarn(res, "checking default.zip"); return; }
|
||||
Zip_Init(&state, &stream);
|
||||
state.SelectEntry = DefaultZip_SelectEntry;
|
||||
|
||||
res = Zip_Extract(&state);
|
||||
stream.Close(&stream);
|
||||
if (res) Logger_SysWarn(res, "inspecting default.zip");
|
||||
res = Zip_Extract(&stream, DefaultZip_SelectEntry, NULL);
|
||||
if (res) Logger_SysWarn2(res, "inspecting", &path);
|
||||
|
||||
/* No point logging error for closing readonly file */
|
||||
(void)stream.Close(&stream);
|
||||
/* >= in case somehow have say "gui.png", "GUI.png" */
|
||||
allZipEntriesExist = zipEntriesFound >= Array_Elems(defaultZipEntries);
|
||||
}
|
||||
|
@ -293,20 +293,14 @@ void TexturePack_SetDefault(const cc_string* texPack) {
|
||||
Options_Set(OPT_DEFAULT_TEX_PACK, texPack);
|
||||
}
|
||||
|
||||
static cc_result ProcessZipEntry(const cc_string* path, struct Stream* stream, struct ZipState* s) {
|
||||
static cc_bool SelectZipEntry(const cc_string* path) { return true; }
|
||||
static cc_result ProcessZipEntry(const cc_string* path, struct Stream* stream, struct ZipEntry* source) {
|
||||
cc_string name = *path;
|
||||
Utils_UNSAFE_GetFilename(&name);
|
||||
Event_RaiseEntry(&TextureEvents.FileChanged, stream, &name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cc_result ExtractZip(struct Stream* stream) {
|
||||
struct ZipState state;
|
||||
Zip_Init(&state, stream);
|
||||
state.ProcessEntry = ProcessZipEntry;
|
||||
return Zip_Extract(&state);
|
||||
}
|
||||
|
||||
static cc_result ExtractPng(struct Stream* stream) {
|
||||
struct Bitmap bmp;
|
||||
cc_result res = Png_Decode(&bmp, stream);
|
||||
@ -328,8 +322,9 @@ static cc_result ExtractFrom(struct Stream* stream, const cc_string* path) {
|
||||
|
||||
res = ExtractPng(stream);
|
||||
if (res == PNG_ERR_INVALID_SIG) {
|
||||
/* file isn't a .png, probably a .zip then */
|
||||
res = ExtractZip(stream);
|
||||
/* file isn't a .png image, probably a .zip archive then */
|
||||
res = Zip_Extract(stream, SelectZipEntry, ProcessZipEntry);
|
||||
|
||||
if (res) Logger_SysWarn2(res, "extracting", path);
|
||||
} else if (res) {
|
||||
Logger_SysWarn2(res, "decoding", path);
|
||||
|
Loading…
x
Reference in New Issue
Block a user