1

I'm doing a bit of a file-format converting, and looking at some Delphi code I was able to get my hands on to decode the original format.

It's a binary file, and I have the function for how the information is written and read from this file, so most of the things are clear. I am however stumped on something.

Within the file there is a line where we read in a bunch of bits into Array[i]:

S.ReadBuffer(Array[i], sizeOf(Array[i]));

Now, I saw this thread, but I'm not sure the same applies to formats written through Delphi (although I would assume so?). How could I tell the actual sizeof for Array[i]? Just by counting the variables in the array I get 168 bits, but how do I properly pad them? Is there a way to get this information from stream declarations?

And I guess another question about this whole format is - do the parts of the struct (struct corresponding to Array[i]) get written in their declared order? What if it's a struct within a struct?

If it matters, I'm decoding it using a Matlab script (for now).

EDIT: Here is the structure declaration:

UsegDef = Record
    tinc: extended;
    cinc: extended;
    tA: LongInt;
    tB: LongInt;
    tC: LongInt;
    Arr: Array of seg;
end;

seg = Record
    val: smallint;
    time: longword;
    typ: byte;
end;
Community
  • 1
  • 1
Mewa
  • 502
  • 1
  • 9
  • 24
  • The answers to the questions can be found in the documentation. Do you know where to look? – David Heffernan Jun 17 '13 at 07:02
  • If the file is written to disk (at some point) there is no more padding since on disk it will be flattened out. – Remko Jun 17 '13 at 10:59
  • @DavidHeffernan, I'm not too sure. This is the first time I've encountered Delphi and I'm just all over confused. – Mewa Jun 17 '13 at 21:31
  • @Remko, aren't all files written to disk? Or where else are files stored? Or do you mean like a CD disk, not hard drive disk? – Mewa Jun 17 '13 at 21:31
  • @Remko Only if the writing is well done. If it's done with a blit then the padding will persist. And looking at the code, it's a blit. – David Heffernan Jun 17 '13 at 21:40
  • @Mewa The code in the question is clear. The in memory representation is blitted directly to and from the file. In which case why do you care about the layout? What are you actually trying to do? Read the file from a different language? What is your ultimate goal. – David Heffernan Jun 17 '13 at 21:42
  • @DavidHeffernan, I'm reading the binary file with Matlab, while it was originally written with Delphi. I am using fread(), where I can specify how many bits to read next and how to treat them (signed/unsigned/char etc). My goal is to read this file into Matlab arrays, and then either write into a file format that another program can use, or use Matlab to plot the data. As I said in the OP, my goal is to convert this file using a Matlab script. – Mewa Jun 17 '13 at 22:11
  • So, do you know how to proceed, or are you still stuck? – David Heffernan Jun 18 '13 at 06:15
  • Anyway, if you really do want any help, step one is to include the declaration of the record in the question. – David Heffernan Jun 18 '13 at 12:05
  • Added. Array in my original post is an array of UsegDef. I think I mostly figured it out, but now I don't know how long "extended" is... Apparently it depends on the OS, but I don't know what OS the code was originally compiled on. – Mewa Jun 19 '13 at 03:38

2 Answers2

1

It would help if you show the declaration type of the array element, but in case it isn't obvious Array[i] means the i'th array element and thus sizeof(Array[i]) is the size of one element in the array.

If the array element is a record (struct) type, then the default is to pad fields so that they start on a natural boundary in relation to their type - a 16-bit int starts at an offset divisible by 2 (16-bits), and so on.

If the packed modifier is used in the record declaration (rare) then no such padding is performed.

Fields are stored within each record in the order they are declared.

  • I figured sizeof(Array[i]) is size of one element, but the element is a struct and that's where it all went kind of downhill. The struct consists of the following variable types (in order that tehy are declared): extended, extended, long int, long int, long int, another struct {smallint, long word, byte}. So what I gathered from your explanation is that if we are writing an int, and the previous write ended on the 254th bit, we would have 2 bits of padding to get to 256 after which the int would follow? – Mewa Jun 17 '13 at 21:24
  • Byte, not bit, but yes. It's actually not too difficult to verify what the compiler is doing: If, for example, you have `type TRec = record b: byte; i: integer; end;` and then `var r: TRec;` you can write out the offsets of the two fields with `writeln(Dword(@r.b) - DWord(@r),' ',DWord(@r.i) - DWord(@r));`. (this assumes that you are using the 32-bit edition of the compiler) – 500 - Internal Server Error Jun 17 '13 at 22:41
0

You could place a breakpoint on hat line, and add a sizeof(array[i]) watch to see the actual size.

That's probably faster and less error-prone than counting manually via the sourcecode.

The size that you see depends on how the bytes are aligned. When I write a record to a file, I usually explicitly add packed to the type definition to make sure that values are aligned per byte, otherwise all bets are off about what actually gets written.

Wouter van Nifterick
  • 23,603
  • 7
  • 78
  • 122
  • I only have one file out of the entire program to go by for this file conversion thing. I'm not sure how I would compile anything :( If there was "packed", what do you mean they align per byte? Like lets say there is a random 10bit value that was written, how does that get handled? Thanks! – Mewa Jun 17 '13 at 21:34