2020-09-08 15:58:35 -04:00
|
|
|
package d2datautils
|
2020-01-26 00:39:13 -05:00
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
2020-07-18 18:07:38 -04:00
|
|
|
const (
|
|
|
|
bytesPerInt16 = 2
|
|
|
|
bytesPerInt32 = 4
|
|
|
|
bytesPerInt64 = 8
|
|
|
|
)
|
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
// StreamReader allows you to read data from a byte array in various formats
|
|
|
|
type StreamReader struct {
|
|
|
|
data []byte
|
|
|
|
position uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateStreamReader creates an instance of the stream reader
|
|
|
|
func CreateStreamReader(source []byte) *StreamReader {
|
|
|
|
result := &StreamReader{
|
|
|
|
data: source,
|
|
|
|
position: 0,
|
|
|
|
}
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPosition returns the current stream position
|
|
|
|
func (v *StreamReader) GetPosition() uint64 {
|
|
|
|
return v.position
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetSize returns the total size of the stream in bytes
|
|
|
|
func (v *StreamReader) GetSize() uint64 {
|
|
|
|
return uint64(len(v.data))
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetByte returns a byte from the stream
|
|
|
|
func (v *StreamReader) GetByte() byte {
|
|
|
|
result := v.data[v.position]
|
|
|
|
v.position++
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetUInt16 returns a uint16 word from the stream
|
|
|
|
func (v *StreamReader) GetUInt16() uint16 {
|
2020-07-18 18:07:38 -04:00
|
|
|
var result uint16
|
|
|
|
|
|
|
|
for offset := uint64(0); offset < bytesPerInt16; offset++ {
|
|
|
|
shift := uint8(bitsPerByte * offset)
|
|
|
|
result += uint16(v.data[v.position+offset]) << shift
|
|
|
|
}
|
|
|
|
|
|
|
|
v.position += bytesPerInt16
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetInt16 returns a int16 word from the stream
|
|
|
|
func (v *StreamReader) GetInt16() int16 {
|
2020-07-18 18:07:38 -04:00
|
|
|
var result int16
|
|
|
|
|
|
|
|
for offset := uint64(0); offset < bytesPerInt16; offset++ {
|
|
|
|
shift := uint8(bitsPerByte * offset)
|
|
|
|
result += int16(v.data[v.position+offset]) << shift
|
|
|
|
}
|
|
|
|
|
|
|
|
v.position += bytesPerInt16
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2020-07-08 09:16:56 -04:00
|
|
|
// SetPosition sets the stream position with the given position
|
2020-01-26 00:39:13 -05:00
|
|
|
func (v *StreamReader) SetPosition(newPosition uint64) {
|
|
|
|
v.position = newPosition
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetUInt32 returns a uint32 dword from the stream
|
|
|
|
func (v *StreamReader) GetUInt32() uint32 {
|
2020-07-18 18:07:38 -04:00
|
|
|
var result uint32
|
|
|
|
|
|
|
|
for offset := uint64(0); offset < bytesPerInt32; offset++ {
|
|
|
|
shift := uint8(bitsPerByte * offset)
|
|
|
|
result += uint32(v.data[v.position+offset]) << shift
|
|
|
|
}
|
|
|
|
|
|
|
|
v.position += bytesPerInt32
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetInt32 returns an int32 dword from the stream
|
|
|
|
func (v *StreamReader) GetInt32() int32 {
|
2020-07-18 18:07:38 -04:00
|
|
|
var result int32
|
|
|
|
|
|
|
|
for offset := uint64(0); offset < bytesPerInt32; offset++ {
|
|
|
|
shift := uint8(bitsPerByte * offset)
|
|
|
|
result += int32(v.data[v.position+offset]) << shift
|
|
|
|
}
|
|
|
|
|
|
|
|
v.position += bytesPerInt32
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetUint64 returns a uint64 qword from the stream
|
|
|
|
func (v *StreamReader) GetUint64() uint64 {
|
2020-07-18 18:07:38 -04:00
|
|
|
var result uint64
|
|
|
|
|
|
|
|
for offset := uint64(0); offset < bytesPerInt64; offset++ {
|
|
|
|
shift := uint8(bitsPerByte * offset)
|
|
|
|
result += uint64(v.data[v.position+offset]) << shift
|
|
|
|
}
|
|
|
|
|
|
|
|
v.position += bytesPerInt64
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetInt64 returns a uint64 qword from the stream
|
|
|
|
func (v *StreamReader) GetInt64() int64 {
|
2020-07-08 09:16:56 -04:00
|
|
|
return int64(v.GetUint64())
|
2020-01-26 00:39:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// ReadByte implements io.ByteReader
|
|
|
|
func (v *StreamReader) ReadByte() (byte, error) {
|
|
|
|
return v.GetByte(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadBytes reads multiple bytes
|
2020-06-20 21:07:36 -04:00
|
|
|
func (v *StreamReader) ReadBytes(count int) []byte {
|
|
|
|
result := v.data[v.position : v.position+uint64(count)]
|
|
|
|
v.position += uint64(count)
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-06-20 21:07:36 -04:00
|
|
|
return result
|
2020-01-26 00:39:13 -05:00
|
|
|
}
|
|
|
|
|
2020-07-08 09:16:56 -04:00
|
|
|
// SkipBytes moves the stream position forward by the given amount
|
2020-01-26 00:39:13 -05:00
|
|
|
func (v *StreamReader) SkipBytes(count int) {
|
|
|
|
v.position += uint64(count)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read implements io.Reader
|
|
|
|
func (v *StreamReader) Read(p []byte) (n int, err error) {
|
|
|
|
streamLength := v.GetSize()
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
for i := 0; ; i++ {
|
|
|
|
if v.GetPosition() >= streamLength {
|
|
|
|
return i, io.EOF
|
|
|
|
}
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
if i >= len(p) {
|
|
|
|
return i, nil
|
|
|
|
}
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-01-26 00:39:13 -05:00
|
|
|
p[i] = v.GetByte()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-08 09:16:56 -04:00
|
|
|
// EOF returns if the stream position is reached to the end of the data, or not
|
|
|
|
func (v *StreamReader) EOF() bool {
|
2020-01-26 00:39:13 -05:00
|
|
|
return v.position >= uint64(len(v.data))
|
|
|
|
}
|