mirror of https://bitbucket.org/ausocean/av.git
Documented methods and standardized on 'buf' for parameter name.
This commit is contained in:
parent
f7de9526c8
commit
396c809424
348
rtmp/amf/amf.go
348
rtmp/amf/amf.go
|
@ -34,7 +34,7 @@ LICENSE
|
|||
Copyright (C) 2009-2010 Howard Chu
|
||||
*/
|
||||
|
||||
// amf implements Action Message Format (AMF) encoding and decoding.
|
||||
// Package amf implements Action Message Format (AMF) encoding and decoding.
|
||||
// See https://en.wikipedia.org/wiki/Action_Message_Format.
|
||||
package amf
|
||||
|
||||
|
@ -50,21 +50,21 @@ const (
|
|||
typeNumber = iota
|
||||
typeBoolean
|
||||
typeString
|
||||
TypeObject // ToDo: consider not exporting this
|
||||
typeMovieClip // reserved, not implemented
|
||||
TypeNull // ToDo: consider not exporting this
|
||||
TypeObject
|
||||
typeMovieClip
|
||||
TypeNull
|
||||
typeUndefined
|
||||
typeReference
|
||||
typeEcmaArray
|
||||
TypeObjectEnd // ToDo: consider not exporting this
|
||||
TypeObjectEnd
|
||||
typeStrictArray
|
||||
typeDate
|
||||
typeLongString
|
||||
typeUnsupported
|
||||
typeRecordset // reserved, not implemented
|
||||
typeRecordset
|
||||
typeXmlDoc
|
||||
typeTypedObject
|
||||
typeAvmplus // reserved, not implemented
|
||||
typeAvmplus
|
||||
typeInvalid = 0xff
|
||||
)
|
||||
|
||||
|
@ -93,157 +93,170 @@ var (
|
|||
ErrUnexpectedEnd = errors.New("amf: unexpected end")
|
||||
)
|
||||
|
||||
// Basic decoding funcions.
|
||||
func DecodeInt16(data []byte) uint16 {
|
||||
return uint16(binary.BigEndian.Uint16(data))
|
||||
// DecodeInt16 decodes a 16-bit integer.
|
||||
func DecodeInt16(buf []byte) uint16 {
|
||||
return uint16(binary.BigEndian.Uint16(buf))
|
||||
}
|
||||
|
||||
func DecodeInt24(data []byte) uint32 {
|
||||
return uint32(data[0])<<16 | uint32(data[1])<<8 | uint32(data[2])
|
||||
// DecodeInt24 decodes a 24-bit integer.
|
||||
func DecodeInt24(buf []byte) uint32 {
|
||||
return uint32(buf[0])<<16 | uint32(buf[1])<<8 | uint32(buf[2])
|
||||
}
|
||||
|
||||
func DecodeInt32(data []byte) uint32 {
|
||||
return uint32(binary.BigEndian.Uint32(data))
|
||||
// DecodeInt32 decodes a 32-bit integer.
|
||||
func DecodeInt32(buf []byte) uint32 {
|
||||
return uint32(binary.BigEndian.Uint32(buf))
|
||||
}
|
||||
|
||||
func DecodeString(data []byte) string {
|
||||
n := DecodeInt16(data)
|
||||
return string(data[2 : 2+n])
|
||||
// DecodeString decodes a string that is less than 2^16 bytes long.
|
||||
func DecodeString(buf []byte) string {
|
||||
n := DecodeInt16(buf)
|
||||
return string(buf[2 : 2+n])
|
||||
}
|
||||
|
||||
func DecodeLongString(data []byte) string {
|
||||
n := DecodeInt32(data)
|
||||
return string(data[2 : 2+n])
|
||||
// DecodeLongString decodes a long string.
|
||||
func DecodeLongString(buf []byte) string {
|
||||
n := DecodeInt32(buf)
|
||||
return string(buf[2 : 2+n])
|
||||
}
|
||||
|
||||
func DecodeNumber(data []byte) float64 {
|
||||
return math.Float64frombits(binary.BigEndian.Uint64(data))
|
||||
// DecodeNumber decodes a 64-bit floating-point number.
|
||||
func DecodeNumber(buf []byte) float64 {
|
||||
return math.Float64frombits(binary.BigEndian.Uint64(buf))
|
||||
}
|
||||
|
||||
func DecodeBoolean(data []byte) bool {
|
||||
return data[0] != 0
|
||||
// DecodeBoolean decodes a boolean.
|
||||
func DecodeBoolean(buf []byte) bool {
|
||||
return buf[0] != 0
|
||||
}
|
||||
|
||||
// Basic encoding functions.
|
||||
func EncodeInt24(dst []byte, val int32) ([]byte, error) {
|
||||
if len(dst) < 3 {
|
||||
// EncodeInt24 encodes a 24-bit integer.
|
||||
func EncodeInt24(buf []byte, val int32) ([]byte, error) {
|
||||
if len(buf) < 3 {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
dst[0] = byte(val >> 16)
|
||||
dst[1] = byte(val >> 8)
|
||||
dst[2] = byte(val)
|
||||
if len(dst) == 3 {
|
||||
buf[0] = byte(val >> 16)
|
||||
buf[1] = byte(val >> 8)
|
||||
buf[2] = byte(val)
|
||||
if len(buf) == 3 {
|
||||
return nil, ErrEndOfBuffer
|
||||
}
|
||||
return dst[3:], nil
|
||||
return buf[3:], nil
|
||||
}
|
||||
|
||||
func EncodeInt32(dst []byte, val int32) ([]byte, error) {
|
||||
if len(dst) < 4 {
|
||||
// EncodeInt32 encodes a 32-bit integer.
|
||||
func EncodeInt32(buf []byte, val int32) ([]byte, error) {
|
||||
if len(buf) < 4 {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
binary.BigEndian.PutUint32(dst, uint32(val))
|
||||
if len(dst) == 4 {
|
||||
binary.BigEndian.PutUint32(buf, uint32(val))
|
||||
if len(buf) == 4 {
|
||||
return nil, ErrEndOfBuffer
|
||||
}
|
||||
return dst[4:], nil
|
||||
return buf[4:], nil
|
||||
}
|
||||
|
||||
func EncodeString(dst []byte, val string) ([]byte, error) {
|
||||
// EncodeString encodes a string.
|
||||
func EncodeString(buf []byte, val string) ([]byte, error) {
|
||||
const typeSize = 1
|
||||
if len(val) < 65536 && len(val)+typeSize+binary.Size(int16(0)) > len(dst) {
|
||||
if len(val) < 65536 && len(val)+typeSize+binary.Size(int16(0)) > len(buf) {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
|
||||
if len(val)+typeSize+binary.Size(int32(0)) > len(dst) {
|
||||
if len(val)+typeSize+binary.Size(int32(0)) > len(buf) {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
|
||||
if len(val) < 65536 {
|
||||
dst[0] = typeString
|
||||
dst = dst[1:]
|
||||
binary.BigEndian.PutUint16(dst[:2], uint16(len(val)))
|
||||
dst = dst[2:]
|
||||
copy(dst, val)
|
||||
if len(dst) == len(val) {
|
||||
buf[0] = typeString
|
||||
buf = buf[1:]
|
||||
binary.BigEndian.PutUint16(buf[:2], uint16(len(val)))
|
||||
buf = buf[2:]
|
||||
copy(buf, val)
|
||||
if len(buf) == len(val) {
|
||||
return nil, ErrEndOfBuffer
|
||||
}
|
||||
return dst[len(val):], nil
|
||||
return buf[len(val):], nil
|
||||
}
|
||||
|
||||
dst[0] = typeLongString
|
||||
dst = dst[1:]
|
||||
binary.BigEndian.PutUint32(dst[:4], uint32(len(val)))
|
||||
dst = dst[4:]
|
||||
copy(dst, val)
|
||||
if len(dst) == len(val) {
|
||||
buf[0] = typeLongString
|
||||
buf = buf[1:]
|
||||
binary.BigEndian.PutUint32(buf[:4], uint32(len(val)))
|
||||
buf = buf[4:]
|
||||
copy(buf, val)
|
||||
if len(buf) == len(val) {
|
||||
return nil, ErrEndOfBuffer
|
||||
}
|
||||
return dst[len(val):], nil
|
||||
return buf[len(val):], nil
|
||||
}
|
||||
|
||||
func EncodeNumber(dst []byte, val float64) ([]byte, error) {
|
||||
if len(dst) < 9 {
|
||||
// EncodeNumber encodes a 64-bit floating-point number.
|
||||
func EncodeNumber(buf []byte, val float64) ([]byte, error) {
|
||||
if len(buf) < 9 {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
dst[0] = typeNumber
|
||||
dst = dst[1:]
|
||||
binary.BigEndian.PutUint64(dst, math.Float64bits(val))
|
||||
return dst[8:], nil
|
||||
buf[0] = typeNumber
|
||||
buf = buf[1:]
|
||||
binary.BigEndian.PutUint64(buf, math.Float64bits(val))
|
||||
return buf[8:], nil
|
||||
}
|
||||
|
||||
func EncodeBoolean(dst []byte, val bool) ([]byte, error) {
|
||||
if len(dst) < 2 {
|
||||
// EncodeBoolean encodes a boolean.
|
||||
func EncodeBoolean(buf []byte, val bool) ([]byte, error) {
|
||||
if len(buf) < 2 {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
dst[0] = typeBoolean
|
||||
buf[0] = typeBoolean
|
||||
if val {
|
||||
dst[1] = 1
|
||||
buf[1] = 1
|
||||
}
|
||||
if len(dst) == 2 {
|
||||
if len(buf) == 2 {
|
||||
return nil, ErrEndOfBuffer
|
||||
}
|
||||
return dst[2:], nil
|
||||
return buf[2:], nil
|
||||
|
||||
}
|
||||
|
||||
func EncodeNamedString(dst []byte, key, val string) ([]byte, error) {
|
||||
if 2+len(key) > len(dst) {
|
||||
// EncodeNamedString encodes a named string, where key is the name and val is the string value.
|
||||
func EncodeNamedString(buf []byte, key, val string) ([]byte, error) {
|
||||
if 2+len(key) > len(buf) {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
binary.BigEndian.PutUint16(dst[:2], uint16(len(key)))
|
||||
dst = dst[2:]
|
||||
copy(dst, key)
|
||||
if len(key) == len(dst) {
|
||||
binary.BigEndian.PutUint16(buf[:2], uint16(len(key)))
|
||||
buf = buf[2:]
|
||||
copy(buf, key)
|
||||
if len(key) == len(buf) {
|
||||
return nil, ErrEndOfBuffer
|
||||
}
|
||||
return EncodeString(dst[len(key):], val)
|
||||
return EncodeString(buf[len(key):], val)
|
||||
}
|
||||
|
||||
func EncodeNamedNumber(dst []byte, key string, val float64) ([]byte, error) {
|
||||
if 2+len(key) > len(dst) {
|
||||
// EncodeNamedNumber encodes a named number, where key is the name and val is the number value.
|
||||
func EncodeNamedNumber(buf []byte, key string, val float64) ([]byte, error) {
|
||||
if 2+len(key) > len(buf) {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
binary.BigEndian.PutUint16(dst[:2], uint16(len(key)))
|
||||
dst = dst[2:]
|
||||
copy(dst, key)
|
||||
if len(key) == len(dst) {
|
||||
binary.BigEndian.PutUint16(buf[:2], uint16(len(key)))
|
||||
buf = buf[2:]
|
||||
copy(buf, key)
|
||||
if len(key) == len(buf) {
|
||||
return nil, ErrEndOfBuffer
|
||||
}
|
||||
return EncodeNumber(dst[len(key):], val)
|
||||
return EncodeNumber(buf[len(key):], val)
|
||||
}
|
||||
|
||||
func EncodeNamedBoolean(dst []byte, key string, val bool) ([]byte, error) {
|
||||
if 2+len(key) > len(dst) {
|
||||
// EncodeNamedNumber encodes a named boolean, where key is the name and val is the booelean value.
|
||||
func EncodeNamedBoolean(buf []byte, key string, val bool) ([]byte, error) {
|
||||
if 2+len(key) > len(buf) {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
binary.BigEndian.PutUint16(dst[:2], uint16(len(key)))
|
||||
dst = dst[2:]
|
||||
copy(dst, key)
|
||||
if len(key) == len(dst) {
|
||||
binary.BigEndian.PutUint16(buf[:2], uint16(len(key)))
|
||||
buf = buf[2:]
|
||||
copy(buf, key)
|
||||
if len(key) == len(buf) {
|
||||
return nil, ErrEndOfBuffer
|
||||
}
|
||||
return EncodeBoolean(dst[len(key):], val)
|
||||
return EncodeBoolean(buf[len(key):], val)
|
||||
}
|
||||
|
||||
// Property functions.
|
||||
|
@ -272,114 +285,114 @@ func PropGetObject(prop *Property, obj *Object) {
|
|||
}
|
||||
|
||||
// PropEncode encodes a property.
|
||||
func PropEncode(p *Property, dst []byte) ([]byte, error) {
|
||||
func PropEncode(p *Property, buf []byte) ([]byte, error) {
|
||||
if p.dtype == typeInvalid {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
|
||||
if p.dtype != TypeNull && len(p.name)+2+1 >= len(dst) {
|
||||
if p.dtype != TypeNull && len(p.name)+2+1 >= len(buf) {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
|
||||
if p.dtype != TypeNull && len(p.name) != 0 {
|
||||
binary.BigEndian.PutUint16(dst[:2], uint16(len(p.name)))
|
||||
dst = dst[2:]
|
||||
copy(dst, p.name)
|
||||
dst = dst[len(p.name):]
|
||||
binary.BigEndian.PutUint16(buf[:2], uint16(len(p.name)))
|
||||
buf = buf[2:]
|
||||
copy(buf, p.name)
|
||||
buf = buf[len(p.name):]
|
||||
}
|
||||
|
||||
var err error
|
||||
switch p.dtype {
|
||||
case typeNumber:
|
||||
dst, err = EncodeNumber(dst, p.number)
|
||||
buf, err = EncodeNumber(buf, p.number)
|
||||
case typeBoolean:
|
||||
dst, err = EncodeBoolean(dst, p.number != 0)
|
||||
buf, err = EncodeBoolean(buf, p.number != 0)
|
||||
case typeString:
|
||||
dst, err = EncodeString(dst, p.str)
|
||||
buf, err = EncodeString(buf, p.str)
|
||||
case TypeNull:
|
||||
if len(dst) < 2 {
|
||||
if len(buf) < 2 {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
dst[0] = TypeNull
|
||||
dst = dst[1:]
|
||||
buf[0] = TypeNull
|
||||
buf = buf[1:]
|
||||
case TypeObject:
|
||||
dst, err = Encode(&p.obj, dst)
|
||||
buf, err = Encode(&p.obj, buf)
|
||||
case typeEcmaArray:
|
||||
dst, err = EncodeEcmaArray(&p.obj, dst)
|
||||
buf, err = EncodeEcmaArray(&p.obj, buf)
|
||||
case typeStrictArray:
|
||||
dst, err = EncodeArray(&p.obj, dst)
|
||||
buf, err = EncodeArray(&p.obj, buf)
|
||||
default:
|
||||
dst, err = nil, ErrInvalidType
|
||||
buf, err = nil, ErrInvalidType
|
||||
}
|
||||
return dst, err
|
||||
return buf, err
|
||||
}
|
||||
|
||||
// PropDecode decodes a property, returning the number of bytes consumed from the supplied buffer.
|
||||
func PropDecode(prop *Property, data []byte, decodeName bool) (int, error) {
|
||||
func PropDecode(prop *Property, buf []byte, decodeName bool) (int, error) {
|
||||
prop.name = ""
|
||||
|
||||
sz := len(data)
|
||||
if len(data) == 0 {
|
||||
sz := len(buf)
|
||||
if len(buf) == 0 {
|
||||
return 0, ErrEndOfBuffer
|
||||
}
|
||||
|
||||
if decodeName {
|
||||
if len(data) < 4 {
|
||||
if len(buf) < 4 {
|
||||
return 0, ErrShortBuffer
|
||||
}
|
||||
n := DecodeInt16(data[:2])
|
||||
if int(n) > len(data)-2 {
|
||||
n := DecodeInt16(buf[:2])
|
||||
if int(n) > len(buf)-2 {
|
||||
return 0, ErrDecodingName
|
||||
}
|
||||
|
||||
prop.name = DecodeString(data)
|
||||
data = data[2+n:]
|
||||
prop.name = DecodeString(buf)
|
||||
buf = buf[2+n:]
|
||||
}
|
||||
|
||||
if len(data) == 0 {
|
||||
if len(buf) == 0 {
|
||||
return 0, ErrEndOfBuffer
|
||||
}
|
||||
|
||||
prop.dtype = uint8(data[0])
|
||||
data = data[1:]
|
||||
prop.dtype = uint8(buf[0])
|
||||
buf = buf[1:]
|
||||
|
||||
switch prop.dtype {
|
||||
case typeNumber:
|
||||
if len(data) < 8 {
|
||||
if len(buf) < 8 {
|
||||
return 0, ErrShortBuffer
|
||||
}
|
||||
prop.number = DecodeNumber(data[:8])
|
||||
data = data[8:]
|
||||
prop.number = DecodeNumber(buf[:8])
|
||||
buf = buf[8:]
|
||||
|
||||
case typeBoolean:
|
||||
return 0, ErrUnimplemented
|
||||
|
||||
case typeString:
|
||||
n := DecodeInt16(data[:2])
|
||||
if len(data) < int(n+2) {
|
||||
n := DecodeInt16(buf[:2])
|
||||
if len(buf) < int(n+2) {
|
||||
return 0, ErrShortBuffer
|
||||
}
|
||||
prop.str = DecodeString(data)
|
||||
data = data[2+n:]
|
||||
prop.str = DecodeString(buf)
|
||||
buf = buf[2+n:]
|
||||
|
||||
case TypeObject:
|
||||
n, err := Decode(&prop.obj, data, true)
|
||||
n, err := Decode(&prop.obj, buf, true)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
data = data[n:]
|
||||
buf = buf[n:]
|
||||
|
||||
|
||||
case TypeNull, typeUndefined, typeUnsupported:
|
||||
prop.dtype = TypeNull
|
||||
|
||||
case typeEcmaArray:
|
||||
data = data[4:]
|
||||
n, err := Decode(&prop.obj, data, true)
|
||||
buf = buf[4:]
|
||||
n, err := Decode(&prop.obj, buf, true)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
data = data[n:]
|
||||
buf = buf[n:]
|
||||
|
||||
case TypeObjectEnd:
|
||||
return 0, ErrUnexpectedEnd
|
||||
|
@ -388,102 +401,107 @@ func PropDecode(prop *Property, data []byte, decodeName bool) (int, error) {
|
|||
return 0, ErrUnimplemented
|
||||
}
|
||||
|
||||
return sz - len(data), nil
|
||||
return sz - len(buf), nil
|
||||
}
|
||||
|
||||
// Encode serializes an Object into its AMF representation.
|
||||
func Encode(obj *Object, dst []byte) ([]byte, error) {
|
||||
if len(dst) < 5 {
|
||||
// Encode encodes an Object into its AMF representation.
|
||||
func Encode(obj *Object, buf []byte) ([]byte, error) {
|
||||
if len(buf) < 5 {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
|
||||
dst[0] = TypeObject
|
||||
dst = dst[1:]
|
||||
buf[0] = TypeObject
|
||||
buf = buf[1:]
|
||||
|
||||
for i := 0; i < len(obj.Props); i++ {
|
||||
var err error
|
||||
dst, err = PropEncode(&obj.Props[i], dst)
|
||||
buf, err = PropEncode(&obj.Props[i], buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(dst) < 4 {
|
||||
if len(buf) < 4 {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
return EncodeInt24(dst, TypeObjectEnd)
|
||||
return EncodeInt24(buf, TypeObjectEnd)
|
||||
}
|
||||
|
||||
func EncodeEcmaArray(obj *Object, dst []byte) ([]byte, error) {
|
||||
if len(dst) < 5 {
|
||||
// EncodeEcmaArray encodes an ECMA array.
|
||||
func EncodeEcmaArray(obj *Object, buf []byte) ([]byte, error) {
|
||||
if len(buf) < 5 {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
|
||||
dst[0] = typeEcmaArray
|
||||
dst = dst[1:]
|
||||
binary.BigEndian.PutUint32(dst[:4], uint32(len(obj.Props)))
|
||||
dst = dst[4:]
|
||||
buf[0] = typeEcmaArray
|
||||
buf = buf[1:]
|
||||
binary.BigEndian.PutUint32(buf[:4], uint32(len(obj.Props)))
|
||||
buf = buf[4:]
|
||||
|
||||
for i := 0; i < len(obj.Props); i++ {
|
||||
var err error
|
||||
dst, err = PropEncode(&obj.Props[i], dst)
|
||||
buf, err = PropEncode(&obj.Props[i], buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(dst) < 4 {
|
||||
if len(buf) < 4 {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
return EncodeInt24(dst, TypeObjectEnd)
|
||||
return EncodeInt24(buf, TypeObjectEnd)
|
||||
}
|
||||
|
||||
func EncodeArray(obj *Object, dst []byte) ([]byte, error) {
|
||||
if len(dst) < 5 {
|
||||
// EncodeArray encodes an array.
|
||||
func EncodeArray(obj *Object, buf []byte) ([]byte, error) {
|
||||
if len(buf) < 5 {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
|
||||
dst[0] = typeStrictArray
|
||||
dst = dst[1:]
|
||||
binary.BigEndian.PutUint32(dst[:4], uint32(len(obj.Props)))
|
||||
dst = dst[4:]
|
||||
buf[0] = typeStrictArray
|
||||
buf = buf[1:]
|
||||
binary.BigEndian.PutUint32(buf[:4], uint32(len(obj.Props)))
|
||||
buf = buf[4:]
|
||||
|
||||
for i := 0; i < len(obj.Props); i++ {
|
||||
var err error
|
||||
dst, err = PropEncode(&obj.Props[i], dst)
|
||||
buf, err = PropEncode(&obj.Props[i], buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return dst, nil
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func Decode(obj *Object, data []byte, decodeName bool) (int, error) {
|
||||
sz := len(data)
|
||||
// Decode decodes an object. Property names are only decoded if decodeName is true.
|
||||
func Decode(obj *Object, buf []byte, decodeName bool) (int, error) {
|
||||
sz := len(buf)
|
||||
|
||||
obj.Props = obj.Props[:0]
|
||||
for len(data) != 0 {
|
||||
if len(data) >= 3 && DecodeInt24(data[:3]) == TypeObjectEnd {
|
||||
data = data[3:]
|
||||
break
|
||||
for len(buf) != 0 {
|
||||
if len(buf) >= 3 && DecodeInt24(buf[:3]) == TypeObjectEnd {
|
||||
buf = buf[3:]
|
||||
break
|
||||
}
|
||||
|
||||
var prop Property
|
||||
n, err := PropDecode(&prop, data, decodeName)
|
||||
n, err := PropDecode(&prop, buf, decodeName)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
data = data[n:]
|
||||
buf = buf[n:]
|
||||
obj.Props = append(obj.Props, prop)
|
||||
}
|
||||
|
||||
return sz - len(data), nil
|
||||
return sz - len(buf), nil
|
||||
}
|
||||
|
||||
func GetProp(obj *Object, name string, idx int32) *Property {
|
||||
// GetProp returns an object's property, either by its index when idx is non-negative, or by its name when name otherwise.
|
||||
// If the matching property is not found nil is returned.
|
||||
func GetProp(obj *Object, name string, idx int) *Property {
|
||||
if idx >= 0 {
|
||||
if idx < int32(len(obj.Props)) {
|
||||
if idx < len(obj.Props) {
|
||||
return &obj.Props[idx]
|
||||
}
|
||||
} else {
|
||||
|
@ -493,5 +511,5 @@ func GetProp(obj *Object, name string, idx int32) *Property {
|
|||
}
|
||||
}
|
||||
}
|
||||
return &Property{}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue