This repository has been archived by the owner on May 21, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathstring_table_parser.go
107 lines (96 loc) · 2.48 KB
/
string_table_parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package yasha
import (
"math"
"github.com/davecgh/go-spew/spew"
)
const (
MaxNameLength = 0x400
KeyHistorySize = 32
)
type CSTObject interface {
GetStringData() []byte
GetNumEntries() int32
GetMaxEntries() int32
GetUserDataFixedSize() bool
GetUserDataSizeBits() int32
}
type USTObject interface {
GetStringData() []byte
GetNumChangedEntries() int32
}
func ParseCST(obj CSTObject) map[int]*StringTableItem {
return Parse(
obj.GetStringData(),
int(obj.GetNumEntries()),
int(obj.GetMaxEntries()),
int(obj.GetUserDataSizeBits()),
obj.GetUserDataFixedSize(),
)
}
func ParseUST(obj USTObject, meta *CacheItem) map[int]*StringTableItem {
return Parse(
obj.GetStringData(),
int(obj.GetNumChangedEntries()),
meta.MaxEntries,
meta.Bits,
meta.IsFixedSize,
)
}
func Parse(data []byte, numEntries, maxEntries, dataSizeBits int, dataFixedSize bool) map[int]*StringTableItem {
br := NewBitReader(data)
bitsPerIndex := int(math.Log(float64(maxEntries)) / math.Log(2))
keyHistory := make([]string, 0, KeyHistorySize)
result := map[int]*StringTableItem{}
mysteryFlag := br.ReadBoolean()
index := -1
nameBuf := ""
for len(result) < numEntries {
if br.ReadBoolean() {
index++
} else {
index = int(br.ReadUBits(bitsPerIndex))
}
nameBuf = ""
if br.ReadBoolean() {
if mysteryFlag && br.ReadBoolean() {
panic("mysteryFlag assertion failed!")
}
if br.ReadBoolean() {
basis := br.ReadUBits(5)
length := br.ReadUBits(5)
if int(basis) >= len(keyHistory) {
// spew.Dump("Ignoring invalid history index...", keyHistory, basis, length)
nameBuf += br.ReadStringN(MaxNameLength)
} else {
s := keyHistory[basis]
if int(length) > len(s) {
spew.Dump(s, length)
nameBuf += s + br.ReadStringN(int(MaxNameLength))
} else {
nameBuf += s[0:length] + br.ReadStringN(int(MaxNameLength-length))
}
}
} else {
nameBuf += br.ReadStringN(MaxNameLength)
}
if len(keyHistory) >= KeyHistorySize {
copy(keyHistory[0:], keyHistory[1:])
keyHistory[len(keyHistory)-1] = "" // or the zero value of T
keyHistory = keyHistory[:len(keyHistory)-1]
}
keyHistory = append(keyHistory, nameBuf)
}
value := []byte{}
if br.ReadBoolean() {
bitLength := 0
if dataFixedSize {
bitLength = dataSizeBits
} else {
bitLength = int(br.ReadUBits(14) * 8)
}
value = append(value, br.ReadBitsAsBytes(bitLength)...)
}
result[index] = &StringTableItem{Str: nameBuf, Data: value}
}
return result
}