Restored more optimised array type conversions for a few select 1D-slice types.
Results of calls to the reflect lib are now stored as local variables for small performance gains.
This commit is contained in:
+136
-52
@@ -31,56 +31,110 @@ func (dst *Float4Array) Set(src interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
value := reflect.ValueOf(src)
|
||||
if !value.IsValid() || value.IsZero() {
|
||||
*dst = Float4Array{Status: Null}
|
||||
return nil
|
||||
}
|
||||
switch value := src.(type) {
|
||||
|
||||
dimensions, elementsLength, ok := findDimensionsFromValue(reflect.ValueOf(src), nil, 0)
|
||||
if !ok {
|
||||
return errors.Errorf("cannot find dimensions of %v for Float4Array", src)
|
||||
}
|
||||
if elementsLength == 0 {
|
||||
*dst = Float4Array{Status: Present}
|
||||
return nil
|
||||
}
|
||||
if len(dimensions) == 0 {
|
||||
if originalSrc, ok := underlyingSliceType(src); ok {
|
||||
return dst.Set(originalSrc)
|
||||
}
|
||||
return errors.Errorf("cannot convert %v to Float4Array", src)
|
||||
}
|
||||
|
||||
*dst = Float4Array{
|
||||
Elements: make([]Float4, elementsLength),
|
||||
Dimensions: dimensions,
|
||||
Status: Present,
|
||||
}
|
||||
elementCount, err := dst.setRecursive(reflect.ValueOf(src), 0, 0)
|
||||
if err != nil {
|
||||
// Maybe the target was one dimension too far, try again:
|
||||
if len(dst.Dimensions) > 1 {
|
||||
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
|
||||
elementsLength = 0
|
||||
for _, dim := range dst.Dimensions {
|
||||
if elementsLength == 0 {
|
||||
elementsLength = int(dim.Length)
|
||||
} else {
|
||||
elementsLength *= int(dim.Length)
|
||||
case []float32:
|
||||
if value == nil {
|
||||
*dst = Float4Array{Status: Null}
|
||||
} else if len(value) == 0 {
|
||||
*dst = Float4Array{Status: Present}
|
||||
} else {
|
||||
elements := make([]Float4, len(value))
|
||||
for i := range value {
|
||||
if err := elements[i].Set(value[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
dst.Elements = make([]Float4, elementsLength)
|
||||
elementCount, err = dst.setRecursive(reflect.ValueOf(src), 0, 0)
|
||||
if err != nil {
|
||||
*dst = Float4Array{
|
||||
Elements: elements,
|
||||
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
|
||||
Status: Present,
|
||||
}
|
||||
}
|
||||
|
||||
case []*float32:
|
||||
if value == nil {
|
||||
*dst = Float4Array{Status: Null}
|
||||
} else if len(value) == 0 {
|
||||
*dst = Float4Array{Status: Present}
|
||||
} else {
|
||||
elements := make([]Float4, len(value))
|
||||
for i := range value {
|
||||
if err := elements[i].Set(value[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*dst = Float4Array{
|
||||
Elements: elements,
|
||||
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
|
||||
Status: Present,
|
||||
}
|
||||
}
|
||||
|
||||
case []Float4:
|
||||
if value == nil {
|
||||
*dst = Float4Array{Status: Null}
|
||||
} else if len(value) == 0 {
|
||||
*dst = Float4Array{Status: Present}
|
||||
} else {
|
||||
*dst = Float4Array{
|
||||
Elements: value,
|
||||
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
|
||||
Status: Present,
|
||||
}
|
||||
}
|
||||
default:
|
||||
reflectedValue := reflect.ValueOf(src)
|
||||
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
|
||||
*dst = Float4Array{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
|
||||
if !ok {
|
||||
return errors.Errorf("cannot find dimensions of %v for Float4Array", src)
|
||||
}
|
||||
if elementsLength == 0 {
|
||||
*dst = Float4Array{Status: Present}
|
||||
return nil
|
||||
}
|
||||
if len(dimensions) == 0 {
|
||||
if originalSrc, ok := underlyingSliceType(src); ok {
|
||||
return dst.Set(originalSrc)
|
||||
}
|
||||
return errors.Errorf("cannot convert %v to Float4Array", src)
|
||||
}
|
||||
|
||||
*dst = Float4Array{
|
||||
Elements: make([]Float4, elementsLength),
|
||||
Dimensions: dimensions,
|
||||
Status: Present,
|
||||
}
|
||||
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
|
||||
if err != nil {
|
||||
// Maybe the target was one dimension too far, try again:
|
||||
if len(dst.Dimensions) > 1 {
|
||||
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
|
||||
elementsLength = 0
|
||||
for _, dim := range dst.Dimensions {
|
||||
if elementsLength == 0 {
|
||||
elementsLength = int(dim.Length)
|
||||
} else {
|
||||
elementsLength *= int(dim.Length)
|
||||
}
|
||||
}
|
||||
dst.Elements = make([]Float4, elementsLength)
|
||||
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if elementCount != len(dst.Elements) {
|
||||
return errors.Errorf("cannot convert %v to Float4Array, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
|
||||
if elementCount != len(dst.Elements) {
|
||||
return errors.Errorf("cannot convert %v to Float4Array, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -95,10 +149,11 @@ func (dst *Float4Array) setRecursive(value reflect.Value, index, dimension int)
|
||||
break
|
||||
}
|
||||
|
||||
if int32(value.Len()) != dst.Dimensions[dimension].Length {
|
||||
valueLen := value.Len()
|
||||
if int32(valueLen) != dst.Dimensions[dimension].Length {
|
||||
return 0, errors.Errorf("multidimensional arrays must have array expressions with matching dimensions")
|
||||
}
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
for i := 0; i < valueLen; i++ {
|
||||
var err error
|
||||
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
|
||||
if err != nil {
|
||||
@@ -133,6 +188,30 @@ func (dst Float4Array) Get() interface{} {
|
||||
func (src *Float4Array) AssignTo(dst interface{}) error {
|
||||
switch src.Status {
|
||||
case Present:
|
||||
if len(src.Dimensions) == 1 {
|
||||
switch v := dst.(type) {
|
||||
|
||||
case *[]float32:
|
||||
*v = make([]float32, len(src.Elements))
|
||||
for i := range src.Elements {
|
||||
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
case *[]*float32:
|
||||
*v = make([]*float32, len(src.Elements))
|
||||
for i := range src.Elements {
|
||||
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
value := reflect.ValueOf(dst)
|
||||
if value.Kind() == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
@@ -171,10 +250,12 @@ func (src *Float4Array) assignToRecursive(value reflect.Value, index, dimension
|
||||
|
||||
length := int(src.Dimensions[dimension].Length)
|
||||
if reflect.Array == kind {
|
||||
if value.Type().Len() != length {
|
||||
return 0, errors.Errorf("expected size %d array, but %s has size %d array", length, value.Type(), value.Type().Len())
|
||||
typ := value.Type()
|
||||
typLen := typ.Len()
|
||||
if typLen != length {
|
||||
return 0, errors.Errorf("expected size %d array, but %s has size %d array", length, typ, typLen)
|
||||
}
|
||||
value.Set(reflect.New(value.Type()).Elem())
|
||||
value.Set(reflect.New(typ).Elem())
|
||||
} else {
|
||||
value.Set(reflect.MakeSlice(value.Type(), length, length))
|
||||
}
|
||||
@@ -192,11 +273,14 @@ func (src *Float4Array) assignToRecursive(value reflect.Value, index, dimension
|
||||
if len(src.Dimensions) != dimension {
|
||||
return 0, errors.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
|
||||
}
|
||||
if !value.CanAddr() || !value.Addr().CanInterface() {
|
||||
if !value.CanAddr() {
|
||||
return 0, errors.Errorf("cannot assign all values from Float4Array")
|
||||
}
|
||||
err := src.Elements[index].AssignTo(value.Addr().Interface())
|
||||
if err != nil {
|
||||
addr := value.Addr()
|
||||
if !addr.CanInterface() {
|
||||
return 0, errors.Errorf("cannot assign all values from Float4Array")
|
||||
}
|
||||
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
index++
|
||||
|
||||
Reference in New Issue
Block a user