From 96cf3791921b0f0cd8b4e9ed66378732ca3d0bf9 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Sat, 1 Oct 2016 15:15:14 -0400 Subject: [PATCH] uint64 fixed is a thing --- bit/decode.go | 64 ++++++++--------------- ent/array.go | 20 +++++-- ent/atoms.go | 132 +++++++++++++++++++++++++++++++++++++++++++---- ent/env.go | 3 ++ ent/generic.go | 3 +- ent/selection.go | 3 +- 6 files changed, 167 insertions(+), 58 deletions(-) diff --git a/bit/decode.go b/bit/decode.go index 6edc6b6..4478c2c 100644 --- a/bit/decode.go +++ b/bit/decode.go @@ -61,62 +61,42 @@ func ReadUBitVarFP(r Reader) uint64 { // in little-endian order. The most-significant bit of each byte represents a // continuation bit. func ReadVarInt(r Reader) uint64 { - var ( - x uint64 - b uint64 - shift uint - ) - for ; shift < 64; shift += 7 { - b = r.ReadBits(8) + var x uint64 + var s uint + for i := 0; ; i++ { + b := r.ReadBits(8) if r.Err() != nil { return 0 } - x |= b & 0x7f << shift - if b&0x80 == 0 { - return x + if b < 0x80 { + if i > 9 || i == 9 && b > 1 { + panic("varint overflow") + } + return x | b< 4 || i == 4 && b > 0xf { + panic("varint32 overflow") + } + return x | uint32(b)< 1<<32-1 { - return fmt.Errorf("uint32 overflow: %d", u) - } - *v = uint32_v(u) + *v = uint32_v(bit.ReadVarInt32(r)) return r.Err() } @@ -121,7 +117,7 @@ type uint64_v uint64 func (v uint64_v) tÿpe() tÿpe { return uint64_t } func (v *uint64_v) read(r bit.Reader) error { - *v = uint64_v(bit.ReadVarInt(r)) + *v = uint64_v(bit.ReadVarInt32(r)) return r.Err() } @@ -129,6 +125,31 @@ func (v uint64_v) String() string { return strconv.FormatUint(uint64(v), 10) } +// ------------------------------------------------------------------------------ +// uint64fixed +// +// (a uint64 value that is always represented on the wire with 64 bits) +// ------------------------------------------------------------------------------ + +var uint64fixed_t = &typeLiteral{ + name: "uint64fixed", + newFn: func() value { + return new(uint64fixed_v) + }, +} + +type uint64fixed_v uint64 + +func (v uint64fixed_v) tÿpe() tÿpe { return uint64fixed_t } +func (v *uint64fixed_v) read(r bit.Reader) error { + *v = uint64fixed_v(r.ReadBits(64)) + return r.Err() +} + +func (v uint64fixed_v) String() string { + return strconv.FormatUint(uint64(v), 10) +} + // ------------------------------------------------------------------------------ // int8 // ------------------------------------------------------------------------------ @@ -153,6 +174,30 @@ func (v int8_v) String() string { return strconv.FormatInt(int64(v), 10) } +// ------------------------------------------------------------------------------ +// int16 +// ------------------------------------------------------------------------------ + +var int16_t = &typeLiteral{ + name: "int16", + newFn: func() value { + return new(int16_v) + }, +} + +type int16_v int16 + +func (v int16_v) tÿpe() tÿpe { return int16_t } +func (v *int16_v) read(r bit.Reader) error { + // TODO: bounds check here? + *v = int16_v(bit.ReadZigZag32(r)) + return r.Err() +} + +func (v int16_v) String() string { + return strconv.FormatInt(int64(v), 10) +} + // ------------------------------------------------------------------------------ // int32 // ------------------------------------------------------------------------------ @@ -176,6 +221,29 @@ func (v int32_v) String() string { return strconv.FormatInt(int64(v), 10) } +// ------------------------------------------------------------------------------ +// int64 +// ------------------------------------------------------------------------------ + +var int64_t = &typeLiteral{ + name: "int64", + newFn: func() value { + return new(int64_v) + }, +} + +type int64_v int64 + +func (v int64_v) tÿpe() tÿpe { return int64_t } +func (v *int64_v) read(r bit.Reader) error { + *v = int64_v(bit.ReadZigZag(r)) + return r.Err() +} + +func (v int64_v) String() string { + return strconv.FormatInt(int64(v), 10) +} + // ------------------------------------------------------------------------------ // CUtlStringToken // @@ -229,24 +297,70 @@ func (c color) String() string { return fmt.Sprintf("#%x%x%x%x", c.r, c.g, c.b, c.a) } +// ------------------------------------------------------------------------------ +// CUtlSymbolLarge +// ------------------------------------------------------------------------------ + +var cutl_string_t = typeLiteral{ + name: "CUtlSymbolLarge", + newFn: func() value { + return new(cutl_string_v) + }, +} + +type cutl_string_v string + +func (v cutl_string_v) tÿpe() tÿpe { return cutl_string_t } +func (v cutl_string_v) String() string { return string(v) } +func (v *cutl_string_v) read(r bit.Reader) error { + *v = cutl_string_v(bit.ReadString(r)) + return r.Err() +} + var atom_types = []tÿpe{ bool_t, uint8_t, uint16_t, uint32_t, - uint64_t, int8_t, + int16_t, int32_t, + int64_t, stringToken_t, color_t, + cutl_string_t, } func atomType(spec *typeSpec, env *Env) tÿpe { for _, t := range atom_types { if t.typeName() == spec.typeName { Debug.Printf(" atom type: %s", t.typeName()) + if spec.bits != 0 { + return typeError("spec can't be atom type: has bit specification: %v", spec) + } + if spec.encoder != "" { + return typeError("spec can't be atom type: has encoder specification: %v", spec) + } + if spec.flags != 0 { + return typeError("spec can't be atom type: has flags: %v", spec) + } + if spec.high != 0 { + return typeError("spec can't be atom type: has high value constraint: %v", spec) + } + if spec.low != 0 { + return typeError("spec can't be atom type: has low value constraint: %v", spec) + } + if spec.serializer != "" { + return typeError("spec can't be atom type: has serializer: %v", spec) + } return t } } + if spec.typeName == "uint64" { + if spec.encoder == "fixed64" { + return uint64fixed_t + } + return uint64_t + } return nil } diff --git a/ent/env.go b/ent/env.go index ca9ab38..37ea8bd 100644 --- a/ent/env.go +++ b/ent/env.go @@ -63,6 +63,9 @@ func (e *Env) mergeSendTables(m *dota.CDemoSendTables) error { if err != nil { return wrap(err, "unable to get serializers in sendtables") } + for i, s := range flat.GetSymbols() { + Debug.Printf("symbol %d: %s", i, s) + } e.symbols = symbolTable(flat.GetSymbols()) e.stubClasses(flat) if err := e.parseFields(flat); err != nil { diff --git a/ent/generic.go b/ent/generic.go index ea80720..c7edfe8 100644 --- a/ent/generic.go +++ b/ent/generic.go @@ -42,10 +42,10 @@ func genericName(name string) ([2]string, error) { for i, r := range runes { if r == '<' { if depth == 0 { + b_start = i out[0] = strings.TrimSpace(string(runes[0:i])) } depth++ - b_start = i } if r == '>' { depth-- @@ -89,6 +89,7 @@ func (v *cutl_vector) tÿpe() tÿpe { return v.t } func (v *cutl_vector) read(r bit.Reader) error { count := bit.ReadVarInt32(r) + Debug.Printf("allocating cutl_vector of size %d with element type %s", count, v.t.elem.typeName()) v.slots = make([]value, count) return r.Err() } diff --git a/ent/selection.go b/ent/selection.go index 0f5f620..c868d5d 100644 --- a/ent/selection.go +++ b/ent/selection.go @@ -30,11 +30,12 @@ func (s selection) fillSlotsIter(offset int, dest slotted, path string, r bit.Re } switch s.count - offset { case 1: + old := dest.getSlotValue(slot) v := dest.slotType(slot).nü() + Debug.Printf("%v %s.%s (%s) %v read", s, path, dest.slotName(slot), dest.slotType(slot).typeName(), old) if err := v.read(r); err != nil { return fmt.Errorf("unable to fill selection %v for %s.%s (%s): %v", s, path, dest.slotName(slot), dest.slotType(slot).typeName(), err) } - old := dest.getSlotValue(slot) dest.setSlotValue(slot, v) Debug.Printf("%v %s.%s (%s) %v -> %v", s, path, dest.slotName(slot), dest.slotType(slot).typeName(), old, v) return nil