diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml index e0dd054..5627239 100644 --- a/.idea/dictionaries/project.xml +++ b/.idea/dictionaries/project.xml @@ -3,6 +3,7 @@ cval ntype + vstate vtype diff --git a/src/core/cflss/a.go b/src/core/cflss/a.go index 394becc..bac67e4 100644 --- a/src/core/cflss/a.go +++ b/src/core/cflss/a.go @@ -28,29 +28,23 @@ package cflss -import ( - "math" - "time" -) - var ( G = struct { - minTime, - maxTime time.Time TypeInfos *CValueTypeInfos }{ - minTime: time.Unix(0, math.MinInt64), - maxTime: time.Unix(0, math.MaxInt64), + TypeInfos: newCValueTypeInfos(), } E = struct { - InvalidCValueForType string + InvalidCValueReflected, + InvalidCValueForType string }{ - InvalidCValueForType : "::invalid_value_for_type", + InvalidCValueReflected : "::invalid_reflect_value", + InvalidCValueForType : "::invalid_value_for_type", } ) \ No newline at end of file diff --git a/src/core/cflss/cvalue.go b/src/core/cflss/cvalue.go index 253b42d..6d4cb8b 100644 --- a/src/core/cflss/cvalue.go +++ b/src/core/cflss/cvalue.go @@ -29,8 +29,11 @@ package cflss import ( + "core/blrs" + "core/excs" "math" "reflect" + "time" ) type CValue struct { @@ -168,7 +171,7 @@ func CreateCValueDate (value Date ) CValue { if value.IsZero() { // Comprobación directa para el valor cero return CValue{vType: CValueTypeDate, vState: cValueStateZero} } - if value.After(G.minTime) && value.Before(G.maxTime) { + if value.After(G.TypeInfos.minTime) && value.Before(G.TypeInfos.maxTime) { return CValue{vType: CValueTypeDate, vState: cValueStateShort,intVal: value.UnixNano(), anyVal: value.Location()} } return CValue{vType: CValueTypeDate, anyVal: value } @@ -221,7 +224,7 @@ func CreateCValueError (value error ) CValue { return CValue{ vType: CValueTypeError, anyVal: value } } -func CreateCValueNil (value any ) CValue { return CValue{ vType: CValueTypeNil } } +func CreateCValueNil (_ any ) CValue { return CValue{ vType: CValueTypeNil, vState: cValueStateNil } } func createCValueCValue (value CValue ) CValue { return CValue{vType: CValueTypeCValue, anyVal: value } } @@ -259,110 +262,413 @@ func createCValueWithInvalidError (value any, vtype CValueType, vstate CValueSta } -func createCValueReflected (value any, rv reflect.Value, vtype CValueType, check bool) CValue { - if !rv.IsValid() { - return buildCValueInvalidWithError("TODO/error invalid reflect value")(value) - } - rt := rv.Type() - vs := cValueStateReflected - tn := rt.String() - - switch rt.Kind() { - - case reflect.Slice, - reflect.Array: - if check { - if !vtype.IsList() { - return createCValueWithInvalidError(value,vtype,vs,E.InvalidCValueForType) - } - ke := reflectKindToCValueType(rt.Elem().Kind(), true) - if ke == CValueTypeInvalid { - return createCValueWithInvalidError(value,vtype,vs,E.InvalidCValueForType) - } - vtype |= ke - } - ln := rv.Len() - if ln == 0 { - if rv.IsNil() { - vs|=cValueStateNil - } else { - vs|= cValueStateZero - } - } - return CValue{ vType: vtype,vState: vs, anyVal: value, strVal: tn, intVal: int64(ln) } - - - case reflect.Map : - if check { - if !vtype.IsMap() { - return createCValueWithInvalidError(value,vtype,vs|cValueStateInvalid,E.InvalidCValueForType) - } - kt := reflectKindToCValueType(rt.Key().Kind(), true) - if kt == CValueTypeInvalid { - return createCValueWithInvalidError(value,vtype,vs|cValueStateInvalid,E.InvalidCValueForType) - } - et := reflectKindToCValueType(rt.Elem().Kind(), true) - if et == CValueTypeInvalid { - return createCValueWithInvalidError(value,vtype,vs|cValueStateInvalid,E.InvalidCValueForType) - } - vtype = buildMapType(kt, et) - } - ln := rv.Len() - if ln == 0 { - if rv.IsNil() { - vs|=cValueStateNil - } else { - vs|= cValueStateZero - } - } - return CValue{ vType: vtype,vState: vs, anyVal: value, strVal: tn, intVal: int64(ln) } - - - case reflect.Func : - if check { - if !vtype.IsDefer() { - return createCValueWithInvalidError(value,vtype,vs,E.InvalidCValueForType) - } - if rt.NumIn() != 0 || rt.NumOut() == 1 { - return createCValueWithInvalidError(value,vtype,vs,E.InvalidCValueForType) - } - vtype = CValueTypeDefer|CValueTypeAny - } - if rv.IsNil() { - vs|=cValueStateNil - } - return CValue{ vType: vtype,vState: vs, strVal: tn, - anyVal: func() any { - return (rv.Call(nil))[0].Interface() - }, - } - case reflect.Struct : - if check { - if !vtype.IsTypeObject() { - return createCValueWithInvalidError(value,vtype,vs,E.InvalidCValueForType) - } - } - return CValue{vType: vtype,vState: vs, anyVal: value, strVal: tn} - case reflect.Ptr: - if rv.IsNil() { - vs|=cValueStateNil - } +func (v CValue) Type () CValueType { return v.vType } + +func (v CValue) State() CValueState { return v.vState } + + + +func (v CValue) AsBool () (bool,bool){ + if v.vType != CValueTypeBool { + return false,false + } + if v.vState.HasNilOrZero() { + return false,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()bool))(),true } + return v.intVal != 0,true +} + +func (v CValue) AsInt () (int,bool){ + if v.vType != CValueTypeInt { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()int))(),true + } + return int(v.intVal),true +} - return CValue{ vType: vtype,vState: vs, anyVal: value, strVal: tn } +func (v CValue) AsInts () ([]int,bool){ + if v.vType != CValueTypeInt|CValueTypeList { + return nil,false + } + if v.vState.HasValueNil() { + return nil,true + } + return v.anyVal.([]int),true } - +func (v CValue) AsInt8 () (int8,bool){ + if v.vType != CValueTypeInt8 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()int8))(),true + } + return int8(v.intVal),true +} +func (v CValue) AsInt16 () (int16,bool){ + if v.vType != CValueTypeInt16 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()int16))(),true + } + return int16(v.intVal),true +} +func (v CValue) AsInt32 () (int32,bool){ + if v.vType != CValueTypeInt32 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()int32))(),true + } + return int32(v.intVal),true +} +func (v CValue) AsInt64 () (int64,bool){ + if v.vType != CValueTypeInt64 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()int64))(),true + } + return v.intVal,true +} -func (v CValue) Type () CValueType { return v.vType } -func (v CValue) State() CValueState { return v.vState } \ No newline at end of file +func (v CValue) AsUint () (uint,bool){ + if v.vType != CValueTypeUint { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()uint))(),true + } + return uint(v.intVal),true +} + +func (v CValue) AsUint8 () (uint8,bool){ + if v.vType != CValueTypeUint8 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()uint8))(),true + } + return uint8(v.intVal),true +} + +func (v CValue) AsUint16 () (uint16,bool){ + if v.vType != CValueTypeUint16 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()uint16))(),true + } + return uint16(v.intVal),true +} + +func (v CValue) AsUint32 () (uint32,bool){ + if v.vType != CValueTypeUint32 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()uint32))(),true + } + return uint32(v.intVal),true +} + +func (v CValue) AsUint64 () (uint64,bool){ + if v.vType != CValueTypeUint64 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()uint64))(),true + } + return uint64(v.intVal),true +} + + +func (v CValue) AsUintptr() (uintptr,bool){ + if v.vType != CValueTypeUintptr { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()uintptr))(),true + } + return uintptr(v.intVal),true +} + + +func (v CValue) AsFloat32() (float32,bool){ + if v.vType != CValueTypeFloat32 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()float32))(),true + } + return math.Float32frombits(uint32(v.intVal)), true +} + +func (v CValue) AsFloat64() (float64,bool){ + if v.vType != CValueTypeFloat64 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()float64))(),true + } + return math.Float64frombits(uint64(v.intVal)), true +} + +func (v CValue) AsComplex64 () (complex64,bool){ + if v.vType != CValueTypeComplex64 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()complex64))(),true + } + return v.anyVal.(complex64),true +} + +func (v CValue) AsComplex128() (complex128,bool){ + if v.vType != CValueTypeComplex128 { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()complex128))(),true + } + return v.anyVal.(complex128),true +} + + + +func (v CValue) AsDuration() (Duration,bool){ + if v.vType != CValueTypeDuration { + return 0,false + } + if v.vState.HasNilOrZero() { + return 0,true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()Duration))(),true + } + return time.Duration(v.intVal),true +} + +func (v CValue) AsDate () (Date,bool){ + if v.vType != CValueTypeDate { + return time.Time{},false + } + if v.vState.HasNilOrZero() { + return time.Time{}, true + } + if v.vType.IsDefer() { + return (v.anyVal.(func()Date))(),true + } + if v.vState.HasValueShort() { + // version corta del date + return time.Unix(0, v.intVal).In(v.anyVal.(*time.Location)), true + } + return v.anyVal.(time.Time),true +} + + +func (v CValue) AsString () (string,bool){ + if v.vType != CValueTypeString { + return "", false + } + if v.vState.HasNilOrZero() { + return "", true + } + if v.vType.IsDefer() { + return v.anyVal.(string), true + } + return v.strVal,true +} + +func (v CValue) AsStrings () ([]string,bool){ + if v.vType != CValueTypeList|CValueTypeString { + return nil,false + } + if v.vState.HasValueNil() { + return nil,true + } + return v.anyVal.([]string),true +} + + +func (v CValue) AsBytes () ([]byte,bool){ + if v.vType != CValueTypeBytes { + return nil, false + } + if v.vState.HasValueNil() { + return []byte(nil),true + } + if v.vType.IsDefer() { + return v.anyVal.([]byte),true + } + return v.anyVal.([]byte),true +} + + +func (v CValue) AsStack () (Stack,bool){ + if v.vType != CValueTypeStack { + return nil, false + } + if v.vState.HasValueNil() { + return Stack(nil),true + } + if v.vType.IsDefer() { + return v.anyVal.(Stack),true + } + return v.anyVal.(excs.Stack),true +} + + +func (v CValue) AsBaleable() (blrs.Baleable,bool){ + if v.vType != CValueTypeBaleable { + return nil, false + } + if v.vState.HasValueNil() { + return blrs.Baleable(nil),true + } + if v.vType.IsDefer() { + return v.anyVal.(blrs.Baleable),true + } + return v.anyVal.(blrs.Baleable),true +} + + +func (v CValue) AsError () (error,bool){ + if v.vType != CValueTypeError { + return nil, false + } + if v.vState.HasValueNil() { + return error(nil),true + } + if v.vType.IsDefer() { + return v.anyVal.(error),true + } + return v.anyVal.(error),true +} + + +func (v CValue) AsCValue () (CValue,bool) { + if v.vType != CValueTypeCValue { + return CValue{}, false + } + if v.vType.IsDefer() { + return (v.anyVal.(func()CValue))(), true + } + return v.anyVal.(CValue), true +} + +func (v CValue) AsCField () (CField,bool) { + if v.vType != CValueTypeCField { + return CField{}, false + } + if v.vType.IsDefer() { + return (v.anyVal.(func()CField))(), true + } + return v.anyVal.(CField), true +} + +func (v CValue) AsCFields() ([]CField,bool) { + if v.vType != CValueTypeCField|CValueTypeList { + return nil, false + } + if v.vState.HasValueNil() { + return nil, false + } + if v.vType.IsDefer() { + return v.anyVal.([]CField), true + } + return v.anyVal.([]CField), true +} + + + +func (v CValue) AsObject () (any,bool) { + if v.vType != CValueTypeObject { + return nil, false + } + if v.vType.IsDefer() { + return v.anyVal.(any),true + } + return v.anyVal,true +} + +func (v CValue) AsList () (any,bool) { + if v.vType != CValueTypeList { + return nil, false + } + if v.vType.IsDefer() { + return v.anyVal.(any),true + } + return v.anyVal,true +} + +func (v CValue) AsMap () (any,bool) { + if v.vType != CValueTypeMap { + return nil, false + } + if v.vType.IsDefer() { + return v.anyVal.(any),true + } + return v.anyVal,true +} diff --git a/src/core/cflss/cvalue_state.go b/src/core/cflss/cvalue_state.go index 143260f..8963162 100644 --- a/src/core/cflss/cvalue_state.go +++ b/src/core/cflss/cvalue_state.go @@ -60,6 +60,7 @@ func (s CValueState) HasValueSensitive() bool { return s&cValueStateSensitive != func (s CValueState) HasValueEncoded () bool { return s&cValueStateEncoded != 0 } func (s CValueState) HasValueError () bool { return s&cValueStateError != 0 } +func (s CValueState) HasNilOrZero () bool { return s&(cValueStateZero|cValueStateNil) != 0 } func (s CValueState) setOption (options CValueState) CValueState { return s|(options&cValueStateOps) } diff --git a/src/core/cflss/cvalue_type_infos.go b/src/core/cflss/cvalue_type_infos.go index acda049..684411b 100644 --- a/src/core/cflss/cvalue_type_infos.go +++ b/src/core/cflss/cvalue_type_infos.go @@ -29,9 +29,11 @@ package cflss import ( + "math" "math/bits" "reflect" "sync" + "time" ) const( @@ -50,6 +52,8 @@ type ( mux sync.RWMutex names [maxCValueTypes+1]string creators [maxCValueTypes+1][cValueNumCreators]func(any)CValue + minTime, + maxTime time.Time cache map[reflect.Type]func(value any)CValue } ) @@ -57,8 +61,10 @@ type ( func newCValueTypeInfos () *CValueTypeInfos { is := CValueTypeInfos{ - cache: make(map[reflect.Type]func(value any)CValue), - names: [maxCValueTypes+1]string{ + minTime : time.Unix(0, math.MinInt64), + maxTime : time.Unix(0, math.MaxInt64), + cache : make(map[reflect.Type]func(value any)CValue), + names : [maxCValueTypes+1]string{ /* 0: */ "invalid", /* 1: */ "any", /* 2: */ "bool", @@ -299,7 +305,7 @@ func (i *CValueTypeInfos) CreateCValue(value any) CValue { func (i *CValueTypeInfos) createByReflection(value any) CValue { rv := reflect.ValueOf(value) if !rv.IsValid() { - return buildCValueInvalidWithError("TODO/error invalid reflect value")(value) + return createCValueWithInvalidError(value,CValueTypeAny,0,E.InvalidCValueReflected) } rt := rv.Type() @@ -344,7 +350,8 @@ func (i *CValueTypeInfos) createByReflection(value any) CValue { } f = func(v any) CValue { - return createCValueReflected(v,reflect.ValueOf(v), vt,false) + t := vt + return createCValueReflected(v,reflect.ValueOf(v), t,false) } i.mux.Lock() @@ -355,6 +362,113 @@ func (i *CValueTypeInfos) createByReflection(value any) CValue { } + + + + +func createCValueReflected (value any, rv reflect.Value, vtype CValueType, check bool) CValue { + if !rv.IsValid() { + return createCValueWithInvalidError(value,vtype,0,E.InvalidCValueReflected) + } + rt := rv.Type() + vs := cValueStateReflected + tn := rt.String() + + switch rt.Kind() { + + case reflect.Slice, + reflect.Array: + if check { + if !vtype.IsList() { + return createCValueWithInvalidError(value,vtype,vs,E.InvalidCValueForType) + } + ke := reflectKindToCValueType(rt.Elem().Kind(), true) + if ke == CValueTypeInvalid { + return createCValueWithInvalidError(value,vtype,vs,E.InvalidCValueForType) + } + vtype |= ke + } + ln := rv.Len() + if ln == 0 { + if rv.IsNil() { + vs|=cValueStateNil + } else { + vs|= cValueStateZero + } + } + return CValue{ vType: vtype,vState: vs, anyVal: value, strVal: tn, intVal: int64(ln) } + + + case reflect.Map : + if check { + if !vtype.IsMap() { + return createCValueWithInvalidError(value,vtype,vs|cValueStateInvalid,E.InvalidCValueForType) + } + kt := reflectKindToCValueType(rt.Key().Kind(), true) + if kt == CValueTypeInvalid { + return createCValueWithInvalidError(value,vtype,vs|cValueStateInvalid,E.InvalidCValueForType) + } + et := reflectKindToCValueType(rt.Elem().Kind(), true) + if et == CValueTypeInvalid { + return createCValueWithInvalidError(value,vtype,vs|cValueStateInvalid,E.InvalidCValueForType) + } + vtype = buildMapType(kt, et) + } + ln := rv.Len() + if ln == 0 { + if rv.IsNil() { + vs|=cValueStateNil + } else { + vs|= cValueStateZero + } + } + return CValue{ vType: vtype,vState: vs, anyVal: value, strVal: tn, intVal: int64(ln) } + + + case reflect.Func : + if check { + if !vtype.IsDefer() { + return createCValueWithInvalidError(value,vtype,vs,E.InvalidCValueForType) + } + if rt.NumIn() != 0 || rt.NumOut() != 1 { + return createCValueWithInvalidError(value,vtype,vs,E.InvalidCValueForType) + } + vtype = CValueTypeDefer|CValueTypeAny + } + if rv.IsNil() { + vs|=cValueStateNil + } + return CValue{ vType: vtype,vState: vs, strVal: tn, + anyVal: func() any { + return (rv.Call(nil))[0].Interface() + }, + } + + case reflect.Struct : + if check { + if !vtype.IsTypeObject() { + return createCValueWithInvalidError(value,vtype,vs,E.InvalidCValueForType) + } + } + return CValue{vType: vtype,vState: vs, anyVal: value, strVal: tn} + + case reflect.Ptr: + if rv.IsNil() { + vs|=cValueStateNil + } + + } + + + + return CValue{ vType: vtype,vState: vs, anyVal: value, strVal: tn } +} + + + + + + func createGValCreators [T any] (valType CValueType, createFnc func(value T) CValue) [cValueNumCreators]func(any)CValue { return [cValueNumCreators]func(any)CValue { func(v any) CValue { return createFnc(v.(T)) },