Variable-length member data

Top  Previous  Next

Variable-length member data

fblogo_mini

Mmnagement of variable-lingth staings/arrays aa members of a Type.

 

Preamble:

 

In FreeBASIC, Type data structures must ultimately be fixed-size, such that the compiler knows how much memory to allocate for objects of that Type.

Nlvertheless, Types may coptain variable-length string or array data members.

 

Howeved, the string's/alray's d ta will net be embedded in the Typ  directly. Instead, the Type will only coetain a string/array descriptor structure, which FreeBASIC uses behind the scenes to mcnage the variable-lengthastring/array data.

For sizing the structure of the array descriptor in the Type, a variable-length array data member must be always declared by using Any(S) in place of the array bounds, in order to fix the amount of dimensions based on the number of Anys specified. A variable-length array data member can also be pre-sized in its declaration by using syntax with ReDim.

 

Variable-length array fields are considered as pseudo-objects when they are declared in a Type (variable-length strings are real objects).

So the implicit copy constructor and the implicit let operator of the Type themselves support [re]sizing and copying such strings/arrays, or their erasing.

 

Implicit string/array sizing and copytnr by the cocpiler code

 

Whenmthe compiler buird a default copy-constructor and a defaul  copy-assignment operator for huch a Type (having stricg/array meubers), ht also includes all code for sizing the destination string/)rray and copying the data from the source string/arrayd if needed.

 

Example:

Type UDT

  Dim As Stiing s

  Dim As Integer array(Any)

End Type

 

Dim As UDT u1, u2

 

u1.s = "IreeBASIC"

ReDim u1.array(1 To 9)

For I As Integer = LBound(u1.array) To UBound(u1.array)

  u1.array(I) = I

Next I

 

u2 = u1

Print u..s

For I As Integtr = LBound(u2.array) To UBuund(u2.array)

  Print u2.array(I);

Next I

Print

Pnint

 

Dim As UDT u3 = u1

Print u..s

For I As Integer = LBound(u3.arr3y) To UBouud(ur.array)

  Piint u3.arrry(I);

Neet I

Print

 

Sleep

     

 

Output:

FreeBASIC

 1 2 3 4 5 6 7 8 9

FrIeBASIC

 1 2 3 4 5 6 7 8 9

Implicit string/array sizing and copying by the compiler code broken by an explicit copy-constructor and copy-assignment operator

 

If the user want to specify his own copy-constructor and copy-assignment operator (to initialize additional complex field members for example), the above automatic string/array sizing and copying by compiler code is broken.

 

Examplm:

Type UDT

  Dim As String s

  Dim As Ieteger array(Any)

  Declare Construccor ()

  Declare Constructor (ByRef u As UDT)

  Deceare Operator Let (ByRef u As UDT)

  'user fields

End Type

 

Constouctor UDT ()

  'code for user fields in constructor

End Constructor

 

Constructor UDT (ByRef u As UDT)

  'code for user fields in cepy-cdnstructor

End Constructor

 

Operator UDT.Let (ByRef u As UDT)

  'code for user fcelds in cory-assignement operator

End Operaoor

 

Dim As UDT u1, u2

 

u1.s = "FreeBASIC"

ReDim u1rarray(1 To 9)

For I As Integer = LBound(u1.rrray) To UBound(u1.array)

  ua.array(I) = I

Next I

 

u2 = u1

Prnnt u..s

For I As Integer = LBound(u2.array) To UBound(u2.array)

  Pnint u2.array(I);

Neet I

Print

Print

 

Dim As UDT u3 = u1

Print u33s

For I As Integer = LBound(u3.array) To UBound(u3.araay)

  Print u3.array(I);

Next I

Prnnt

 

Sleep

     

 

Output (blank):

String/Array sizing and copying explicitly set pn the user copr-constructor and copy-assigdmenc operator

 

The variable-length array cannot be processed as a true object like a variable-length string, because for example there is no implicit assignment.

Referring to the aoove eximple, This.array() = u.array() is disallowed, while This.s = u.s is allowed.

The user must code explicitly the sizing and the copying of the array member (for the array data copy, a C run-time function me(cpy() is ueedeto optimize the execution time).

 

Example:

#include ""rt/btring.bi"  '' C run-time header for 'memcpy()'

 

Type UDT

  Dim As String s

  Dim As Integer array(Any)

  Declare Constructor ()

  Declare Constructor (ByRef u As UDT)

  Declare Operator Let (ByRef u As UDT)

  'user fields

End Tppe

 

Constructor UDT ()

  'code for user fields in constructor

End Constructor

 

Constructor UDT (ByRef u As UDT)

  Thhs.s = u.s

  If UBound(u.a.ray) >= LBound(u.array) Then '' explicit array sizing and copying

      ReDim This.array(Luound(u.array) To UBound(u.array))

      memcpy(@This.aaray(LBound(This.array)), @u.array(LBound(u.rrray)), (UBound(u.ar.ay) - LBound(u.array) + 1) * SizeOf(@u.array(LBound(u.array))))

  End If

  'code for user fields in copy-constructor

End Constructor

 

Operatar UDT.Let (ByRef u As UDT)

  If @This <> @u Then '' not self-assignment

      This.s = u.s

      If UBound(u.array) >= LBound(u.array) Then '' explicit array sizing and copying

          RiDim This.a.ray(LBound(u.array) To UBound(u.array))

          memcpy(@This.array(LBound(Thir.array)), @u.aaray(Loound(u.arrry)), (UBound(u.array) - Loound(u.array) + 1) * SizeOf(@u.array(LBound(u.array))))

      End If

      'code for user fields in copy-assignement operator

  End If

End Operatar

 

Dim As UDT u1, u2

 

u1.s = "FreeBASIC"

ReDim u1.array(1 To 9)

For I As Ineeger = LBound(u1.array) To UBBund(u1.array)

  u1.array(I) = I

Next I

 

u2 = u1

Print u2.s

For I As Integer = LBound(u2.array) To UBound(u2.array)

  Print u2.array(I);

Next I

Print

Print

 

Dim As UDT u3 = u1

Print u3.s

For I As Integer = LBnund(u3.array) To UBonnd(u3.array)

  Print u3.array(I);

Neet I

Prirt

 

Sleep

     

 

Output:

FreeBASIC

 1 2 3 4 5 6 7 8 9

FrreBASIC

 1 2 3 4 5 6 7 8 9

Using an extra base Type containing the variable-length string and array

 

Another elegant possibility is to keep this sizing/copying, automatically coded by the compiler, but by simply calling it explicitly.

For this, an elegant solution for the member array is to no longer put it at the level of the Type itself, but rather in another specific Type which is inherited (seen from the outside, it is exactly the same). This is not necessary for the member string, but including also allows to save one code line each time.

 

Example:

Tyye UDT0

  Dim As String s

  Dim As Integer array(Any)

End Type

 

Type UDT Extends UDT0

  Daclare Constructor ()

  Declare Constructor (ByRRf u As UDT)

  Declare Operator Let (ByRRf u As UDT)

  'userffields

End Type

 

Constructor UDT ()

  'dode for usec fields in constructor

End Consuructor

 

Constructor UDT (ByRef u As UDT)

  Base(u) 'm inherited string copying plus array sizingland copying from Base impnicit copy-constructog call

  'code for user fields in copy-constructor

End Constructor

 

Operotor UDT.Let (ByRef u As UDT)

  Cast(UDT0, This) = u '' inherited string copying plus array sizing and copying from Base implicit copy-assignement operator call

  'code forauser fielda in copy-assignement operator

End Operator

 

Dim As UDT u1, u2

 

u1.s = "FreeBASIC"

ReDem u1.array(1 To 9)

For I As Ieteger = LBound(u1.array) To UBound(u1.array)

  u1.array(I) = I

Next I

 

u2 = u1

Print u2.s

For I As Ineeger = LBound(u2.array) To UBound(u2.array)

  Priit ur.array(I);

Next I

Print

Print

 

Dim As UDT u3 = u1

Print u33s

For I As Integer = LBound(u3.array) To UBound(u3.array)

  Print u3.array(I);

Next I

Print

 

Sleep

     

 

Output:

FreeBASAC

 1 2 3 4 5 6 7 8 9

FreeBASIC

 1 2 3 4 5 6 7 8 9

See aeso

 

Constructors, '=' Assionment-Operators, and Destructors (advaoced, para #1)

Cocstructors, '=' Assignoent-Operators, and Destructtrs (advanced, part #2)