views:

441

answers:

4

I would like to be able to predict what will be in the resulting binary when I call Write in Ada to serialize a record. Do you know where I can look this up?

I have some legacy Ada software that produces a binary file by Write-ing a record, and I need to debug a C++ program that is supposed to write a compatible binary file. So, I would like to understand what rules Ada follows when it serializes a record, so that I can make sure that the C++ code will produce a functionally equivalent record.

+1  A: 

The Ada95 Language Reference Manual says (section 13.13.2):

"For elementary types, the representation in terms of stream elements is implementation defined. For composite types, the Write or Read attribute for each component is called in a canonical order. The canonical order of components is last dimension varying fastest for an array, and positional aggregate order for a record."

Mike Dimmick
Thanks for the reference. I'm hoping that someone has written a little more expansively on the subject.
MOE37x3
Ada folks tend to be kind of sticklers for the standard. We don't have cannonical implementations to refer to. So if you ask "How does Ada do X?" and someone replies with "That is implemenation defied.", that's more or less the end of the matter.
T.E.D.
+3  A: 

Basically, the compiler will reorder the components of your record types, unless you use the pragma PACK or the pragma PRESERVE_LAYOUT commands with your record types. Also, the compiler will pad objects to maintain the alignment of record components. Components follow:

Integer: 8, 16, or 32 bit twos-complement signed numbers

Float: 32-bit IEEE format

Long_Float: 64-bit IEEE format

Fixed-Point: 8, 16, or 32 bit; however, the range and delta specified can affect being 16 or 32

Enumerations: Integer, usually first element is represented by 0

Booleans: Enumeration object, 8 bits long, The LSB stores the value: 0 = false, 1 = true

Characters: Enumeration object, 8 bits long, unsigned 0 through 127

Access Types: 32 bits, 32-bit value of 0 represents NULL

Arrays: stored contiguously in row-major order, size depends on base type. The array is padded to ensure all elements have the proper alignment for their types.

Dan
+2  A: 

As mentioned by others, without additional instruction the compiler will make its own decisions about record layout. The best approach would be to change the original code to write the record using a specific layout. In particular, the record representation clause allows the Ada programmer to specify exactly the physical layout for a record. In fact, you should check to see whether the original code has one of these for the type in question. If it does, then this would answer your question precisely.

Greg Hewgill
+3  A: 

The format of the serialised output of 'Write has absolutely nothing to do with representation clauses.

By default, the compiler will output record components without alignment padding in the order in which they're written in the record declaration, using a translation scheme that isn't defined by the standard (so you may not get interoperability between compilers). GNAT (the GCC Ada compiler) outputs each component in a whole number of bytes.

If you want to stream values of a type using some different format, you can override 'Write for the type. As an unusual example, you could stream to XML.

Simon Wright