Revision [16119]
This is an old revision of KeyPgType made by FxMwikki on 2012-02-09 02:52:24.
TYPE
Declares a user-defined type.
Syntax:
Type typename
End Type
End Type
Type typename [ KeyPgExtends Extends base_typename ] [ KeyPgField Field = alignment ]
[ KeyPgVisPrivate Private: ]
[ KeyPgVisPublic Public: ]
[ KeyPgVisProtected Protected: ]
KeyPgDeclare declare [ KeyPgConstMember Const ] KeyPgConstructor constructor [ ( [ parameters ] ) ]
KeyPgDeclare declare [ KeyPgConstMember Const ] KeyPgDestructor destructor [ () ]
KeyPgDeclare declare [ KeyPgStaticMember Static | KeyPgConstMember Const ] KeyPgMemberSub sub fieldname [calling convention specifier] [ KeyPgAlias alias external_name ] [ ( [ parameters ] ) ] [ KeyPgStatic Static ]
KeyPgDeclare declare [ KeyPgStaticMember Static | KeyPgConstMember Const ] KeyPgMemberFunction function fieldname [calling convention specifier] [ KeyPgAlias alias external_name ] [ ( [ parameters ] ) ] [ KeyPgAs as DataType datatype ] [ KeyPgStatic Static ]
fieldname [ ( array subscripts ) | : bits ] KeyPgAs as DataType DataType [ = initializer ]
KeyPgAs as DataType DataType fieldname [ ( array subscripts ) | : bits ] [ = initializer ], ...
KeyPgDeclare declare [ KeyPgConstMember Const ] KeyPgOperator operator operatorname[ ( [ parameters ] ) ]
KeyPgDeclare declare [ KeyPgConstMember Const ] KeyPgProperty property fieldname[ ( [ parameters ] ) ] [ KeyPgAs as DataType datatype ]
...
End Type[ KeyPgVisPublic Public: ]
[ KeyPgVisProtected Protected: ]
KeyPgDeclare declare [ KeyPgConstMember Const ] KeyPgConstructor constructor [ ( [ parameters ] ) ]
KeyPgDeclare declare [ KeyPgConstMember Const ] KeyPgDestructor destructor [ () ]
KeyPgDeclare declare [ KeyPgStaticMember Static | KeyPgConstMember Const ] KeyPgMemberSub sub fieldname [calling convention specifier] [ KeyPgAlias alias external_name ] [ ( [ parameters ] ) ] [ KeyPgStatic Static ]
KeyPgDeclare declare [ KeyPgStaticMember Static | KeyPgConstMember Const ] KeyPgMemberFunction function fieldname [calling convention specifier] [ KeyPgAlias alias external_name ] [ ( [ parameters ] ) ] [ KeyPgAs as DataType datatype ] [ KeyPgStatic Static ]
fieldname [ ( array subscripts ) | : bits ] KeyPgAs as DataType DataType [ = initializer ]
KeyPgAs as DataType DataType fieldname [ ( array subscripts ) | : bits ] [ = initializer ], ...
KeyPgDeclare declare [ KeyPgConstMember Const ] KeyPgOperator operator operatorname[ ( [ parameters ] ) ]
KeyPgDeclare declare [ KeyPgConstMember Const ] KeyPgProperty property fieldname[ ( [ parameters ] ) ] [ KeyPgAs as DataType datatype ]
...
Parameters:
alignment
Specifies the byte alignment for data fields.
fieldname
Name of the data field or member procedure.
external_name
Name of field as seen when externally linked.
parameters
The parameters to be passed to a member procedure.
array subscripts
Subscripts to declare a fixed-length array.
bits
Number of bits a data field occupies (only valid for integer numeric data-types up to 32-bit types).
initializer
Default initializer for the data field.
operatorname
The name of the operator to be overloaded.
calling convention specifierDescription:
Type is used to declare custom data types containing one or more bit, scalar, array or other Type fields.
Types support member functions including KeyPgConstructor Constructor, KeyPgDestructor Destructor, KeyPgMemberFunction Function, KeyPgOperator Operator, KeyPgProperty Property and KeyPgMemberSub Sub.
Fields default to KeyPgVisPublic Public: member access unless, KeyPgVisPrivate Private: or KeyPgVisProtected Protected: is specified.
An anonymous KeyPgUnion Union can be nested in a Type declaration.
KeyPgExtends Extends can optionally be used to create a user-defined type that is derived from another type and inherits its members.
The optional KeyPgField Field=number when given will change the default field alignment. KeyPgField Field=1 will disable any alignment, making the Type contiguous in memory.
Type can be used to return a temporary type variable. See KeyPgTypeTemp Type().
Type can be used to declare a type definition ( i.e. an alias or alternative name ) for an already declared or yet to be declared type. See KeyPgTypeAlias Type (Alias)
Data fields may have an optional default initializer value. This default value initializes the data field immediately before any constructor is called.
KeyPgStaticMember Static immediately preceding KeyPgMemberSub Sub or KeyPgMemberFunction Function indicates that no hidden KeyPgThis This parameter is to be passed to the member procedure.
KeyPgConstMember Const immediately preceding KeyPgMemberSub Sub, KeyPgMemberFunction Function, KeyPgConstructor Constructor, KeyPgDestructor Destructor, KeyPgProperty Property or KeyPgOperator Operator indicates that the hidden KeyPgThis This parameter is to be considered read-only.
Warning Special care must be taken when using a user defined type for file I/O. It is recommended to use Field = 1 for such cases, and it may be required to read files created by other applications.
UDTs that contain pointers to data should not be written to file as-is: when the data is read later, the pointers will almost certainly be invalid, and the data they pointed to will no longer be available. Instead, custom input/output routines should be used, to save the allocated data in a different format in the file. This includes UDTs containing variable-length strings.
Additionally, reading fixed length strings in UDT's from files is problematic: at present, fixed-length strings contain an extra NULL character on the end. To preserve alignment the field would need to be declared with one char less than the actual size and accessing the field by its name makes the last character unavailable. It also means there may be potential problems passing the string to functions that expect the NULL character to be there.
A better solution is to use ubyte arrays, this requires a couple of auxiliary functions converting to/from string. See the example.
The optional KeyPgField Field=number when given will change the default field alignment. KeyPgField Field=1 will disable any alignment, making the Type contiguous in memory.
Type can be used to return a temporary type variable. See KeyPgTypeTemp Type().
Type can be used to declare a type definition ( i.e. an alias or alternative name ) for an already declared or yet to be declared type. See KeyPgTypeAlias Type (Alias)
Data fields may have an optional default initializer value. This default value initializes the data field immediately before any constructor is called.
KeyPgStaticMember Static immediately preceding KeyPgMemberSub Sub or KeyPgMemberFunction Function indicates that no hidden KeyPgThis This parameter is to be passed to the member procedure.
KeyPgConstMember Const immediately preceding KeyPgMemberSub Sub, KeyPgMemberFunction Function, KeyPgConstructor Constructor, KeyPgDestructor Destructor, KeyPgProperty Property or KeyPgOperator Operator indicates that the hidden KeyPgThis This parameter is to be considered read-only.
Warning Special care must be taken when using a user defined type for file I/O. It is recommended to use Field = 1 for such cases, and it may be required to read files created by other applications.
UDTs that contain pointers to data should not be written to file as-is: when the data is read later, the pointers will almost certainly be invalid, and the data they pointed to will no longer be available. Instead, custom input/output routines should be used, to save the allocated data in a different format in the file. This includes UDTs containing variable-length strings.
Additionally, reading fixed length strings in UDT's from files is problematic: at present, fixed-length strings contain an extra NULL character on the end. To preserve alignment the field would need to be declared with one char less than the actual size and accessing the field by its name makes the last character unavailable. It also means there may be potential problems passing the string to functions that expect the NULL character to be there.
A better solution is to use ubyte arrays, this requires a couple of auxiliary functions converting to/from string. See the example.
Examples:
This is an example of a QB-style type, not including procedure definitions
Type clr
red As UByte
green As UByte
blue As UByte
End Type
Dim c As clr
c.red = 255
c.green = 128
c.blue = 64
red As UByte
green As UByte
blue As UByte
End Type
Dim c As clr
c.red = 255
c.green = 128
c.blue = 64
And this is an example of a type working as an object:
'' Example showing the problems with fixed length string fields in UDTs
'' Suppose we have read a GIF header from a file
'' signature width height
Dim As ZString*(10+1) z => "GIF89a" + MKShort(10) + MKShort(11)
Print "Using fixed-length string"
Type hdr1 Field = 1
As String*(6-1) sig /' We have to dimension the string with 1 char
' less to avoid misalignments '/
As UShort wid, hei
End Type
Dim As hdr1 Ptr h1 = CPtr(hdr1 Ptr, @z)
Print h1->sig, h1->wid, h1->hei '' Prints GIF89 (misses a char!) 10 11
'' We can do comparisons only with the 5 visible chars and creating a temporary string with LEFT
If Left(h1->sig, 5) = "GIF89" Then Print "ok" Else Print "error"
'' Using a ubyte array, we need an auxiliary function to convert it to a string
Function ub2str( ub() As UByte ) As String
Dim As Integer length = UBound(ub) + 1
Dim As String res = Space(length)
For i As Integer = 0 To length-1
res[i] = ub(i): Next
Function = res
End Function
Print
Print "Using an array of ubytes"
Type hdr2 Field = 1
sig(0 To 6-1) As UByte '' Dimension 6
As UShort wid, hei
End Type
Dim As hdr2 Ptr h2 = CPtr(hdr2 Ptr, @z)
'' Viewing and comparing is correct but a conversion to string is required
Print ub2str(h2->sig()), h2->wid, h2->hei '' Prints GIF89a 10 11 (ok)
If ub2str(h2->sig()) = "GIF89a" Then Print "ok" Else Print "error" '' Prints ok
'' Suppose we have read a GIF header from a file
'' signature width height
Dim As ZString*(10+1) z => "GIF89a" + MKShort(10) + MKShort(11)
Print "Using fixed-length string"
Type hdr1 Field = 1
As String*(6-1) sig /' We have to dimension the string with 1 char
' less to avoid misalignments '/
As UShort wid, hei
End Type
Dim As hdr1 Ptr h1 = CPtr(hdr1 Ptr, @z)
Print h1->sig, h1->wid, h1->hei '' Prints GIF89 (misses a char!) 10 11
'' We can do comparisons only with the 5 visible chars and creating a temporary string with LEFT
If Left(h1->sig, 5) = "GIF89" Then Print "ok" Else Print "error"
'' Using a ubyte array, we need an auxiliary function to convert it to a string
Function ub2str( ub() As UByte ) As String
Dim As Integer length = UBound(ub) + 1
Dim As String res = Space(length)
For i As Integer = 0 To length-1
res[i] = ub(i): Next
Function = res
End Function
Print "Using an array of ubytes"
Type hdr2 Field = 1
sig(0 To 6-1) As UByte '' Dimension 6
As UShort wid, hei
End Type
Dim As hdr2 Ptr h2 = CPtr(hdr2 Ptr, @z)
'' Viewing and comparing is correct but a conversion to string is required
Print ub2str(h2->sig()), h2->wid, h2->hei '' Prints GIF89a 10 11 (ok)
If ub2str(h2->sig()) = "GIF89a" Then Print "ok" Else Print "error" '' Prints ok
Platform Differences:
- The default field alignment is 4 bytes for DOS and Linux targets.
- The default field alignment is 8 bytes for Windows targets.
- Object-related features such as functions declared inside Type blocks are supported only with the CompilerOptlang -lang fb dialect since version 0.17b
- In the CompilerOptlang -lang fb and CompilerOptlang -lang fblite dialects, the default field alignment depends on the target platform.
- With the CompilerOptlang -lang qb dialect the fields are aligned to byte boundaries by default, unless otherwise specified.
- To force byte alignment use FIELD=1.
Differences from QB:
- At present, fixed-length strings have an extra, redundant character on the end, which means they take up one more byte than they do in QB. For this reason, UDTs that use them are not compatible with QB when used for file I/O.
See also:
- KeyPgTypeAlias Type (Alias)
- KeyPgTypeTemp Type (Temporary)
- KeyPgUnion Union
- KeyPgEnum Enum
- KeyPgTypeof Typeof
- KeyPgOffsetof OffsetOf
- KeyPgField Field
- KeyPgExtends Extends
- KeyPgWith With
Back to User Defined Types