Skip to content

Commit 8fec609

Browse files
Merge pull request #19 from runetopic/development
Replace Synchronized annotations by making the lists Synchronized ins…
2 parents 629635f + 3118b75 commit 8fec609

File tree

9 files changed

+112
-163
lines changed

9 files changed

+112
-163
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ A cache library written in Kotlin.
2828
# Implementation
2929
Just use cache if you do not require any of the revision specific loaders.
3030
```
31-
cache = { module = "com.runetopic.cache:cache", version.ref "1.4.15-SNAPSHOT" }
31+
cache = { module = "com.runetopic.cache:cache", version.ref "1.4.16-SNAPSHOT" }
3232
loader = { module = "com.runetopic.cache:loader", version.ref "647.6.3-SNAPSHOT" }
3333
```
3434

cache/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
signing
55
}
66

7-
version = "1.4.15-SNAPSHOT"
7+
version = "1.4.16-SNAPSHOT"
88

99
java {
1010
withJavadocJar()

cache/src/main/kotlin/com/runetopic/cache/codec/ContainerCodec.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.runetopic.cache.codec
22

33
import com.runetopic.cache.codec.CodecType.*
44
import com.runetopic.cache.exception.CompressionException
5+
import com.runetopic.cache.extension.readUnsignedByte
56
import com.runetopic.cache.extension.readUnsignedShort
67
import com.runetopic.cache.extension.remainingBytes
78
import com.runetopic.cryptography.fromXTEA
@@ -19,7 +20,7 @@ internal object ContainerCodec {
1920
fun decompress(data: ByteArray, keys: IntArray = intArrayOf()): Container {
2021
val buffer = ByteBuffer.wrap(data)
2122

22-
val compression = buffer.get().toInt() and 0xFF
23+
val compression = buffer.readUnsignedByte()
2324
val length = buffer.int
2425

2526
if (length < 0 || length > 2000000) {

cache/src/main/kotlin/com/runetopic/cache/extension/ByteBuffer.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import java.nio.ByteBuffer
44

55
internal fun ByteBuffer.readUnsignedByte(): Int = get().toInt() and 0xFF
66
internal fun ByteBuffer.readUnsignedShort(): Int = short.toInt() and 0xFFFF
7+
internal fun ByteBuffer.readUnsignedMedium(): Int = ((get().toInt() and 0xFF shl 16) or (get().toInt() and 0xFF shl 8) or (get().toInt() and 0xFF))
78
internal fun ByteBuffer.readUnsignedIntShortSmart(): Int = if (get(position()).toInt() < 0) int and Int.MAX_VALUE else readUnsignedShort()
89

910
internal fun ByteBuffer.remainingBytes(): ByteArray {

cache/src/main/kotlin/com/runetopic/cache/store/Js5Store.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import java.io.Closeable
77
import java.math.BigInteger
88
import java.nio.ByteBuffer
99
import java.nio.file.Path
10+
import java.util.concurrent.CopyOnWriteArrayList
1011

1112
/**
1213
* @author Tyler Telis
@@ -19,14 +20,13 @@ class Js5Store(
1920
parallel: Boolean = false
2021
) : Closeable {
2122
private var storage = Js5DiskStorage(path, parallel)
22-
private val indexes = arrayListOf<Index>()
23+
private val indexes = CopyOnWriteArrayList<Index>()
2324

2425
init {
2526
storage.init(this)
2627
indexes.sortWith(compareBy { it.id })
2728
}
2829

29-
@Synchronized
3030
internal fun addIndex(index: Index) {
3131
indexes.forEach { i -> require(index.id != i.id) { "Index with Id={${index.id}} already exists." } }
3232
indexes.add(index)

cache/src/main/kotlin/com/runetopic/cache/store/storage/js5/Js5DiskStorage.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.runetopic.cache.store.storage.js5.impl.IdxFile
1111
import com.runetopic.cryptography.toWhirlpool
1212
import java.io.FileNotFoundException
1313
import java.nio.file.Path
14+
import java.util.concurrent.CopyOnWriteArrayList
1415
import java.util.concurrent.CountDownLatch
1516
import java.util.concurrent.Executors
1617
import kotlin.io.path.ExperimentalPathApi
@@ -29,7 +30,7 @@ internal class Js5DiskStorage(
2930
) : IStorage {
3031
private var masterIdxFile: IIdxFile
3132
private var datFile: IDatFile
32-
private var idxFiles: ArrayList<IdxFile> = arrayListOf()
33+
private var idxFiles = CopyOnWriteArrayList<IdxFile>()
3334
private val logger = InlineLogger()
3435

3536
init {
@@ -79,7 +80,7 @@ internal class Js5DiskStorage(
7980
return
8081
}
8182
val indexDatTable = datFile.readReferenceTable(masterIdxFile.id(), indexTable)
82-
store.addIndex(loadIndex(datFile, getIdxFile(indexId), indexDatTable.toWhirlpool(), ContainerCodec.decompress(indexDatTable)))
83+
store.addIndex(decode(datFile, getIdxFile(indexId), indexDatTable.toWhirlpool(), ContainerCodec.decompress(indexDatTable)))
8384
}
8485

8586
override fun loadMasterReferenceTable(groupId: Int): ByteArray {
@@ -96,7 +97,6 @@ internal class Js5DiskStorage(
9697
return datFile.readReferenceTable(index.id, getIdxFile(index.id).loadReferenceTable(group.id))
9798
}
9899

99-
@Synchronized
100100
private fun getIdxFile(id: Int): IdxFile {
101101
idxFiles.find { it.id() == id }?.let { return it }
102102
return IdxFile(id, Path.of("$path/${Constants.MAIN_FILE_IDX}${id}"))

cache/src/main/kotlin/com/runetopic/cache/store/storage/js5/Js5IndexFactory.kt renamed to cache/src/main/kotlin/com/runetopic/cache/store/storage/js5/Js5IndexDecoder.kt

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ import java.util.zip.ZipException
1515
/**
1616
* @author Jordan Abraham
1717
*/
18-
internal fun loadIndex(
18+
internal fun decode(
1919
datFile: IDatFile,
2020
idxFile: IIdxFile,
2121
whirlpool: ByteArray,
2222
decompressed: Container
2323
): Index {
2424
val buffer = ByteBuffer.wrap(decompressed.data)
25-
val crc = decompressed.crc
26-
val compression = decompressed.compression
2725
val protocol = buffer.readUnsignedByte()
2826
val revision = when {
2927
protocol < 5 || protocol > 7 -> throw ProtocolException("Unhandled protocol $protocol")
@@ -41,23 +39,15 @@ internal fun loadIndex(
4139
val isNamed = (0x1 and hash) != 0
4240
val isUsingWhirlpool = (0x2 and hash) != 0
4341

44-
val groupIds = IntArray(count)
45-
var lastGroupId = 0
46-
var biggest = -1
47-
(0 until count).forEach {
48-
groupIds[it] = if (protocol >= 7) { buffer.readUnsignedIntShortSmart() } else { buffer.readUnsignedShort() }
49-
.let { id -> lastGroupId += id; lastGroupId }
50-
if (groupIds[it] > biggest) biggest = groupIds[it]
51-
}
52-
53-
val largestGroupId = biggest + 1
54-
val groupNameHashes = groupNameHashes(largestGroupId, count, isNamed, groupIds, buffer)
55-
val groupCrcs = groupCrcs(largestGroupId, count, groupIds, buffer)
56-
val groupWhirlpools = groupWhirlpools(largestGroupId, isUsingWhirlpool, count, buffer, groupIds)
57-
val groupRevisions = groupRevisions(largestGroupId, count, groupIds, buffer)
58-
val groupFileIds = groupFileIds(largestGroupId, count, groupIds, buffer, protocol)
59-
val fileIds = fileIds(largestGroupId, groupFileIds, count, groupIds, buffer, protocol)
60-
val fileNameHashes = fileNameHashes(largestGroupId, groupFileIds, count, groupIds, buffer, isNamed)
42+
val groupIds = decodeGroupIds(count, buffer, protocol)
43+
val maxGroupId = (groupIds.maxOrNull() ?: -1) + 1
44+
val groupNameHashes = decodeGroupNameHashes(maxGroupId, count, isNamed, groupIds, buffer)
45+
val groupCrcs = decodeGroupCrcs(maxGroupId, count, groupIds, buffer)
46+
val groupWhirlpools = decodeGroupWhirlpools(maxGroupId, isUsingWhirlpool, count, buffer, groupIds)
47+
val groupRevisions = decodeGroupRevisions(maxGroupId, count, groupIds, buffer)
48+
val groupFileIds = decodeGroupFileIds(maxGroupId, count, groupIds, buffer, protocol)
49+
val fileIds = decodeFileIds(maxGroupId, groupFileIds, count, groupIds, buffer, protocol)
50+
val fileNameHashes = decodeFileNameHashes(maxGroupId, groupFileIds, count, groupIds, buffer, isNamed)
6151

6252
val groups = hashMapOf<Int, Group>()
6353
(0 until count).forEach {
@@ -69,48 +59,62 @@ internal fun loadIndex(
6959
groupWhirlpools[groupId],
7060
groupRevisions[groupId],
7161
intArrayOf(),//TODO
72-
groupFiles(fileIds, fileNameHashes, groupTables[it], groupFileIds[it], it),
62+
decodeFiles(fileIds, fileNameHashes, groupTables[it], groupFileIds[it], it),
7363
groupTables[it]
7464
))
7565
}
76-
return Index(idxFile.id(), crc, whirlpool, compression, protocol, revision, isNamed, groups)
66+
return Index(idxFile.id(), decompressed.crc, whirlpool, decompressed.compression, protocol, revision, isNamed, groups)
67+
}
68+
69+
private fun decodeGroupIds(
70+
count: Int,
71+
buffer: ByteBuffer,
72+
protocol: Int
73+
): IntArray {
74+
val groupIds = IntArray(count)
75+
var offset = 0
76+
(0 until count).forEach {
77+
groupIds[it] = if (protocol >= 7) { buffer.readUnsignedIntShortSmart() } else { buffer.readUnsignedShort() }
78+
.let { id -> offset += id; offset }
79+
}
80+
return groupIds
7781
}
7882

79-
private fun groupFileIds(
80-
largestGroupId: Int,
83+
private fun decodeGroupFileIds(
84+
maxGroupId: Int,
8185
count: Int,
8286
groupIds: IntArray,
8387
buffer: ByteBuffer,
8488
protocol: Int
8589
): IntArray {
86-
val groupFileIds = IntArray(largestGroupId)
90+
val groupFileIds = IntArray(maxGroupId)
8791
(0 until count).forEach {
8892
groupFileIds[groupIds[it]] = if (protocol >= 7) buffer.readUnsignedIntShortSmart() else buffer.readUnsignedShort()
8993
}
9094
return groupFileIds
9195
}
9296

93-
private fun groupRevisions(
94-
largestGroupId: Int,
97+
private fun decodeGroupRevisions(
98+
maxGroupId: Int,
9599
count: Int,
96100
groupIds: IntArray,
97101
buffer: ByteBuffer
98102
): IntArray {
99-
val revisions = IntArray(largestGroupId)
103+
val revisions = IntArray(maxGroupId)
100104
(0 until count).forEach {
101105
revisions[groupIds[it]] = buffer.int
102106
}
103107
return revisions
104108
}
105109

106-
private fun groupWhirlpools(
107-
largestGroupId: Int,
110+
private fun decodeGroupWhirlpools(
111+
maxGroupId: Int,
108112
usesWhirlpool: Boolean,
109113
count: Int,
110114
buffer: ByteBuffer,
111115
groupIds: IntArray
112116
): Array<ByteArray> {
113-
val whirlpools = Array(largestGroupId) { ByteArray(64) }
117+
val whirlpools = Array(maxGroupId) { ByteArray(64) }
114118
if (usesWhirlpool.not()) return whirlpools
115119

116120
(0 until count).forEach {
@@ -121,27 +125,27 @@ private fun groupWhirlpools(
121125
return whirlpools
122126
}
123127

124-
private fun groupCrcs(
125-
largestGroupId: Int,
128+
private fun decodeGroupCrcs(
129+
maxGroupId: Int,
126130
count: Int,
127131
groupIds: IntArray,
128132
buffer: ByteBuffer
129133
): IntArray {
130-
val crcs = IntArray(largestGroupId)
134+
val crcs = IntArray(maxGroupId)
131135
(0 until count).forEach {
132136
crcs[groupIds[it]] = buffer.int
133137
}
134138
return crcs
135139
}
136140

137-
private fun groupNameHashes(
138-
largestGroupId: Int,
141+
private fun decodeGroupNameHashes(
142+
maxGroupId: Int,
139143
count: Int,
140144
isNamed: Boolean,
141145
groupIds: IntArray,
142146
buffer: ByteBuffer
143147
): IntArray {
144-
val nameHashes = IntArray(largestGroupId) { -1 }
148+
val nameHashes = IntArray(maxGroupId) { -1 }
145149
if (isNamed.not()) return nameHashes
146150

147151
(0 until count).forEach {
@@ -150,36 +154,36 @@ private fun groupNameHashes(
150154
return nameHashes
151155
}
152156

153-
private fun fileIds(
154-
largestGroupId: Int,
157+
private fun decodeFileIds(
158+
maxGroupId: Int,
155159
validFileIds: IntArray,
156160
count: Int,
157161
groupIds: IntArray,
158162
buffer: ByteBuffer,
159163
protocol: Int
160164
): Array<IntArray> {
161-
val fileIds = Array(largestGroupId) { IntArray(validFileIds[it]) }
165+
val fileIds = Array(maxGroupId) { IntArray(validFileIds[it]) }
162166
(0 until count).forEach {
163167
val groupId = groupIds[it]
164-
var currentFileId = 0
168+
var offset = 0
165169
(0 until validFileIds[groupId]).forEach { fileId ->
166170
if (protocol >= 7) { buffer.readUnsignedIntShortSmart() } else { buffer.readUnsignedShort() }
167-
.let { i -> currentFileId += i; currentFileId }
168-
.also { fileIds[groupId][fileId] = currentFileId }
171+
.let { i -> offset += i; offset }
172+
.also { fileIds[groupId][fileId] = offset }
169173
}
170174
}
171175
return fileIds
172176
}
173177

174-
private fun fileNameHashes(
175-
largestGroupId: Int,
178+
private fun decodeFileNameHashes(
179+
maxGroupId: Int,
176180
validFileIds: IntArray,
177181
count: Int,
178182
groupIds: IntArray,
179183
buffer: ByteBuffer,
180184
isNamed: Boolean
181185
): Array<IntArray> {
182-
val fileNameHashes = Array(largestGroupId) { IntArray(validFileIds[it]) }
186+
val fileNameHashes = Array(maxGroupId) { IntArray(validFileIds[it]) }
183187
if (isNamed) {
184188
(0 until count).forEach {
185189
val groupId = groupIds[it]
@@ -191,7 +195,7 @@ private fun fileNameHashes(
191195
return fileNameHashes
192196
}
193197

194-
internal fun groupFiles(
198+
internal fun decodeFiles(
195199
fileIds: Array<IntArray>,
196200
fileNameHashes: Array<IntArray>,
197201
groupReferenceTableData: ByteArray,

0 commit comments

Comments
 (0)