package parser import ( "encoding/binary" "eq2emu/internal/common" "unsafe" ) type ParseContext struct { data []byte offset int version uint32 flags uint64 vars map[string]any arrayStack []int } func NewContext(data []byte, version uint32, flags uint64) *ParseContext { return &ParseContext{ data: data, version: version, flags: flags, vars: make(map[string]any), } } func (ctx *ParseContext) readUint8() uint8 { val := ctx.data[ctx.offset] ctx.offset++ return val } func (ctx *ParseContext) readUint16() uint16 { val := binary.LittleEndian.Uint16(ctx.data[ctx.offset:]) ctx.offset += 2 return val } func (ctx *ParseContext) readUint32() uint32 { val := binary.LittleEndian.Uint32(ctx.data[ctx.offset:]) ctx.offset += 4 return val } func (ctx *ParseContext) readOversizedUint8(threshold int) uint8 { if ctx.data[ctx.offset] == byte(threshold) { ctx.offset++ return ctx.readUint8() } return ctx.readUint8() } func (ctx *ParseContext) readOversizedUint16(threshold int) uint16 { if ctx.data[ctx.offset] == byte(threshold) { ctx.offset++ return ctx.readUint16() } return uint16(ctx.readUint8()) } func (ctx *ParseContext) readString8() string { length := ctx.readUint8() str := string(ctx.data[ctx.offset : ctx.offset+int(length)]) ctx.offset += int(length) return str } func (ctx *ParseContext) readString16() string { length := ctx.readUint16() str := string(ctx.data[ctx.offset : ctx.offset+int(length)]) ctx.offset += int(length) return str } func (ctx *ParseContext) readEQ2String8() common.EQ2String8 { size := ctx.readUint8() data := string(ctx.data[ctx.offset : ctx.offset+int(size)]) ctx.offset += int(size) return common.EQ2String8{ Size: size, Data: data, } } func (ctx *ParseContext) readEQ2String16() common.EQ2String16 { size := ctx.readUint16() data := string(ctx.data[ctx.offset : ctx.offset+int(size)]) ctx.offset += int(size) return common.EQ2String16{ Size: size, Data: data, } } func (ctx *ParseContext) readEQ2String32() common.EQ2String32 { size := ctx.readUint32() data := string(ctx.data[ctx.offset : ctx.offset+int(size)]) ctx.offset += int(size) return common.EQ2String32{ Size: size, Data: data, } } func (ctx *ParseContext) readEQ2Color() common.EQ2Color { return common.EQ2Color{ Red: ctx.readUint8(), Green: ctx.readUint8(), Blue: ctx.readUint8(), } } func (ctx *ParseContext) readEQ2Equipment() common.EQ2EquipmentItem { return common.EQ2EquipmentItem{ Type: ctx.readUint16(), Color: ctx.readEQ2Color(), Highlight: ctx.readEQ2Color(), } } func (ctx *ParseContext) readBytes(count int) []byte { val := make([]byte, count) copy(val, ctx.data[ctx.offset:ctx.offset+count]) ctx.offset += count return val } func (ctx *ParseContext) readFloat32() float32 { val := ctx.readUint32() return *(*float32)(unsafe.Pointer(&val)) } func (ctx *ParseContext) setVar(name string, value any) { ctx.vars[name] = value } func (ctx *ParseContext) pushArrayIndex(index int) { ctx.arrayStack = append(ctx.arrayStack, index) } func (ctx *ParseContext) popArrayIndex() { if len(ctx.arrayStack) > 0 { ctx.arrayStack = ctx.arrayStack[:len(ctx.arrayStack)-1] } }