Mixed datatype

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
srvaldez
Posts: 2527
Joined: Sep 25, 2005 21:54

Re: Mixed datatype

Postby srvaldez » Jun 17, 2020 10:15

thank you fxm and dodicat, it turns out I shot myself in the foot when I added the integer constructor, will study more and hack less.
srvaldez
Posts: 2527
Joined: Sep 25, 2005 21:54

Re: Mixed datatype

Postby srvaldez » Jun 18, 2020 14:40

adding more constructors were needed for enhanced functionality
many thanks to fxm for correcting and enhancing the original Mixed.bi viewtopic.php?p=273217#p273217
I recommend that you use his version unless you feel adventurous or perhaps to try the Mixed-assocarray example posted at bottom
Mixed.bi

Code: Select all

''
''    Mixed datatype definition
''
''    by Aleksandar Ruzicic
''

#Ifndef __MIXED_TYPE__
#Define __MIXED_TYPE__

   #Macro MixedDeclareOperators(_TYPE_)
      Declare Operator Cast As _TYPE_
      Declare Operator Let(value As _TYPE_)
      Declare Operator +=(value As _TYPE_)
      Declare Operator -=(value As _TYPE_)
      Declare Operator *=(value As _TYPE_)
      Declare Operator /=(value As _TYPE_)
      Declare Operator \=(value As _TYPE_)
      Declare Operator ^=(value As _TYPE_)
      Declare Operator Mod=(value As _TYPE_)
      Declare Operator Shl=(value As _TYPE_)
      Declare Operator Shr=(value As _TYPE_)
      Declare Operator And=(value As _TYPE_)
      Declare Operator Or=(value As _TYPE_)
      Declare Operator Xor=(value As _TYPE_)
      Declare Operator Imp=(value As _TYPE_)
      Declare Operator Eqv=(value As _TYPE_)
   #EndMacro

   #Macro MixedImplementAssignmentOperators(_TYPE_)
      Operator Mixed.+=(value As _TYPE_)
         This = Cast(_TYPE_, This) + value
      End Operator
      Operator Mixed.-=(value As _TYPE_)
         This = Cast(_TYPE_, This) - value
      End Operator
      Operator Mixed.*=(value As _TYPE_)
         This = Cast(_TYPE_, This) * value
      End Operator
      Operator Mixed./=(value As _TYPE_)
         This = Cast(_TYPE_, This) / value
      End Operator
      Operator Mixed.\=(value As _TYPE_)
         This = Cast(_TYPE_, This) \ value
      End Operator
      Operator Mixed.^=(value As _TYPE_)
         This = Cast(_TYPE_, This) ^ value
      End Operator
      Operator Mixed.Mod=(value As _TYPE_)
         This = Cast(_TYPE_, This) Mod value
      End Operator
      Operator Mixed.Shl=(value As _TYPE_)
         This = Cast(_TYPE_, This) Shl value
      End Operator
      Operator Mixed.Shr=(value As _TYPE_)
         This = Cast(_TYPE_, This) Shr value
      End Operator
      Operator Mixed.And=(value As _TYPE_)
         This = Cast(_TYPE_, This) And value
      End Operator
      Operator Mixed.Or=(value As _TYPE_)
         This = Cast(_TYPE_, This) Or value
      End Operator
      Operator Mixed.Xor=(value As _TYPE_)
         This = Cast(_TYPE_, This) Xor value
      End Operator
      Operator Mixed.Imp=(value As _TYPE_)
         This = Cast(_TYPE_, This) Imp value
      End Operator
      Operator Mixed.Eqv=(value As _TYPE_)
         This = Cast(_TYPE_, This) Eqv value
      End Operator
   #EndMacro

   #Macro MixedImplementBinaryOperator(_OP_)
   Operator _OP_(ByRef lhs As Mixed, ByRef rhs As Mixed) As Mixed
      If lhs.TypeId < fbInteger Or rhs.TypeId < fbInteger Then
         Return CDbl(lhs) _OP_ CDbl(rhs)
      Else
         Return CInt(lhs) _OP_ CInt(rhs)
      EndIf
   End Operator
   #EndMacro


   Enum MixedType
      fbEmpty
      fbString
      fbDouble
      fbSingle
      fbLongInt
      fbLong
      fbInteger
      fbShort
      fbByte
      fbAnyPointer
   End Enum

   Type Mixed

      Public:

      Declare Constructor

      Declare Constructor(ByRef m As Mixed)
      declare Constructor (Byval m As byte)
      declare Constructor (Byval m As short)
      declare Constructor (Byval m As long)
      declare Constructor (Byval m As integer)
      declare Constructor (Byval m As longint)
      declare Constructor (Byval m As single)
      declare Constructor (Byval m As double)

      declare Constructor (Byref m As string)
      
      declare Constructor (Byval m As Ubyte)
      declare Constructor (Byval m As Ushort)
      declare Constructor (Byval m As Ulong)
      declare Constructor (Byval m As Uinteger)
      declare Constructor (Byval m As Ulongint)

      Declare Operator Let(ByRef m As Mixed)

      Declare Destructor

      Declare Property TypeId As MixedType

      Declare Operator Cast As String
      Declare Operator Let(value As String)
      Declare Operator +=(value As String)
      Declare Operator &=(value As String)
      
      declare operator +=(byref rhs as Mixed)
      
      MixedDeclareOperators(Double)
      MixedDeclareOperators(Single)
      MixedDeclareOperators(LongInt)
      MixedDeclareOperators(Long)
      MixedDeclareOperators(Integer)
      MixedDeclareOperators(Short)
      MixedDeclareOperators(Byte)
         
      Declare Operator Cast As Any Pointer
      Declare Operator Let(value As Any Pointer)
      '------------------------------------------
      ' For Next Implicit step = +1
      Declare Operator For ( )
      Declare Operator Step( )
      Declare Operator Next( Byref end_cond As Mixed ) As Integer
      ' For Next Exlicit step
      Declare Operator For ( Byref stp As Mixed )
      Declare Operator Step( Byref stp As Mixed )
      Declare Operator Next( Byref end_cond As Mixed, Byref step_var As Mixed ) As Integer
      '----------------------------------------------
      Private:

         StoredType   As MixedType   = fbEmpty
         StoredData   As Any Pointer   = 0

   End Type

   Constructor Mixed
   End Constructor

   Constructor Mixed(ByRef m As Mixed)
       This = m
   End Constructor

   Constructor Mixed(Byval m As byte)
       This = m
   End Constructor
   
   Constructor Mixed(Byval m As short)
       This = m
   End Constructor
   
   Constructor Mixed(Byval m As long)
       This = m
   End Constructor
   
   Constructor Mixed(Byval m As integer)
       This = m
   End Constructor

   Constructor Mixed(Byval m As longint)
       This = m
   End Constructor

   Constructor Mixed(Byval m As Ubyte)
       This = m
   End Constructor
   
   Constructor Mixed(Byval m As Ushort)
       This = m
   End Constructor
   
   Constructor Mixed(Byval m As Ulong)
       This = m
   End Constructor

   Constructor Mixed(Byval m As Uinteger)
       This = m
   End Constructor

   Constructor Mixed(Byval m As Ulongint)
       This = m
   End Constructor

   Constructor Mixed(Byval m As single)
       This = m
   End Constructor
   
   Constructor Mixed(Byval m As double)
       This = m
   End Constructor
   
   Constructor Mixed(Byref m As string)
       This = m
   End Constructor
   
   Operator Mixed.Let(ByRef m As Mixed)
      Select Case m.StoredType
         Case fbEmpty:
         Case fbString: This = *Cast(String Pointer, m.StoredData)
         Case fbDouble: This = *Cast(Double Pointer, m.StoredData)
         Case fbSingle: This = *Cast(Single Pointer, m.StoredData)
         Case fbLongInt: This = *Cast(LongInt Pointer, m.StoredData)
         Case fbLong: This = *Cast(Long Pointer, m.StoredData)
         Case fbInteger: This = *Cast(Integer Pointer, m.StoredData)
         Case fbShort: This = *Cast(Short Pointer, m.StoredData)
         Case fbByte: This = *Cast(Byte Pointer, m.StoredData)
         Case fbAnyPointer: This = *Cast(Single Pointer, m.StoredData)
      End Select
   End Operator

   Destructor Mixed
      If This.StoredType <> fbEmpty And this.StoredType <> fbAnyPointer Then
         If This.StoredType = fbString Then
            *Cast(String Pointer, This.StoredData) = ""
         EndIf
         DeAllocate This.StoredData
      EndIf
   End Destructor

   Property Mixed.TypeId As MixedType
      Return This.StoredType
   End Property

   Operator Mixed.Cast As String
      Select Case This.StoredType
         Case fbEmpty: Return ""
         Case fbString: Return *Cast(String Pointer, This.StoredData)
         Case fbDouble: Return Str(*Cast(Double Pointer, This.StoredData))
         Case fbSingle: Return Str(*Cast(Single Pointer, This.StoredData))
         Case fbLongInt: Return Str(*Cast(LongInt Pointer, This.StoredData))
         Case fbLong: Return Str(*Cast(Long Pointer, This.StoredData))
         Case fbInteger: Return Str(*Cast(Integer Pointer, This.StoredData))
         Case fbShort: Return Str(*Cast(Short Pointer, This.StoredData))
         Case fbByte: Return Str(*Cast(Byte Pointer, This.StoredData))
         Case fbAnyPointer: Return *Cast(String Pointer, This.StoredData)
      End Select
   End Operator
   Operator Mixed.Let(Value As String)
      If This.StoredType <> fbEmpty And This.StoredType <> fbAnyPointer Then
         If This.StoredType = fbString Then
            *Cast(String Pointer, This.StoredData) = ""
         EndIf
         DeAllocate This.StoredData
      EndIf
      This.StoredType = fbString
      This.StoredData = CAllocate(SizeOf(String))
      *Cast(String Pointer, This.StoredData) = value
   End Operator
   Operator Mixed.+=(value As String)
      This = Cast(String, This) & value
   End Operator
   Operator Mixed.&=(value As String)
      This = Cast(String, This) & value
   End Operator

   Operator Mixed.Cast As Double
      Select Case This.StoredType
         Case fbEmpty: Return 0
         Case fbString: Return CDbl(*Cast(String Pointer, This.StoredData))
         Case fbDouble: Return *Cast(Double Pointer, This.StoredData)
         Case fbSingle: Return CDbl(*Cast(Single Pointer, This.StoredData))
         Case fbLongInt: Return CDbl(*Cast(LongInt Pointer, This.StoredData))
         Case fbLong: Return CDbl(*Cast(Long Pointer, This.StoredData))
         Case fbInteger: Return CDbl(*Cast(Integer Pointer, This.StoredData))
         Case fbShort: Return CDbl(*Cast(Short Pointer, This.StoredData))
         Case fbByte: Return CDbl(*Cast(Byte Pointer, This.StoredData))
         Case fbAnyPointer: Return *Cast(Double Pointer, This.StoredData)
      End Select
   End Operator
   Operator Mixed.Let(Value As Double)
      If This.StoredType <> fbEmpty And This.StoredType <> fbAnyPointer Then
         DeAllocate This.StoredData
      EndIf
      This.StoredType = fbDouble
      This.StoredData = Allocate(SizeOf(Double))
      *Cast(Double Pointer, This.StoredData) = value
   End Operator
   MixedImplementAssignmentOperators(Double)

   Operator Mixed.Cast As Single
      Select Case This.StoredType
         Case fbEmpty: Return 0
         Case fbString: Return CSng(*Cast(String Pointer, This.StoredData))
         Case fbDouble: Return CSng(*Cast(Double Pointer, This.StoredData))
         Case fbSingle: Return *Cast(Single Pointer, This.StoredData)
         Case fbLongInt: Return CSng(*Cast(LongInt Pointer, This.StoredData))
         Case fbLong: Return CSng(*Cast(Long Pointer, This.StoredData))
         Case fbInteger: Return CSng(*Cast(Integer Pointer, This.StoredData))
         Case fbShort: Return CSng(*Cast(Short Pointer, This.StoredData))
         Case fbByte: Return CSng(*Cast(Byte Pointer, This.StoredData))
         Case fbAnyPointer: Return *Cast(Single Pointer, This.StoredData)
      End Select
   End Operator
   Operator Mixed.Let(Value As Single)
      If This.StoredType <> fbEmpty And This.StoredType <> fbAnyPointer Then
         DeAllocate This.StoredData
      EndIf
      This.StoredType = fbSingle
      This.StoredData = Allocate(SizeOf(Single))
      *Cast(Single Pointer, This.StoredData) = value
   End Operator
   MixedImplementAssignmentOperators(Single)

   Operator Mixed.Cast As LongInt
      Select Case This.StoredType
         Case fbEmpty: Return 0
         Case fbString: Return CLngInt(*Cast(String Pointer, This.StoredData))
         Case fbDouble: Return CLngInt(*Cast(Double Pointer, This.StoredData))
         Case fbSingle: Return CLngInt(*Cast(Single Pointer, This.StoredData))
         Case fbLongInt: Return *Cast(LongInt Pointer, This.StoredData)
         Case fbLong: Return CLngInt(*Cast(Long Pointer, This.StoredData))
         Case fbInteger: Return CLngInt(*Cast(Integer Pointer, This.StoredData))
         Case fbShort: Return CLngInt(*Cast(Short Pointer, This.StoredData))
         Case fbByte: Return CLngInt(*Cast(Byte Pointer, This.StoredData))
         Case fbAnyPointer: Return *Cast(LongInt Pointer, This.StoredData)
      End Select
   End Operator
   Operator Mixed.Let(Value As LongInt)
      If This.StoredType <> fbEmpty And This.StoredType <> fbAnyPointer Then
         DeAllocate This.StoredData
      EndIf
      This.StoredType = fbLongInt
      This.StoredData = Allocate(SizeOf(LongInt))
      *Cast(LongInt Pointer, This.StoredData) = value
   End Operator
   MixedImplementAssignmentOperators(LongInt)

   Operator Mixed.Cast As Long
      Select Case This.StoredType
         Case fbEmpty: Return 0
         Case fbString: Return CLng(*Cast(String Pointer, This.StoredData))
         Case fbDouble: Return CLng(*Cast(Double Pointer, This.StoredData))
         Case fbSingle: Return CLng(*Cast(Single Pointer, This.StoredData))
         Case fbLongInt: Return CLng(*Cast(LongInt Pointer, This.StoredData))
         Case fbLong: Return *Cast(Long Pointer, This.StoredData)
         Case fbInteger: Return CLng(*Cast(Integer Pointer, This.StoredData))
         Case fbShort: Return CLng(*Cast(Short Pointer, This.StoredData))
         Case fbByte: Return CLng(*Cast(Byte Pointer, This.StoredData))
         Case fbAnyPointer: Return *Cast(Long Pointer, This.StoredData)
      End Select
   End Operator
   Operator Mixed.Let(Value As Long)
      If This.StoredType <> fbEmpty And This.StoredType <> fbAnyPointer Then
         DeAllocate This.StoredData
      EndIf
      This.StoredType = fbLong
      This.StoredData = Allocate(SizeOf(Long))
      *Cast(Long Pointer, This.StoredData) = value
   End Operator
   MixedImplementAssignmentOperators(Long)

   Operator Mixed.Cast As Integer
      Select Case This.StoredType
         Case fbEmpty: Return 0
         Case fbString: Return CInt(*Cast(String Pointer, This.StoredData))
         Case fbDouble: Return CInt(*Cast(Double Pointer, This.StoredData))
         Case fbSingle: Return CInt(*Cast(Single Pointer, This.StoredData))
         Case fbLongInt: Return CInt(*Cast(LongInt Pointer, This.StoredData))
         Case fbLong: Return CInt(*Cast(Long Pointer, This.StoredData))
         Case fbInteger: Return *Cast(Integer Pointer, This.StoredData)
         Case fbShort: Return CInt(*Cast(Short Pointer, This.StoredData))
         Case fbByte: Return CInt(*Cast(Byte Pointer, This.StoredData))
         Case fbAnyPointer: Return *Cast(Integer Pointer, This.StoredData)
      End Select
   End Operator
   Operator Mixed.Let(Value As Integer)
      If This.StoredType <> fbEmpty And This.StoredType <> fbAnyPointer Then
         DeAllocate This.StoredData
      EndIf
      This.StoredType = fbInteger
      This.StoredData = Allocate(SizeOf(Integer))
      *Cast(Integer Pointer, This.StoredData) = value
   End Operator
   MixedImplementAssignmentOperators(Integer)

   Operator Mixed.Cast As Short
      Select Case This.StoredType
         Case fbEmpty: Return 0
         Case fbString: Return CShort(*Cast(String Pointer, This.StoredData))
         Case fbDouble: Return CShort(*Cast(Double Pointer, This.StoredData))
         Case fbSingle: Return CShort(*Cast(Single Pointer, This.StoredData))
         Case fbLongInt: Return CShort(*Cast(LongInt Pointer, This.StoredData))
         Case fbLong: Return CShort(*Cast(Long Pointer, This.StoredData))
         Case fbInteger: Return CShort(*Cast(Integer Pointer, This.StoredData))
         Case fbShort: Return *Cast(Short Pointer, This.StoredData)
         Case fbByte: Return CShort(*Cast(Byte Pointer, This.StoredData))
         Case fbAnyPointer: Return *Cast(Short Pointer, This.StoredData)
      End Select
   End Operator
   Operator Mixed.Let(Value As Short)
      If This.StoredType <> fbEmpty And This.StoredType <> fbAnyPointer Then
         DeAllocate This.StoredData
      EndIf
      This.StoredType = fbShort
      This.StoredData = Allocate(SizeOf(Short))
      *Cast(Short Pointer, This.StoredData) = value
   End Operator
   MixedImplementAssignmentOperators(Short)

   Operator Mixed.Cast As Byte
      Select Case This.StoredType
         Case fbEmpty: Return 0
         Case fbString: Return CByte(*Cast(String Pointer, This.StoredData))
         Case fbDouble: Return CByte(*Cast(Double Pointer, This.StoredData))
         Case fbSingle: Return CByte(*Cast(Single Pointer, This.StoredData))
         Case fbLongInt: Return CByte(*Cast(LongInt Pointer, This.StoredData))
         Case fbLong: Return CByte(*Cast(Long Pointer, This.StoredData))
         Case fbInteger: Return CByte(*Cast(Integer Pointer, This.StoredData))
         Case fbShort: Return CByte(*Cast(Short Pointer, This.StoredData))
         Case fbByte: Return *Cast(Byte Pointer, This.StoredData)
         Case fbAnyPointer: Return *Cast(Byte Pointer, This.StoredData)
      End Select
   End Operator
   Operator Mixed.Let(Value As Byte)
      If This.StoredType <> fbEmpty And This.StoredType <> fbAnyPointer Then
         DeAllocate This.StoredData
      EndIf
      This.StoredType = fbByte
      This.StoredData = Allocate(SizeOf(Byte))
      *Cast(Byte Pointer, This.StoredData) = value
   End Operator
   MixedImplementAssignmentOperators(Byte)

   Operator Mixed.Cast As Any Pointer
      Select Case This.StoredType
         Case fbEmpty: Return 0
         Case fbString: Return Cast(String Pointer, This.StoredData)
         Case fbDouble: Return Cast(Double Pointer, This.StoredData)
         Case fbSingle: Return Cast(Single Pointer, This.StoredData)
         Case fbLongInt: Return Cast(LongInt Pointer, This.StoredData)
         Case fbLong: Return Cast(Long Pointer, This.StoredData)
         Case fbInteger: Return Cast(Integer Pointer, This.StoredData)
         Case fbShort: Return Cast(Short Pointer, This.StoredData)
         Case fbByte: Return Cast(Byte Pointer, This.StoredData)
         Case fbAnyPointer: Return This.StoredData
      End Select
   End Operator
   Operator Mixed.Let(Value As Any Pointer)
      If This.StoredType <> fbEmpty And This.StoredType <> fbAnyPointer Then
         DeAllocate This.StoredData
      EndIf
      This.StoredType = fbAnyPointer
      This.StoredData = Allocate(SizeOf(Any Pointer))
      This.StoredData = value
   End Operator

   Operator -(ByRef rhs As Mixed) As Mixed
      Select Case rhs.TypeId
         Case fbEmpty:    Return 0
         Case Else:       Return -Cast(Double, rhs)
      End Select
   End Operator

   Operator &(ByRef lhs As Mixed, ByRef rhs As Mixed) As Mixed
      Return Str(lhs) & Str(rhs)
   End Operator

   MixedImplementBinaryOperator(+)
   MixedImplementBinaryOperator(-)
   MixedImplementBinaryOperator(*)
   MixedImplementBinaryOperator(/)
   MixedImplementBinaryOperator(\)
   MixedImplementBinaryOperator(Mod)
   MixedImplementBinaryOperator(Shl)
   MixedImplementBinaryOperator(Shr)
   MixedImplementBinaryOperator(And)
   MixedImplementBinaryOperator(Or)
   MixedImplementBinaryOperator(Xor)
   MixedImplementBinaryOperator(Imp)
   MixedImplementBinaryOperator(Eqv)
   MixedImplementBinaryOperator(^)
   MixedImplementBinaryOperator(=)
   MixedImplementBinaryOperator(<>)
   MixedImplementBinaryOperator(<)
   MixedImplementBinaryOperator(>)
   MixedImplementBinaryOperator(<=)
   MixedImplementBinaryOperator(>=)
   
   operator Mixed.+=(byref rhs as Mixed)
      this+=rhs
   end operator
   '============================================================================
   '' For Next for Mixed type
   ''
   '' implicit step versions
   ''
   '' In this example, we interpret implicit step
   '' to mean 1
   Operator Mixed.for ( )
   End Operator
   
   Operator Mixed.step ( )
         this += 1 'this = this+1 '
   End Operator
   
   Operator Mixed.next ( Byref end_cond As Mixed ) As Integer
         Return this <= end_cond
   End Operator
   
   
   '' explicit step versions
   ''
   Operator Mixed.for ( Byref step_var As Mixed )
   End Operator
   
   Operator Mixed.step ( Byref step_var As Mixed )
         this += step_var 
   End Operator
   
   Operator Mixed.next ( Byref end_cond As Mixed, Byref step_var As Mixed ) As Integer
         If step_var < 0 Then
               Return this >= end_cond
         Else
               Return this <= end_cond
         End If
   End Operator

   '============================================================================
#EndIf

now the following example works with assocarray.bi found here viewtopic.php?f=7&t=11538
you need to change line 14 of assocarray.bi to

Code: Select all

Dim As ZString Ptr chars = cast(zstring ptr,StrPtr(Key))

example of using Mixed assocarray

Code: Select all

#include "assocarray.bi"
#include "mixed.bi"

DefineAssocArrayType( Mixed )

Dim array As MixedArray

array.Item("color name") = "red"
array.Item("color value") = &HFF0000
array.Item(10) = "Ten"
array.Item(100) = 100
array.Item("***") = 555

Print "array.Item(""color name"") = ";array.Item("color name")
Print "array.Item(""color value"") = ";hex(cint(array.Item("color value")))
Print "array.Item(10) = ";array.Item(10)
Print "array.Item(100) = ";array.Item(100)
Print "array.Item(""***"") = ";array.Item("***")

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest