string table updates

master
Jordan Orelli 8 years ago
parent 4f20e1aac1
commit 227ebfd445

@ -0,0 +1,46 @@
package main
type intRing struct {
items []int
next int // index of the next available slot
full bool // whether or not we've filled the ring
base int // index in items of the virtual zero index
}
func newIntRing(size int) *intRing {
return &intRing{
items: make([]int, size),
}
}
func (r *intRing) add(i int) {
r.items[r.next] = i
r.next = r.incr(r.next)
if !r.full && r.next == 0 {
r.full = true
}
if r.full {
r.base = r.incr(r.base)
}
}
func (r *intRing) incr(i int) int {
if i == len(r.items)-1 {
return 0
}
return i + 1
}
func (r *intRing) at(i int) int {
idx := r.base + i
for idx >= len(r.items) {
idx -= len(r.items)
}
return r.items[idx]
}
func (r *intRing) clear() {
r.next = 0
r.full = false
r.base = 0
}

@ -40,13 +40,14 @@ func newStringTables() *stringTables {
}
type stringTable struct {
name string
entries []stringTableEntry
byteSize int
bitSize int // this is in the protobuf message but I don't know what it does.
}
func (s stringTable) String() string {
return fmt.Sprintf("{%s}", s.entries)
return fmt.Sprintf("{%s %s}", s.name, s.entries)
}
func (t *stringTable) create(br *bit.BufReader, entries int) {
@ -111,10 +112,10 @@ func (s *stringTables) handle(m proto.Message) {
case *dota.CSVCMsg_CreateStringTable:
prettyPrint(m)
s.handleCreate(v)
fmt.Println(s)
// fmt.Println(s)
case *dota.CSVCMsg_UpdateStringTable:
// prettyPrint(m)
// s.handleUpdate(v)
prettyPrint(m)
s.handleUpdate(v)
case *dota.CSVCMsg_ClearAllStringTables:
// prettyPrint(m)
case *dota.CDemoStringTables:
@ -125,9 +126,9 @@ func (s *stringTables) handle(m proto.Message) {
func (s *stringTables) handleCreate(m *dota.CSVCMsg_CreateStringTable) {
fmt.Printf("create %s\n", m.GetName())
if m.GetUserDataFixedSize() {
s.tables = append(s.tables, stringTable{byteSize: int(m.GetUserDataSize()), bitSize: int(m.GetUserDataSizeBits())})
s.tables = append(s.tables, stringTable{name: m.GetName(), byteSize: int(m.GetUserDataSize()), bitSize: int(m.GetUserDataSizeBits())})
} else {
s.tables = append(s.tables, stringTable{})
s.tables = append(s.tables, stringTable{name: m.GetName()})
}
s.idx[m.GetName()] = &s.tables[len(s.tables)-1]
table := &s.tables[len(s.tables)-1]
@ -154,22 +155,71 @@ func (s *stringTables) handleCreate(m *dota.CSVCMsg_CreateStringTable) {
s.br.SetSource(sd)
table.create(s.br, int(m.GetNumEntries()))
fmt.Println(table)
}
// type CSVCMsg_UpdateStringTable struct {
// TableId *int32
// NumChangedEntries *int32
// StringData []byte
// }
func (s *stringTables) handleUpdate(m *dota.CSVCMsg_UpdateStringTable) {
// hazard
table := s.tables[m.GetTableId()]
table := &s.tables[m.GetTableId()]
s.br.SetSource(m.GetStringData())
fmt.Printf("update %s\n", table.name)
table.update(s.br, int(m.GetNumChangedEntries()))
}
func (t *stringTable) update(br *bit.BufReader, changed int) {
var (
idx = -1
entry *stringTableEntry
)
h := newIntRing(32)
for i := 0; i < changed; i++ {
// sequential index flag should rarely be true in update
if bit.ReadBool(br) {
idx++
} else {
idx = int(bit.ReadVarInt(br)) + 1
}
h.add(idx)
for idx > len(t.entries)-1 {
t.entries = append(t.entries, stringTableEntry{})
}
entry = &t.entries[idx]
fmt.Printf("%s -> ", entry)
// key flag
if bit.ReadBool(br) {
// backreading flag
if bit.ReadBool(br) {
prev, pLen := h.at(int(br.ReadBits(5))), int(br.ReadBits(5))
if prev < len(t.entries) {
prevEntry := &t.entries[prev]
entry.key = prevEntry.key[:pLen] + bit.ReadString(br)
} else {
panic("backread error")
}
} else {
entry.key = bit.ReadString(br)
}
}
// value flag
if bit.ReadBool(br) {
if t.byteSize != 0 {
if entry.value == nil {
entry.value = make([]byte, t.byteSize)
}
} else {
size, _ := int(br.ReadBits(14)), br.ReadBits(3)
if len(entry.value) < size {
entry.value = make([]byte, size)
} else {
entry.value = entry.value[:size]
}
}
br.Read(entry.value)
}
fmt.Printf("%s\n", entry)
}
}

Loading…
Cancel
Save