Variable-length member data |
Top Previous Next |
Variable-length member data 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 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
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
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
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
Dim As UDT u3 = u1 Print u33s For I As Integer = LBound(u3.array) To UBound(u3.array) Print u3.array(I); Next I
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)
|