mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
85 lines
1.8 KiB
Go
85 lines
1.8 KiB
Go
package aml
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"reflect"
|
|
"unsafe"
|
|
)
|
|
|
|
var (
|
|
errInvalidUnreadByte = errors.New("amlStreamReader: invalid use of UnreadByte")
|
|
)
|
|
|
|
type amlStreamReader struct {
|
|
offset uint32
|
|
data []byte
|
|
}
|
|
|
|
// Init sets up the reader so it can read up to dataLen bytes from the virtual
|
|
// memory address dataAddr. If a non-zero initialOffset is specified, it will
|
|
// be used as the current offset in the stream.
|
|
func (r *amlStreamReader) Init(dataAddr uintptr, dataLen, initialOffset uint32) {
|
|
// Overlay a byte slice on top of the memory block to be accessed.
|
|
r.data = *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
|
Len: int(dataLen),
|
|
Cap: int(dataLen),
|
|
Data: dataAddr,
|
|
}))
|
|
|
|
r.SetOffset(initialOffset)
|
|
}
|
|
|
|
// EOF returns true if the end of the stream has been reached.
|
|
func (r *amlStreamReader) EOF() bool {
|
|
return r.offset == uint32(len(r.data))
|
|
}
|
|
|
|
// ReadByte returns the next byte from the stream.
|
|
func (r *amlStreamReader) ReadByte() (byte, error) {
|
|
if r.EOF() {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
r.offset++
|
|
return r.data[r.offset-1], nil
|
|
}
|
|
|
|
// PeekByte returns the next byte from the stream without advancing the read pointer.
|
|
func (r *amlStreamReader) PeekByte() (byte, error) {
|
|
if r.EOF() {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
return r.data[r.offset], nil
|
|
}
|
|
|
|
// LastByte returns the last byte read off the stream
|
|
func (r *amlStreamReader) LastByte() (byte, error) {
|
|
if r.offset == 0 {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
return r.data[r.offset-1], nil
|
|
}
|
|
|
|
// UnreadByte moves back the read pointer by one byte.
|
|
func (r *amlStreamReader) UnreadByte() error {
|
|
if r.offset == 0 {
|
|
return errInvalidUnreadByte
|
|
}
|
|
|
|
r.offset--
|
|
return nil
|
|
}
|
|
|
|
// Offset returns the current offset.
|
|
func (r *amlStreamReader) Offset() uint32 {
|
|
return r.offset
|
|
}
|
|
|
|
// SetOffset sets the reader offset to the supplied value.
|
|
func (r *amlStreamReader) SetOffset(off uint32) {
|
|
r.offset = off
|
|
}
|