Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2012-03

FPC Advanced Records

10 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mark Morgan Lloyd

Can an Advanced Record, i.e. a record which as well as having fields has at least one embedded function, be safely used as a cast or type transfer overlaying unstructured bytes?

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Mark Morgan Lloyd
to Jonas Maebe
Jonas Maebe wrote 5 lines
On 09 Mar 2012, at 21:38, Mark Morgan Lloyd wrote: > Can an Advanced Record, i.e. a record which as well as having fields has at least one embedded function, be safely used as a cast or type transfer overlaying unstructured bytes? Yes.

Thanks Jonas, I don't think I need to do it but I thought it was a fair question: better safe than sorry.

OK, so hopefully I can get away with another. I'm looking at a program written in Delphi, which reads a file containing the image of an IBM mainframe tape. This has a record:

Type TAWSHeader=Record

        ThisSize: Word;

..

ThisSize is defined as being in Intel-style little-endian format, so I'm going to have problems if compiling the program for SPARC or (hypothetically) zSeries which are big-endian. If I understand things correctly I can do this:

Type TAWSHeader=Record
        ThisSizeLE: Word;
        function ThisSize: Word;
..

but is there any way to define something like an endianness-correcting type, i.e.:

Type TAWSHeader=Record

        ThisSize: WordLE;

..

where by the time ThisSize is accessed any disparity has been corrected?

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Jonas Maebe
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 7 lines
Thanks Jonas, I don't think I need to do it but I thought it was a fair question: better safe than sorry. OK, so hopefully I can get away with another. I'm looking at a program written in Delphi, which reads a file containing the image of an IBM mainframe tape. This has a record: Type TAWSHeader=Record ThisSize: Word; ..

If you want a record to have a predictable layout, always either a) use {$packrecords c} if it's a translation of a C struct, or b) declare it as "packed"

In other cases, you can (and will) have problems across different platforms or even compiler versions.

Show quoted text 7 lines
but is there any way to define something like an endianness-correcting type, i.e.: Type TAWSHeader=Record ThisSize: WordLE; .. where by the time ThisSize is accessed any disparity has been corrected?

No.

Jonas

Reply by email

Martin
to Mark Morgan Lloyd: Thanks Jonas, I don't think I need to do it but I thought it was a fair question: better…
Mark Morgan Lloyd wrote 10 lines
but is there any way to define something like an endianness-correcting type, i.e.: Type TAWSHeader=Record ThisSize: WordLE; .. where by the time ThisSize is accessed any disparity has been corrected?

Not sure if this will be of any use.

but you can always define an assignment incompatible type
    WordLE = record data: Word; end;

and define all required overloaded operators

Reply by email

Mark Morgan Lloyd
to Jonas Maebe: If you want a record to have a predictable layout, always either a) use {$packrecords c}…
Jonas Maebe wrote 15 lines
On 09 Mar 2012, at 22:26, Mark Morgan Lloyd wrote: > Thanks Jonas, I don't think I need to do it but I thought it was a fair question: better safe than sorry. > > OK, so hopefully I can get away with another. I'm looking at a program written in Delphi, which reads a file containing the image of an IBM mainframe tape. This has a record: > > Type TAWSHeader=Record > ThisSize: Word; > .. If you want a record to have a predictable layout, always either a) use {$packrecords c} if it's a translation of a C struct, or b) declare it as "packed" In other cases, you can (and will) have problems across different platforms or even compiler versions.

Thanks Jonas, noted (although I invariably put lots of Assert(SizeOf()=) in initialization). It's actually pretty simple stuff, but derives from a card IBM designed which had a mainframe (big-endian) processor on it but plugged into an MCA (little-endian) system.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Mark Morgan Lloyd
to Martin: Not sure if this will be of any use. but you can always define an assignment incompatible…
Martin wrote 18 lines
On 09/03/2012 21:26, Mark Morgan Lloyd wrote: > > but is there any way to define something like an endianness-correcting > type, i.e.: > > Type TAWSHeader=Record > ThisSize: WordLE; > .. > > where by the time ThisSize is accessed any disparity has been corrected? > Not sure if this will be of any use. but you can always define an assignment incompatible type WordLE = record data: Word; end; and define all required overloaded operators

I think that could be of a lot of use, but I'll need to tinker :-)

Noted your example, but apart from that is there any concise way to define a type such as WordLE with the explicit restriction that it requires an explicit definition of assignment operators (i.e. is never subject to implicit casts or type conversions)? Can this be done such that WordLE has a predefined size even if the assignment has to go via code?

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Sven Barth
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 29 lines
Martin wrote: > On 09/03/2012 21:26, Mark Morgan Lloyd wrote: >> >> but is there any way to define something like an >> endianness-correcting type, i.e.: >> >> Type TAWSHeader=Record >> ThisSize: WordLE; >> .. >> >> where by the time ThisSize is accessed any disparity has been corrected? >> > > Not sure if this will be of any use. > > but you can always define an assignment incompatible type > WordLE = record data: Word; end; > > and define all required overloaded operators I think that could be of a lot of use, but I'll need to tinker :-) Noted your example, but apart from that is there any concise way to define a type such as WordLE with the explicit restriction that it requires an explicit definition of assignment operators (i.e. is never subject to implicit casts or type conversions)? Can this be done such that WordLE has a predefined size even if the assignment has to go via code?

You could play around with a construct like the following:

type
   generic TMyLEType<T> = record
     Data: T;
     class operator := (aRight: TMyLEType): TMyLEType;
     class operator := (aRight: TMyLEType): T;
   end;
   TWordLE = specialize TMyLEType<Word>;
   TLongWordLE = specialize TMyLEType<LongWord>;
   // ...
class operator TMyLEType.:= (aRight: TMyLEType): TMyLEType;
begin
   Result.Data := aRight.Data
end;
class operator TMyLEType.:= (aRight: TMyLEType): T;
begin
   // convert the value to the correct endianess here
   // you might want to use SizeOf(T) for a determination of the
   // correct size of T, so you can swap correctly
end;

Regards,
Sven

Reply by email

Mark Morgan Lloyd
to Sven Barth
Sven Barth wrote 56 lines
Am 09.03.2012 23:26, schrieb Mark Morgan Lloyd: > Martin wrote: >> On 09/03/2012 21:26, Mark Morgan Lloyd wrote: >>> >>> but is there any way to define something like an >>> endianness-correcting type, i.e.: >>> >>> Type TAWSHeader=Record >>> ThisSize: WordLE; >>> .. >>> >>> where by the time ThisSize is accessed any disparity has been >>> corrected? >>> >> >> Not sure if this will be of any use. >> >> but you can always define an assignment incompatible type >> WordLE = record data: Word; end; >> >> and define all required overloaded operators > > I think that could be of a lot of use, but I'll need to tinker :-) > > Noted your example, but apart from that is there any concise way to > define a type such as WordLE with the explicit restriction that it > requires an explicit definition of assignment operators (i.e. is never > subject to implicit casts or type conversions)? Can this be done such > that WordLE has a predefined size even if the assignment has to go via > code? > You could play around with a construct like the following: type generic TMyLEType<T> = record Data: T; class operator := (aRight: TMyLEType): TMyLEType; class operator := (aRight: TMyLEType): T; end; TWordLE = specialize TMyLEType<Word>; TLongWordLE = specialize TMyLEType<LongWord>; // ... class operator TMyLEType.:= (aRight: TMyLEType): TMyLEType; begin Result.Data := aRight.Data end; class operator TMyLEType.:= (aRight: TMyLEType): T; begin // convert the value to the correct endianess here // you might want to use SizeOf(T) for a determination of the // correct size of T, so you can swap correctly end;

Thanks. Thinking about it, Martin's example probably fits my criteria of conciseness etc.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Ludo Brands
to Martin: Not sure if this will be of any use. but you can always define an assignment incompatible…
Show quoted text 11 lines
> > where by the time ThisSize is accessed any disparity has been > corrected? > Not sure if this will be of any use. but you can always define an assignment incompatible type WordLE = record data: Word; end; and define all required overloaded operators

Or an endian independant implementation:

type
  wordLE=packed record
    L1,L2:byte;
  end;
operator := (w1:word) w2:wordLE;
  begin
    w2.L2:=(w1 shr 8) and $FF;
    w2.L1:=w1 and $FF;
  end;
operator := (w1:wordLE) w2:word;
  begin
    w2:=((w1.L2 shl 8) and $FF00 ) or word(w1.L1);
  end;

Ludo

Reply by email