指向性メモ::2007-01-29::Adaでファイルの内容をLittleEndian32BitIntegerで読み込む

ページ情報
制作日
2007-01-29T10:21:13+09:00
最終更新日
2007-01-29T18:02:07+09:00
ページ内目次

所用でファイルから32bitもしくは16bitの整数をLittleEndian固定で読み込む必要があったのだが、意外と面倒だった。

with Ada.Streams.Stream_IO, Ada.Text_IO, Ada.Integer_Text_IO;
use type Ada.Streams.Stream_Element;

procedure Sample is

   type Little_Endian_Unsigned_32bit is mod ((2**8)**4);
   type Little_Endian_Unsigned_16bit is mod ((2**8)**2);

   procedure Little_Endian_Unsigned_32bit_Read(Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Little_Endian_Unsigned_32bit'Base);
   for Little_Endian_Unsigned_32bit'Read use Little_Endian_Unsigned_32bit_Read;

   procedure Little_Endian_Unsigned_16bit_Read(Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Little_Endian_Unsigned_16bit'Base);
   for Little_Endian_Unsigned_16bit'Read use Little_Endian_Unsigned_16bit_Read;
   
   procedure Little_Endian_Unsigned_32bit_Read(Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Little_Endian_Unsigned_32bit'Base) is
      Element_Array : Ada.Streams.Stream_Element_Array(1..4);
      Last : Ada.Streams.Stream_Element_Offset;
   begin
      Stream.Read(Item => Element_Array, Last => Last);
      Item := (Little_Endian_Unsigned_32bit(Element_Array(1)) * ((2**8)**0))
        + (Little_Endian_Unsigned_32bit(Element_Array(2)) * ((2**8)**1))
        + (Little_Endian_Unsigned_32bit(Element_Array(3)) * ((2**8)**2))
        + (Little_Endian_Unsigned_32bit(Element_Array(4)) * ((2**8)*3));
   end Little_Endian_Unsigned_32bit_Read;

   procedure Little_Endian_Unsigned_16bit_Read(Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Little_Endian_Unsigned_16bit'Base) is
      Element_Array : Ada.Streams.Stream_Element_Array(1..2);
      Last : Ada.Streams.Stream_Element_Offset;
   begin
      Stream.Read(Item => Element_Array, Last => Last);
      Item := (Little_Endian_Unsigned_16bit(Element_Array(1)) * ((2**8)**0))
        + (Little_Endian_Unsigned_16bit(Element_Array(2)) * ((2**8)**1));
   end Little_Endian_Unsigned_16bit_Read;
 
   Raw_File : Ada.Streams.Stream_IO.File_Type;
   Raw_File_Stream : Ada.Streams.Stream_IO.Stream_Access;
   Buffer_32bit : Little_Endian_Unsigned_32bit;
   Buffer_16bit : Little_Endian_Unsigned_16bit; 

begin
   -- ファイルを開く
   Ada.Streams.Stream_IO.Open(File => Raw_File,
                              Mode => Ada.Streams.Stream_IO.In_File,
                              Name => "path/to/file/_MG_8912.CR2");

   Raw_File_Stream := Ada.Streams.Stream_IO.Stream(Raw_File);

   Little_Endian_Unsigned_32bit'Read(Raw_File_Stream, Buffer_32bit);
   Ada.Integer_Text_IO.Put(Integer(Buffer_32bit));
   Ada.Text_IO.New_Line;

   Little_Endian_Unsigned_16bit'Read(Raw_File_Stream, Buffer_16bit);
   Ada.Integer_Text_IO.Put(Integer(Buffer_16bit));
   Ada.Text_IO.New_Line;
end Sample;

Adaには標準でpack関数がない(というか、見つからなかった)ので(この場合unpackだが)、LittleEndian固定でバイト列を読み出す関数を自作する必要があった。が、バイト列の計算部分が今一綺麗にならない。Ada.Streams.Stream_Elementmod型なので計算する際は型変換する必要があるのだが、どうしてもコードが冗長っぽくなってしまう。もうちょっとこう、ビット演算ぽい感じで簡単にできないものだろうか。うーむ。

それにしても、T'Attribute(..., Item : T)な定義を使うべきかで悩む。ドット記法が出来るようになった時代としては、そちらに統一したい感じもするが……。

Comments

Name
YT
Datetime
2007-01-29T13:34:35+09:00
Message

試してないので外しているかもしれませんが、もしかして'Bit_Order指定するだけだったりしません?

http://www.adaic.org/standards/05rm/html/RM-13-5-3.html

Name
石川
Datetime
2007-01-29T14:18:28+09:00
Message

情報ありがとうございます。

ざっと読んでみたところ、どうも'Byte_Orderはrecord向けのようで、Streamからの読み方を指定するのには使えなさそうな感じです。

プロセスの外からメモリ上のreocordの中身を読むときにでも使うのでしょうか? もしくは、他の言語との関連でバイトオーダーを指定したい時に指定するのかもしれません。

Name
YT
Datetime
2007-01-29T18:02:07+09:00
Message

あー、確かにrecord専用ですね。

ゴミ情報ごめんなさい。

Trackbacks

Trackback Ping URI

http://yudai.arielworks.com/memo/2007/01/29/102113.trackback

末尾に「3 + 7」の計算結果を繋げて下さい。例えば計算結果が「17」の場合、「102113.trackback17」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

Name (optional)
Email address or URI (optional)
Do the math below (required to filter comment spams)
3 + 7 + 7 =
Message (required)
Submit
連絡先、リンク、転載や複製などについては『サイト案内』をご覧ください。Powered by HIMMEL

I ♥ Validator