func sizeof(v reflect.Type) int { switch t := v.(type) { case *reflect.ArrayType: n := sizeof(t.Elem()) if n < 0 { return -1 } return t.Len() * n case *reflect.StructType: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s := sizeof(t.Field(i).Type) if s < 0 { return -1 } sum += s } return sum case *reflect.UintType, *reflect.IntType, *reflect.FloatType, *reflect.ComplexType: switch t := t.Kind(); t { case reflect.Int, reflect.Uint, reflect.Uintptr: return -1 } return int(v.Size()) } return -1 }
func defaultType(t reflect.Type) TypeDesc { switch t.Kind() { case reflect.Bool: return BooleanType case reflect.String: return UTF8Type case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return LongType case reflect.Float32: return FloatType case reflect.Float64: return DoubleType case reflect.Array: if t.Name() == "UUID" && t.Size() == 16 { return UUIDType } return UnknownType case reflect.Struct: if t.Name() == "Time" && t.PkgPath() == "time" { return DateType } return UnknownType case reflect.Slice: if et := t.Elem(); et.Kind() == reflect.Uint8 { return BytesType } return UnknownType } return UnknownType }
func indexer(t reflect.Type) indexFunc { size := t.Size() return func(v handle, i int) handle { header := (*reflect.SliceHeader)(unsafe.Pointer(&v)) return handle(header.Data + uintptr(i)*size) } }
func sizeof(t reflect.Type) (int, error) { switch t.Kind() { case reflect.Array: n, err := sizeof(t.Elem()) if err != nil { return 0, err } return t.Len() * n, nil case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s, err := sizeof(t.Field(i).Type) if err != nil { return 0, err } sum += s } return sum, nil case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: return int(t.Size()), nil } return 0, errors.New("invalid type " + t.String()) }
// integerPromote determines if we can promote v to dType, and if so, return the promoted value. // This is needed because msgpack always encodes values as the minimum sized int that can hold them. func integerPromote(dType reflect.Type, v reflect.Value) (reflect.Value, bool) { vt := v.Type() dsz := dType.Size() vtsz := vt.Size() if isIntType(dType) && isIntType(vt) && vtsz <= dsz { pv := reflect.New(dType).Elem() pv.SetInt(v.Int()) return pv, true } if isUintType(dType) && isUintType(vt) && vtsz <= dsz { pv := reflect.New(dType).Elem() pv.SetUint(v.Uint()) return pv, true } if isIntType(dType) && isUintType(vt) && vtsz <= dsz { pv := reflect.New(dType).Elem() pv.SetInt(int64(v.Uint())) return pv, true } if isUintType(dType) && isIntType(vt) && vtsz <= dsz { pv := reflect.New(dType).Elem() pv.SetUint(uint64(v.Int())) return pv, true } return v, false }
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable. func sizeof(t reflect.Type) int { switch t.Kind() { case reflect.Array: if s := sizeof(t.Elem()); s >= 0 { return s * t.Len() } case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s := sizeof(t.Field(i).Type) if s < 0 { return -1 } sum += s } return sum case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr: return int(t.Size()) } return -1 }
func benchmarkWriteSlice(b *testing.B, typ reflect.Type, count int) { slice := reflect.MakeSlice(reflect.SliceOf(typ), count, count).Interface() b.SetBytes(int64(count * int(typ.Size()))) b.ResetTimer() for i := 0; i < b.N; i++ { Write(ioutil.Discard, BigEndian, slice) } }
func benchmarkReadSlice(b *testing.B, typ reflect.Type, count int) { fr := &fakeReader{} slice := reflect.MakeSlice(reflect.SliceOf(typ), count, count).Interface() b.SetBytes(int64(count * int(typ.Size()))) b.ResetTimer() for i := 0; i < b.N; i++ { Read(fr, BigEndian, slice) } }
func structMatchGeneric(t *testing.T, ta, tb reflect.Type, sza, szb uintptr) { if sza != szb { t.Errorf("type size mismatch: %s(%d) != %s(%d)", ta.Name(), ta.Size(), tb.Name(), tb.Size()) t.Fail() } if ta.Kind() != tb.Kind() { t.Errorf("type kind mismatch: %s=%s != %s=%s", ta.Name(), ta.Kind(), tb.Name(), tb.Kind()) t.Fail() } }
func sse2Reflect(t reflect.Type) sse2type { elemSize := uint(0) if t.Kind() == reflect.Array { elemSize = uint(t.Elem().Size()) } return sse2type{ name: t.Name(), size: uint(t.Size()), elemSize: elemSize, align: uint(t.Size()), t: t, } }
func indexSetter(t reflect.Type) indexSetFunc { size := t.Size() return func(v handle, i int, val handle) { header := (*reflect.SliceHeader)(unsafe.Pointer(&v)) var dst []byte dh := (*reflect.SliceHeader)(unsafe.Pointer(&dst)) dh.Len = int(size) dh.Data = header.Data + uintptr(i)*size var src []byte sh := (*reflect.SliceHeader)(unsafe.Pointer(&src)) sh.Len = int(size) sh.Data = uintptr(val) copy(dst, src) } }
func MatchHeaders(b reflect.Type, slice interface{}, header reflect.SliceHeader) (e error) { h, s, al := SliceHeader(slice) switch { case s != int(b.Size()): e = HeaderMismatch{"%v: slice element size should be %v not %v", b.Name(), b.Size(), s} case al != b.Align(): e = HeaderMismatch{"%v: slice element alignment should be %v not %v", b.Name(), b.Align(), al} case h.Data != header.Data: e = HeaderMismatch{"%v: slice headers should point to the same memory: %v - %v", b.Name(), h.Data, header.Data} case h.Len != header.Len: e = HeaderMismatch{"%v: slice header lengths should be the same: %v - %v", b.Name(), h.Len, header.Len} case h.Cap != header.Cap: e = HeaderMismatch{"%v: slice header capacities should be the same: %v - %v", b.Name(), h.Cap, header.Cap} } return }
func swapper(t reflect.Type) swapFunc { size := t.Size() tmp := make([]byte, size) return func(v handle, i, j int) { header := (*reflect.SliceHeader)(unsafe.Pointer(&v)) var si []byte hi := (*reflect.SliceHeader)(unsafe.Pointer(&si)) hi.Len = int(size) hi.Data = header.Data + uintptr(i)*size var sj []byte hj := (*reflect.SliceHeader)(unsafe.Pointer(&sj)) hj.Len = int(size) hj.Data = header.Data + uintptr(j)*size copy(tmp, sj) copy(sj, si) copy(si, tmp) } }
func NewMesh(attrs interface{}, indicies []uint32) *Mesh { mesh := new(Mesh) mesh.Attrs = attrs mesh.Indicies = indicies gl33.GenVertexArrays(1, &mesh.vao) gl33.BindVertexArray(mesh.vao) attrsValue := reflect.ValueOf(attrs) mesh.vertexBO = NewBuffer(gl33.ARRAY_BUFFER, gl33.STATIC_DRAW, attrs) vertexSpec := attrsValue.Type().Elem() if vertexSpec.Kind() != reflect.Struct && vertexSpec.Kind() != reflect.Array { panic("attrs is not a slice of structs or arrays") } var num int if vertexSpec.Kind() == reflect.Struct { num = vertexSpec.NumField() } else { num = vertexSpec.Len() } for i, offset := 0, uintptr(0); i < num; i++ { var field reflect.Type var type_ gl33.Enum var dimensions int if vertexSpec.Kind() == reflect.Struct { field = vertexSpec.Field(i).Type } else { field = vertexSpec.Elem() } if field.Kind() == reflect.Array { type_ = glType(field.Elem().Kind()) dimensions = field.Len() } else { type_ = glType(field.Kind()) dimensions = 1 } setupAttrib(gl33.Uint(i), type_, dimensions, offset, int(vertexSpec.Size())) offset += field.Size() } mesh.indexBO = NewBuffer(gl33.ELEMENT_ARRAY_BUFFER, gl33.STATIC_DRAW, indicies) return mesh }
func structMatch(t *testing.T, ta, tb reflect.Type) { structMatchGeneric(t, ta, tb, ta.Size(), tb.Size()) }
func new_dataTypeFromType(t reflect.Type) *DataType { var dt *DataType = nil switch t.Kind() { case reflect.Int: dt = T_NATIVE_INT // FIXME: .Copy() instead ? case reflect.Int8: dt = T_NATIVE_INT8 case reflect.Int16: dt = T_NATIVE_INT16 case reflect.Int32: dt = T_NATIVE_INT32 case reflect.Int64: dt = T_NATIVE_INT64 case reflect.Uint: dt = T_NATIVE_UINT // FIXME: .Copy() instead ? case reflect.Uint8: dt = T_NATIVE_UINT8 case reflect.Uint16: dt = T_NATIVE_UINT16 case reflect.Uint32: dt = T_NATIVE_UINT32 case reflect.Uint64: dt = T_NATIVE_UINT64 case reflect.Float32: dt = T_NATIVE_FLOAT case reflect.Float64: dt = T_NATIVE_DOUBLE case reflect.String: dt = T_GO_STRING //dt = T_C_S1 case reflect.Array: elem_type := new_dataTypeFromType(t.Elem()) n := t.Len() dims := []int{n} adt, err := NewArrayType(elem_type, dims) if err != nil { panic(err) } dt, err = adt.Copy() if err != nil { panic(err) } case reflect.Slice: elem_type := new_dataTypeFromType(t.Elem()) vlen_dt, err := NewVarLenType(elem_type) if err != nil { panic(err) } dt, err = vlen_dt.Copy() if err != nil { panic(err) } case reflect.Struct: sz := int(t.Size()) hdf_dt, err := CreateDataType(T_COMPOUND, sz) if err != nil { panic(err) } cdt := &CompType{*hdf_dt} n := t.NumField() for i := 0; i < n; i++ { f := t.Field(i) var field_dt *DataType = nil field_dt = new_dataTypeFromType(f.Type) offset := int(f.Offset + 0) if field_dt == nil { panic(fmt.Sprintf("pb with field [%d-%s]", i, f.Name)) } field_name := string(f.Tag) if len(field_name) == 0 { field_name = f.Name } err = cdt.Insert(field_name, offset, field_dt) if err != nil { panic(fmt.Sprintf("pb with field [%d-%s]: %s", i, f.Name, err)) } } cdt.Lock() dt, err = cdt.Copy() if err != nil { panic(err) } case reflect.Ptr: panic("sorry, pointers not yet supported") default: panic(fmt.Sprintf("unhandled kind (%d)", t.Kind())) } return dt }
// Value returns an arbitrary value of the given type. // If the type implements the Generator interface, that will be used. // Note: in order to create arbitrary values for structs, all the members must be public. func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) { if m, ok := reflect.MakeZero(t).Interface().(Generator); ok { return m.Generate(rand, complexSize), true } switch concrete := t.(type) { case *reflect.BoolType: return reflect.NewValue(rand.Int()&1 == 0), true case *reflect.Float32Type: return reflect.NewValue(randFloat32(rand)), true case *reflect.Float64Type: return reflect.NewValue(randFloat64(rand)), true case *reflect.FloatType: if t.Size() == 4 { return reflect.NewValue(float(randFloat32(rand))), true } else { return reflect.NewValue(float(randFloat64(rand))), true } case *reflect.Int16Type: return reflect.NewValue(int16(randInt64(rand))), true case *reflect.Int32Type: return reflect.NewValue(int32(randInt64(rand))), true case *reflect.Int64Type: return reflect.NewValue(randInt64(rand)), true case *reflect.Int8Type: return reflect.NewValue(int8(randInt64(rand))), true case *reflect.IntType: return reflect.NewValue(int(randInt64(rand))), true case *reflect.MapType: numElems := rand.Intn(complexSize) m := reflect.MakeMap(concrete) for i := 0; i < numElems; i++ { key, ok1 := Value(concrete.Key(), rand) value, ok2 := Value(concrete.Elem(), rand) if !ok1 || !ok2 { return nil, false } m.SetElem(key, value) } return m, true case *reflect.PtrType: v, ok := Value(concrete.Elem(), rand) if !ok { return nil, false } p := reflect.MakeZero(concrete) p.(*reflect.PtrValue).PointTo(v) return p, true case *reflect.SliceType: numElems := rand.Intn(complexSize) s := reflect.MakeSlice(concrete, numElems, numElems) for i := 0; i < numElems; i++ { v, ok := Value(concrete.Elem(), rand) if !ok { return nil, false } s.Elem(i).SetValue(v) } return s, true case *reflect.StringType: numChars := rand.Intn(complexSize) codePoints := make([]int, numChars) for i := 0; i < numChars; i++ { codePoints[i] = rand.Intn(0x10ffff) } return reflect.NewValue(string(codePoints)), true case *reflect.StructType: s := reflect.MakeZero(t).(*reflect.StructValue) for i := 0; i < s.NumField(); i++ { v, ok := Value(concrete.Field(i).Type, rand) if !ok { return nil, false } s.Field(i).SetValue(v) } return s, true case *reflect.Uint16Type: return reflect.NewValue(uint16(randInt64(rand))), true case *reflect.Uint32Type: return reflect.NewValue(uint32(randInt64(rand))), true case *reflect.Uint64Type: return reflect.NewValue(uint64(randInt64(rand))), true case *reflect.Uint8Type: return reflect.NewValue(uint8(randInt64(rand))), true case *reflect.UintType: return reflect.NewValue(uint(randInt64(rand))), true case *reflect.UintptrType: return reflect.NewValue(uintptr(randInt64(rand))), true default: return nil, false } return }
func AddApis(am Apis) { for _, a := range am { f := r.ValueOf(a.Fnc) if f.Kind() != r.Ptr { panic("outside: " + r.TypeOf(a.Fnc).String() + " supplied : Pointer to function expected") } fn := f.Elem() fnt := fn.Type() var apiCall func(i []r.Value) []r.Value //Allow 2 returns and put err in 2nd if supplied var ot, et r.Type nOut := fnt.NumOut() if nOut >= 1 { ot = fnt.Out(0) } if nOut == 2 { et = fnt.Out(1) } p, unicode := apiAddr(a.Ep) if p != nil { fai, sli, fao, slo := funcAnalysis(fnt) // name := a.Ep retSizeArg := -1 if nOut >= 1 && ot.Kind() == r.Slice { if sa, ok := ot.MethodByName("SizeArg"); ok { retSizeArg = int(sa.Func.Call([]r.Value{r.Indirect(r.New(ot))})[0].Int() - 1) } } var hasErrorMethod bool var ea r.Method if ot != nil { ea, hasErrorMethod = ot.MethodByName("Error") } apiCall = func(i []r.Value) []r.Value { TOT++ var rr r.Value inStructs(unicode, i, fai, sli) ina := inArgs(unicode, i) r1, r2, f, err := p.call(ina...) // Printf("%s %v %v %b %x %b %x\n", name, i, ot, fai, sli, fao, slo) outStructs(unicode, i, fao, slo) if ot != nil { if runtime.GOARCH == "amd64" || ot.Size() == 4 { rr = r.ValueOf(r1) } else if fnt.Out(0).Kind() == r.Float64 || fnt.Out(0).Kind() == r.Float32 { rr = r.ValueOf(f) } else { rr = r.ValueOf((uint64(r2) << 32) | uint64(r1)) } vrsa := rsaNo if retSizeArg != -1 { vrsa = i[retSizeArg] } v1 := convert(rr, ot, unicode, vrsa) if hasErrorMethod { // TODO(t): for linux - error strategy var ret []r.Value if err == nil { ret = ea.Func.Call([]r.Value{v1, r.Zero(r.TypeOf(new(error)).Elem())}) // issue 6871 } else { ret = ea.Func.Call([]r.Value{v1, r.ValueOf(err)}) } v1 = ret[0] if e := ret[1].Interface(); e != nil { err = e.(error) } else { err = nil } } if et == nil { return []r.Value{v1} } else { return []r.Value{v1, convert(r.ValueOf(err), et, unicode, rsaNo)} } } else { return nil } } } else { apiCall = func(i []r.Value) []r.Value { panic(`outside: call of non-existent procedure "` + string(a.Ep) + `"`) } } v := r.MakeFunc(fn.Type(), apiCall) fn.Set(v) } }
// NewDatatypeFromType creates a new Datatype from a reflect.Type. func NewDataTypeFromType(t reflect.Type) (*Datatype, error) { var dt *Datatype = nil var err error switch t.Kind() { case reflect.Int: dt, err = T_NATIVE_INT.Copy() case reflect.Int8: dt, err = T_NATIVE_INT8.Copy() case reflect.Int16: dt, err = T_NATIVE_INT16.Copy() case reflect.Int32: dt, err = T_NATIVE_INT32.Copy() case reflect.Int64: dt, err = T_NATIVE_INT64.Copy() case reflect.Uint: dt, err = T_NATIVE_UINT.Copy() case reflect.Uint8: dt, err = T_NATIVE_UINT8.Copy() case reflect.Uint16: dt, err = T_NATIVE_UINT16.Copy() case reflect.Uint32: dt, err = T_NATIVE_UINT32.Copy() case reflect.Uint64: dt, err = T_NATIVE_UINT64.Copy() case reflect.Float32: dt, err = T_NATIVE_FLOAT.Copy() case reflect.Float64: dt, err = T_NATIVE_DOUBLE.Copy() case reflect.String: dt, err = T_GO_STRING.Copy() case reflect.Array: elem_type, err := NewDataTypeFromType(t.Elem()) if err != nil { return nil, err } dims := getArrayDims(t) adt, err := NewArrayType(elem_type, dims) if err != nil { return nil, err } dt, err = adt.Copy() if err != nil { return nil, err } case reflect.Struct: sz := int(t.Size()) hdf_dt, err := CreateDatatype(T_COMPOUND, sz) if err != nil { return nil, err } cdt := &CompoundType{*hdf_dt} n := t.NumField() for i := 0; i < n; i++ { f := t.Field(i) var field_dt *Datatype = nil field_dt, err = NewDataTypeFromType(f.Type) if err != nil { return nil, err } offset := int(f.Offset + 0) if field_dt == nil { return nil, fmt.Errorf("pb with field [%d-%s]", i, f.Name) } field_name := string(f.Tag) if len(field_name) == 0 { field_name = f.Name } err = cdt.Insert(field_name, offset, field_dt) if err != nil { return nil, fmt.Errorf("pb with field [%d-%s]: %s", i, f.Name, err) } } cdt.Lock() dt, err = cdt.Copy() if err != nil { return nil, err } default: // Should never happen. panic(fmt.Sprintf("unhandled kind (%v)", t.Kind())) } return dt, err }
func structMatchFixed(t *testing.T, ta, tb reflect.Type, szb uintptr) { structMatchGeneric(t, ta, tb, ta.Size(), szb) }
// PointerToByteArray convert to bytes array. // // Warning: // While it is technically possible to have count be an arbitrary large number, // it is unwise to do so. Attempting to do so is undefined and may have security // or stability issues. The security issues from including outside boundary data // or stability issues from attempting to extend outside the bounds of the // current data block and causing an OS fault. func PointerToByteArray(ptr uintptr, count uint32, t reflect.Type) []byte { byteCount := count * uint32(t.Size()) slicehdr := reflect.SliceHeader{Data: ptr, Len: int(byteCount), Cap: int(byteCount)} return *(*[]byte)(unsafe.Pointer(&slicehdr)) }