From bf4436178d7ff975ea4de11c6343d88eb1efdd20 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 3 Sep 2017 20:49:58 -0400 Subject: [PATCH] cache: split index data reading off. It is shared with the cache client too. --- .../java/net/runelite/cache/fs/Archive.java | 23 -- .../java/net/runelite/cache/fs/Index.java | 105 ++-------- .../net/runelite/cache/index/ArchiveData.java | 95 +++++++++ .../net/runelite/cache/index/FileData.java | 51 +++++ .../net/runelite/cache/index/IndexData.java | 197 ++++++++++++++++++ 5 files changed, 365 insertions(+), 106 deletions(-) create mode 100644 cache/src/main/java/net/runelite/cache/index/ArchiveData.java create mode 100644 cache/src/main/java/net/runelite/cache/index/FileData.java create mode 100644 cache/src/main/java/net/runelite/cache/index/IndexData.java diff --git a/cache/src/main/java/net/runelite/cache/fs/Archive.java b/cache/src/main/java/net/runelite/cache/fs/Archive.java index 76e652954c..dc30c04526 100644 --- a/cache/src/main/java/net/runelite/cache/fs/Archive.java +++ b/cache/src/main/java/net/runelite/cache/fs/Archive.java @@ -120,19 +120,6 @@ public class Archive return file; } - public void loadFiles(InputStream stream, int numberOfFiles, int protocol) - { - int archive = 0; - - for (int i = 0; i < numberOfFiles; ++i) - { - int fileId = archive += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); - - FSFile file = new FSFile(this, fileId); - this.files.add(file); - } - } - public void decompressAndLoad(int[] keys) throws IOException { byte[] encryptedData = this.getData(); @@ -428,16 +415,6 @@ public class Archive Collections.sort(files, (f1, f2) -> Integer.compare(f1.getFileId(), f2.getFileId())); } - public void loadNames(InputStream stream, int numberOfFiles) - { - for (int i = 0; i < numberOfFiles; ++i) - { - FSFile file = this.files.get(i); - int name = stream.readInt(); - file.setNameHash(name); - } - } - public int getArchiveId() { return archiveId; diff --git a/cache/src/main/java/net/runelite/cache/fs/Index.java b/cache/src/main/java/net/runelite/cache/fs/Index.java index 8108c8ddf1..8085dd96f3 100644 --- a/cache/src/main/java/net/runelite/cache/fs/Index.java +++ b/cache/src/main/java/net/runelite/cache/fs/Index.java @@ -35,8 +35,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; +import net.runelite.cache.index.ArchiveData; +import net.runelite.cache.index.FileData; +import net.runelite.cache.index.IndexData; import net.runelite.cache.util.Djb2; -import net.runelite.cache.io.InputStream; import net.runelite.cache.io.OutputStream; import net.runelite.cache.util.Crc32; import net.runelite.cache.util.Whirlpool; @@ -347,92 +349,29 @@ public class Index implements Closeable public void readIndexData(byte[] data) { - InputStream stream = new InputStream(data); - protocol = stream.readUnsignedByte(); - if (protocol >= 5 && protocol <= 7) + IndexData indexData = new IndexData(); + indexData.load(data); + + protocol = indexData.getProtocol(); + revision = indexData.getRevision(); + named = indexData.isNamed(); + usesWhirpool = indexData.isUsesWhirpool(); + + for (ArchiveData ad : indexData.getArchives()) { - if (protocol >= 6) + Archive archive = new Archive(this, ad.getId()); + archive.setNameHash(ad.getNameHash()); + archive.setWhirlpool(ad.getWhirlpool()); + archive.setCrc(ad.getCrc()); + archive.setRevision(ad.getRevision()); + + for (FileData fd : ad.getFiles()) { - this.revision = stream.readInt(); + FSFile file = archive.addFile(fd.getId()); + file.setNameHash(fd.getNameHash()); } - int hash = stream.readUnsignedByte(); - named = (1 & hash) != 0; - usesWhirpool = (2 & hash) != 0; - assert (hash & ~3) == 0; - int validArchivesCount = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); - int lastArchiveId = 0; - - int index; - int archive; - for (index = 0; index < validArchivesCount; ++index) - { - archive = lastArchiveId += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); - Archive a = new Archive(this, archive); - this.archives.add(a); - } - - if (named) - { - for (index = 0; index < validArchivesCount; ++index) - { - int nameHash = stream.readInt(); - Archive a = this.archives.get(index); - a.setNameHash(nameHash); - } - } - - if (usesWhirpool) - { - for (index = 0; index < validArchivesCount; ++index) - { - byte[] var13 = new byte[64]; - stream.readBytes(var13); - - Archive a = this.archives.get(index); - a.setWhirlpool(var13); - } - } - - for (index = 0; index < validArchivesCount; ++index) - { - int crc = stream.readInt(); - - Archive a = this.archives.get(index); - a.setCrc(crc); - } - - for (index = 0; index < validArchivesCount; ++index) - { - int revision = stream.readInt(); - - Archive a = this.archives.get(index); - a.setRevision(revision); - } - - int[] numberOfFiles = new int[validArchivesCount]; - for (index = 0; index < validArchivesCount; ++index) - { - int num = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); - numberOfFiles[index] = num; - } - - for (index = 0; index < validArchivesCount; ++index) - { - archive = 0; - - Archive a = this.archives.get(index); - a.loadFiles(stream, numberOfFiles[index], protocol); - } - - if (named) - { - for (index = 0; index < validArchivesCount; ++index) - { - Archive a = this.archives.get(index); - a.loadNames(stream, numberOfFiles[index]); - } - } + archives.add(archive); } } diff --git a/cache/src/main/java/net/runelite/cache/index/ArchiveData.java b/cache/src/main/java/net/runelite/cache/index/ArchiveData.java new file mode 100644 index 0000000000..71ddc56c59 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/index/ArchiveData.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.index; + +public class ArchiveData +{ + int id; + int nameHash; + byte[] whirlpool; + int crc; + int revision; + FileData[] files; + + public int getId() + { + return id; + } + + public void setId(int id) + { + this.id = id; + } + + public int getNameHash() + { + return nameHash; + } + + public void setNameHash(int nameHash) + { + this.nameHash = nameHash; + } + + public byte[] getWhirlpool() + { + return whirlpool; + } + + public void setWhirlpool(byte[] whirlpool) + { + this.whirlpool = whirlpool; + } + + public int getCrc() + { + return crc; + } + + public void setCrc(int crc) + { + this.crc = crc; + } + + public int getRevision() + { + return revision; + } + + public void setRevision(int revision) + { + this.revision = revision; + } + + public FileData[] getFiles() + { + return files; + } + + public void setFiles(FileData[] files) + { + this.files = files; + } +} diff --git a/cache/src/main/java/net/runelite/cache/index/FileData.java b/cache/src/main/java/net/runelite/cache/index/FileData.java new file mode 100644 index 0000000000..dfe8f41e48 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/index/FileData.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.index; + +public class FileData +{ + int id; + int nameHash; + + public int getId() + { + return id; + } + + public void setId(int id) + { + this.id = id; + } + + public int getNameHash() + { + return nameHash; + } + + public void setNameHash(int nameHash) + { + this.nameHash = nameHash; + } +} diff --git a/cache/src/main/java/net/runelite/cache/index/IndexData.java b/cache/src/main/java/net/runelite/cache/index/IndexData.java new file mode 100644 index 0000000000..492d2f7455 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/index/IndexData.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.index; + +import net.runelite.cache.io.InputStream; + +public class IndexData +{ + private int protocol; + private int revision; + private boolean named; + private boolean usesWhirpool; + private ArchiveData[] archives; + + public void load(byte[] data) + { + InputStream stream = new InputStream(data); + protocol = stream.readUnsignedByte(); + if (protocol < 5 || protocol > 7) + { + throw new IllegalArgumentException("Unsupported protocol"); + } + + if (protocol >= 6) + { + this.revision = stream.readInt(); + } + + int hash = stream.readUnsignedByte(); + named = (1 & hash) != 0; + usesWhirpool = (2 & hash) != 0; + assert (hash & ~3) == 0; + int validArchivesCount = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); + int lastArchiveId = 0; + + archives = new ArchiveData[validArchivesCount]; + + for (int index = 0; index < validArchivesCount; ++index) + { + int archive = lastArchiveId += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); + + ArchiveData ad = new ArchiveData(); + ad.id = archive; + archives[index] = ad; + } + + if (named) + { + for (int index = 0; index < validArchivesCount; ++index) + { + int nameHash = stream.readInt(); + ArchiveData ad = archives[index]; + ad.nameHash = nameHash; + } + } + + if (usesWhirpool) + { + for (int index = 0; index < validArchivesCount; ++index) + { + byte[] w = new byte[64]; + stream.readBytes(w); + + ArchiveData ad = archives[index]; + ad.whirlpool = w; + } + } + + for (int index = 0; index < validArchivesCount; ++index) + { + int crc = stream.readInt(); + + ArchiveData ad = archives[index]; + ad.crc = crc; + } + + for (int index = 0; index < validArchivesCount; ++index) + { + int revision = stream.readInt(); + + ArchiveData ad = archives[index]; + ad.revision = revision; + } + + int[] numberOfFiles = new int[validArchivesCount]; + for (int index = 0; index < validArchivesCount; ++index) + { + int num = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); + numberOfFiles[index] = num; + } + + for (int index = 0; index < validArchivesCount; ++index) + { + ArchiveData ad = archives[index]; + int num = numberOfFiles[index]; + + ad.files = new FileData[num]; + + int last = 0; + for (int i = 0; i < num; ++i) + { + int fileId = last += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); + + FileData fd = ad.files[i] = new FileData(); + fd.id = fileId; + } + } + + if (named) + { + for (int index = 0; index < validArchivesCount; ++index) + { + ArchiveData ad = archives[index]; + int num = numberOfFiles[index]; + + for (int i = 0; i < num; ++i) + { + FileData fd = ad.files[i]; + int name = stream.readInt(); + fd.nameHash = name; + } + } + } + } + + public int getProtocol() + { + return protocol; + } + + public void setProtocol(int protocol) + { + this.protocol = protocol; + } + + public int getRevision() + { + return revision; + } + + public void setRevision(int revision) + { + this.revision = revision; + } + + public boolean isNamed() + { + return named; + } + + public void setNamed(boolean named) + { + this.named = named; + } + + public boolean isUsesWhirpool() + { + return usesWhirpool; + } + + public void setUsesWhirpool(boolean usesWhirpool) + { + this.usesWhirpool = usesWhirpool; + } + + public ArchiveData[] getArchives() + { + return archives; + } + + public void setArchives(ArchiveData[] archives) + { + this.archives = archives; + } +}