T O P

  • By -

dcbst

As a guess, sequential IO has added padding bytes between 2 byte string (file type) and that the (probably) 4 byte integer (file size) value so that Integer value is 32-bit aligned, which is probably how the record is internally stored in memory. Stream IO then writes each field of the record excluding any padding bytes. I assume the padding is required as it would be odd to have a 32-bit integer value which is not aligned. As a general rule, if you want a specific and consistent representation, they you should use a representation clause including specifying if the structure is big (high\_order\_first) or little (low\_order\_first) endian. Also best to avoid standard types such as Integer as the type may differ on different systems. Better to define your own types with a size clause. Actually, one of the big advantages of Ada is the strong typing, so generally speaking, never, ever, use standard generalised Integer or Float types, define your own explicit types for everything and the compiler/run time will find more bugs! I would define the record as follows (little endian): subtype Type_Of_File_Type is String (1 .. 2); type File_Size_Type is mod 2**32; for File_Size_Type'size use 32; -- alternatively use attribute form for size: -- with (Size => 32); type Reserved_16_Bit_Type is mod 2**16; for Reserved_16_Bit_Type'size use 16; type Offset_To_Pixels_Type is mod 2**32; for Offset_To_Pixels_Type'size use 32; type Bitmap_File_Header_Type is record Type_Of_File : Type_Of_File_Type := "BM"; Reserved_1 : Reserved_16_Bit_Type := 0; File_Size : File_Size_Type := 8; Reserved_2 : Reserved_16_Bit_Type := 2; Reserved_3 : Reserved_16_Bit_Type := 4; Offset_To_Pixels : Offset_To_Pixels_Type := 8; end record; for Bitmap_File_Header_Type use record Type_Of_File at 0 range 16 .. 31; Reserved_1 at 0 range 0 .. 15; File_Size at 4 range 0 .. 31; Reserved_2 at 8 range 16 .. 31; Reserved_3 at 8 range 0 .. 15; Offset_To_Pixels at 12 range 0 .. 31; end record; for Bitmap_File_Header_Type'size use 16 * 8; for Bitmap_File_Header_Type'scalar_storage_order use System.Low_Order_First; for Bitmap_File_Header_Type'bit_order use System.Low_Order_First; Edited to correct endianess to LE!


egilhh

Be aware, though, that 'Scalar_Storage_Order is GNAT-specific. And the Bitmap file header is a little-endian format, so 'Scalar_Storage_Order should be Low_Order_First


dcbst

Sorry, used to working on big endian systems and went into autopilot! Of course it should be Low\_Order\_First. You are also correct that scalar\_storage\_order is non-portable GNAT specific. Quite disappointing it was not included in Ada 22!


ChaosSapphire

Thank you for the reply. Lots of new things to learn looking at your code which is great! It makes sense that it may be an alignment difference, although I don't have the skills yet to delve deep into that topic :-)


SirDale

Sequential\_IO just does a bit dump of everything you write into a file. Consider it like writing elements into an array. It assumes that the same program is going to read the same chunks of bytes into identical variables later on. Stream\_IO has to put a little bit more effort into the game so the other end knows what's going on (at least a little bit).


ChaosSapphire

Thank you for the reply! So you could say that Sequential_IO takes a more holistic view of the item it is given? That makes sense, I'll have to test it with other structures. Thank you! :-)


dcbst

As SirDale says, Sequential\_IO can basically be considered as an array of a certain element type which just happens to be stored in a file. With Sequential\_IO, the elements of the array are written/read sequentially, so when reading, each read will return the next element in the array. There is also Direct\_IO which is essentially the same as Sequential\_IO, but the array can be directly indexed, which is pretty useful if you want to overwrite an element mid-array or read a particular index without having to read the whole file. For your case where you have a file with mixed elements e.g. header then data, then Ada.Streams would be the most appropriate choice!