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?
Mailing lists / fpc-pascal / 2012-03
FPC Advanced Records
10 messages · 5 people · –
- MMark Morgan Lloyd 5
- JJonas Maebe 2
- LLudo Brands 1
- MMartin 1
- SSven Barth 1
Reply by email Subscribe to this list Your subscription
Read-only archive. Use j and k to move between messages.
Mark Morgan Lloyd wroteCan 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.
Jonas
Jonas Maebe wrote 5 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;..
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 wrote 7 lines
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
No.
Jonas
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
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
If you want a record to have a predictable layout, always either a) use {$packrecords c}…
Jonas Maebe wrote 15 lines
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.
Not sure if this will be of any use. but you can always define an assignment incompatible…
Martin wrote 18 lines
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 wrote 29 lines
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
Sven Barth wrote 56 lines
Thanks. Thinking about it, Martin's example probably fits my criteria of conciseness etc.
Not sure if this will be of any use. but you can always define an assignment incompatible…
Show quoted text 11 lines
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
