internal/lib/reflect: Value.IsZero
This commit is contained in:
@@ -22,6 +22,7 @@ package reflect
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"math"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/c/bitcast"
|
"github.com/goplus/llgo/c/bitcast"
|
||||||
@@ -843,66 +844,63 @@ func (v Value) IsValid() bool {
|
|||||||
// IsZero reports whether v is the zero value for its type.
|
// IsZero reports whether v is the zero value for its type.
|
||||||
// It panics if the argument is invalid.
|
// It panics if the argument is invalid.
|
||||||
func (v Value) IsZero() bool {
|
func (v Value) IsZero() bool {
|
||||||
/*
|
switch v.kind() {
|
||||||
switch v.kind() {
|
case Bool:
|
||||||
case Bool:
|
return !v.Bool()
|
||||||
return !v.Bool()
|
case Int, Int8, Int16, Int32, Int64:
|
||||||
case Int, Int8, Int16, Int32, Int64:
|
return v.Int() == 0
|
||||||
return v.Int() == 0
|
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
||||||
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
return v.Uint() == 0
|
||||||
return v.Uint() == 0
|
case Float32, Float64:
|
||||||
case Float32, Float64:
|
return math.Float64bits(v.Float()) == 0
|
||||||
return math.Float64bits(v.Float()) == 0
|
case Complex64, Complex128:
|
||||||
case Complex64, Complex128:
|
c := v.Complex()
|
||||||
c := v.Complex()
|
return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
|
||||||
return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
|
case Array:
|
||||||
case Array:
|
// If the type is comparable, then compare directly with zero.
|
||||||
// If the type is comparable, then compare directly with zero.
|
if v.typ().Equal != nil && v.typ().Size() <= maxZero {
|
||||||
if v.typ().Equal != nil && v.typ().Size() <= maxZero {
|
if v.flag&flagIndir == 0 {
|
||||||
if v.flag&flagIndir == 0 {
|
return v.ptr == nil
|
||||||
return v.ptr == nil
|
|
||||||
}
|
|
||||||
// v.ptr doesn't escape, as Equal functions are compiler generated
|
|
||||||
// and never escape. The escape analysis doesn't know, as it is a
|
|
||||||
// function pointer call.
|
|
||||||
return v.typ().Equal(noescape(v.ptr), unsafe.Pointer(&zeroVal[0]))
|
|
||||||
}
|
}
|
||||||
|
// v.ptr doesn't escape, as Equal functions are compiler generated
|
||||||
n := v.Len()
|
// and never escape. The escape analysis doesn't know, as it is a
|
||||||
for i := 0; i < n; i++ {
|
// function pointer call.
|
||||||
if !v.Index(i).IsZero() {
|
return v.typ().Equal(noescape(v.ptr), unsafe.Pointer(&zeroVal[0]))
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
case Chan, Func, Interface, Map, Pointer, Slice, UnsafePointer:
|
|
||||||
return v.IsNil()
|
|
||||||
case String:
|
|
||||||
return v.Len() == 0
|
|
||||||
case Struct:
|
|
||||||
// If the type is comparable, then compare directly with zero.
|
|
||||||
if v.typ().Equal != nil && v.typ().Size() <= maxZero {
|
|
||||||
if v.flag&flagIndir == 0 {
|
|
||||||
return v.ptr == nil
|
|
||||||
}
|
|
||||||
// See noescape justification above.
|
|
||||||
return v.typ().Equal(noescape(v.ptr), unsafe.Pointer(&zeroVal[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
n := v.NumField()
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
if !v.Field(i).IsZero() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
// This should never happen, but will act as a safeguard for later,
|
|
||||||
// as a default value doesn't makes sense here.
|
|
||||||
panic(&ValueError{"reflect.Value.IsZero", v.Kind()})
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
panic("todo: reflect.Value.IsZero")
|
n := v.Len()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
if !v.Index(i).IsZero() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
case Chan, Func, Interface, Map, Pointer, Slice, UnsafePointer:
|
||||||
|
return v.IsNil()
|
||||||
|
case String:
|
||||||
|
return v.Len() == 0
|
||||||
|
case Struct:
|
||||||
|
// If the type is comparable, then compare directly with zero.
|
||||||
|
if v.typ().Equal != nil && v.typ().Size() <= maxZero {
|
||||||
|
if v.flag&flagIndir == 0 {
|
||||||
|
return v.ptr == nil
|
||||||
|
}
|
||||||
|
// See noescape justification above.
|
||||||
|
return v.typ().Equal(noescape(v.ptr), unsafe.Pointer(&zeroVal[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
n := v.NumField()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
if !v.Field(i).IsZero() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
// This should never happen, but will act as a safeguard for later,
|
||||||
|
// as a default value doesn't makes sense here.
|
||||||
|
panic(&ValueError{"reflect.Value.IsZero", v.Kind()})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetZero sets v to be the zero value of v's type.
|
// SetZero sets v to be the zero value of v's type.
|
||||||
@@ -1793,6 +1791,9 @@ func Zero(typ Type) Value {
|
|||||||
// must match declarations in runtime/map.go.
|
// must match declarations in runtime/map.go.
|
||||||
const maxZero = runtime.MaxZero
|
const maxZero = runtime.MaxZero
|
||||||
|
|
||||||
|
//go:linkname zeroVal runtime.ZeroVal
|
||||||
|
var zeroVal [maxZero]byte
|
||||||
|
|
||||||
// New returns a Value representing a pointer to a new zero value
|
// New returns a Value representing a pointer to a new zero value
|
||||||
// for the specified type. That is, the returned Value's Type is PointerTo(typ).
|
// for the specified type. That is, the returned Value's Type is PointerTo(typ).
|
||||||
func New(typ Type) Value {
|
func New(typ Type) Value {
|
||||||
|
|||||||
Reference in New Issue
Block a user