Record buffer assignment

Basic assignment

The statement record_id1 = record_id2 assigns the data in all fields in record_id2 to the identically named fields in record_id1. Fields in record_id1 with no matching name in record_id2 are unchanged. Both record_id1 and record_id2 may be the names of files or of temporary record layouts. This enables a temporary copy of a file buffer to be made effortlessly, e.g:

!ofile File "data/testfile" update
!record Record {
  FirstDate,,i4/dn
  LastDate,,i4/dn
  Total,,i4
}

File = Record

In this example, all fields in the file “File” which bear identical field names (“FirstDate”, “LastDate” or “Total”) to fields in the temporary record structure “Record” are assigned the values of the corresponding fields in “Record”. Fields in the file that do not match fields in the record structure are not updated. The command Record = File has the reverse effect, updating fields in the temporary record structure from identically named fields in the file.

Note: When one record is a copy record of the other one, like in !record Record = File. The assignment is just a memory copy (fastest case).

Subscripts, field arrays and record arrays

If a !record with dimensions is refered using a subscript (possible since version 6.2.0), the subscript always refers to the !record array dimension and never to any field array it contains.

When the two !record’s do not define dimensions, the assignment follows the rules defined before Sculptor version 6.2.0:

record1 = record2

No subscripts specified:

  • Fields that are arrays in both records have all common subscripts assigned (if the destination field array has the “a” flag, then it can be auto-redim’ed)

  • If a field is an array in one record but not in the other, the first element of the field array is used.

record1 = record2[i]

Subscript specified for source record only:

  • Fields that are arrays in both records have all common subscripts assigned (if the destination field array has the “a” flag, then it can be auto-redim’ed). If this is not the required behaviour, specify the subscript for both records.

  • If a record1 field is an array and the corresponding record2 field is not, the first element of the record1 field is used

  • If the record2 field is an array and the record1 field is not, element i of the record2 field array is used.

record1[i] = record2

Subscript specified for destination record only:

  • Fields that are arrays in both records have all common subscripts assigned (if the destination field array has the “a” flag, then it can be auto-redim’ed). If this is not the required behaviour, specify the subscript for both records.

  • If a record2 field is an array and the corresponding record1 field is not, the first element of the record2 field array is used.

  • If the record1 field is an array and the record2 field is not, element i of the record1 field array is used.

record1[i] = record2[j]

Subscripts specified for both records:

  • If a field is an array in both records, element j of the record2 field is assigned to element i of the record1 field. All other subscripts are ignored.

  • If a record2 field is an array and the corresponding record1 field is not, element j of the record2 field is assigned to the record1 field.

  • If the record1 field is an array and the record2 field is not, the record2 field is assigned to element i of the record1 field.

In all cases, fields that are non-array fields in both the source and destination records are always assigned, regardless of any subscripts specified.

Examples of non-dimension !record’s:

!record rec1 {
    fld,,i4[10]
}

!record rec2 {
    fld,,i4[5]
}

rec2[4] = rec1[6]
/* Assigns rec1.fld[6] into rec2.fld[4] */

rec2 = rec1
/* Assigns rec1.fld[1-5] into rec2.fld[1-5] */

rec1->fld->flags = "a"
rec2[2] = rec1
rec2 = rec1[7]
/* With "auto-redim" flag in both cases will redim rec2.fld and assign rec1.fld[1-10] into it */

Since Sculptor 6.2.0, when dealing with dimension (array) !record’s, the specified index is used for the record array (and not any containing field array), so that indexed position of the record array behaves like an un-subscripted record in the previous table.

These are the general rules:

record1 = record2

No subscripts specified:

  • When both records have no dimensions refer to previous table.

  • When one of the records has no dimensions, the other record is automatically indexed as 1.

  • When both !record’s are record arrays then all the common subscripts are assigned (if the destination record array has the RECFL_AUTOREDIM record flag, then it may be auto-redim’ed)

record1 = record2[i]

Subscript specified for source record only:

  • If record1 is a dimension record, then is automatically indexed as 1.

  • If record2 is a non-dimension record the previous table should be used.

  • Otherwise element i of the record2 array is used.

record1[i] = record2

Subscript specified for destination record only:

  • If record2 is a dimension record, then is automatically indexed as 1.

  • If record1 is a non-dimension record the previous table should be used.

  • Otherwise element i of the record1 array is overwritten.

record1[i] = record2[j]

Subscripts specified for both records:

  • When both records have no dimensions refer to previous table.

  • When one of the records has no dimensions, the index is used as explained in the previous table.

  • When both !record’s are record arrays then all the specified subscripts are assigned (record1 and recurd2 may be the same record)

Examples of dimension !record’s:

!record rec {
    fld,,i4[10]
}

!record recArray[5] {
    fld,,i4[5]
}

recArray[4] = rec[6]
recArray[4] = rec
/* Assigns rec.fld[1-5] into recArray[4].fld[1-5] */

recArray = rec
/* Assigns rec.fld[1-5] into recArray[1].fld[1-5] */

rec = recArray
rec = recArray[1]
/* Assigns recArray[1].fld[1-5] into rec.fld[1-5] */

recArray->fld->flags = "a"
recArray[2] = rec
/* Redim recArray.fld and assign rec.fld[1-10] into recArray[2].fld[1-10] */

recArray[2] = recArray[5]
/* Overwritte position 2 with position 5 */

rec = recArray[1]
recArray[1] = recArray[4]
recArray[4] = rec
/* Swap positions 1 & 4 */

Example with auto-redim:

!record recArray[5] {
    fld,,i4[5]
}

!record anotherArray[1] {
    fld,,i4[5]
}
anotherArray->flags = RECFL_AUTOREDIM
anotherArray = recArray
/* Redim anotherArray and copy the whole recArray[1-5] */

Assignments to/from non-record objects

When assigning a non-record to a record and vice-versa, the record buffer is treated as binary data, so it can be assigned directly to a binary field to store the whole !record object, this makes possible to have a kind of layout with the record information, e.g:

!record rec1 {
    fld,,a5[4]
    num,,i4
}
!record rec2 {
    fld,,a10[2]
    num,,i4
}
!temp binary,,b255

rec2.num = 3452
rec2.fld[1] = "abcdefghij"
rec2.fld[2] = "qwertytrew"

binary = rec2
rec1 = binary

/* Now:
 * rec1.fld[1] = "abcde"
 * rec1.fld[2] = "fghij"
 * rec1.fld[3] = "qwert"
 * rec1.fld[4] = "ytrew"
 * rec1.num = 3452
 */

Note: the assignment of a field array to a record object produces an undefined result and should not be used util defined (as whatever the current behaviour is, it may change in the future)

Nested record assignment

Since Sculptor version 6.2.0 record assignment works with copy records and non-copy records that happen to have the same field or subrecord names. When two subrecords have the same name these same rules are applied. When a subrecord name corresponds in the “other” record to a binary field. The subrecord buffer is copied into/from the binary field, E.g:

!record Rec_1 {
    txt,,a16
    !record Rec_1_1 {
        num,,i4[2]
        txt,,a8
    }
    num,,i4
    !record Rec_1_2 = Rec_1.Rec_1_1
}

!record Rec_2 = Rec_1

!record Rec_3 {
    txt,,a16
    !record Rec_1_1 {
        num,,i4[2]
        txt,,a8
    }
    num,,i4
    !record Rec_1_2 = Rec_3.Rec_1_1
}

/* Record with binary fields to test the binary copy of subrecords */
!record BinRec {
    txt,,a16
    Rec_1_1,,b16
    num,,i4
    Rec_1_2,,b16
}

Rec_1.txt = ...

/* Copy records case -> Faster, just a buffer copy */
Rec_2 = Rec_1

/* Similar record -> Slower check all fields, subrecords, subfields... */
Rec3 = Rec_1

/* Binary fields -> copies subrecords into binary fields and vice-versa */
BinRec = Rec_1
Rec_2 = BinRec

RELATED TOPICS

!record

![o]file

RECFL_ flags

redim()