From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: *** X-Spam-Status: No, score=3.2 required=5.0 tests=BAYES_00,RATWARE_MS_HASH, RATWARE_OUTLOOK_NONAME autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,ad5bd2429a45288e,start X-Google-Attributes: gid103376,public From: "David C. Hoos, Sr." Subject: Re: Recommended way of reading file as byte blocks Date: 1996/09/21 Message-ID: <01bba7c6$c6776fe0$0a8371a5@dhoossr.iquest.com> X-Deja-AN: 184445723 distribution: world references: <01BBA702.69F8B220@idc213.rb.icl.co.uk> content-type: text/plain; charset=ISO-8859-1 organization: DBH Enterprises, Inc. mime-version: 1.0 newsgroups: comp.lang.ada Date: 1996-09-21T00:00:00+00:00 List-Id: Simon Johnston wrote in article <01BBA702.69F8B220@idc213.rb.icl.co.uk>... Hi, I have tried a number of ways of doing this, reading a file as blocks of bytes. In most cases when the application is examined a better way is found, however I am now at a point where I am converting some C code which does: fp = fopen(...) i = fread(fp, buffer, 512) while (!feof(fp)) { for ( ; i > 0; i--) { .. } handle buffer i = fread(...) } and it really matters that this logic is preserved. I can open the file as a Direct_IO(Element => BYTE) file which is nasty, I have tried using Streams but never quite get it right. Any ideas? Thanks. Well, for what they're worth, here are my ideas. First, I want to point out that the correct call to fread is "i = fread (buffer, 1, 512, fp)", rather than "i = fread (fp, buffer, 512)", so the code which follows is based on that difference. I would make a generic package instantiated for the element type, and the "buffer" of elements. I have included a partial implementation here, just enough to show that it works. What I have tried to do here, is to preserve the syntax as close to that of C, as much as possible, to simplify translation. This involves some compromises. For example, you will get a compiler warning that The_Byte_Array is never assigned a value. This is because the Ada compiler doesn't know that the C library function to which we've interfaced is going to use the address we've passed it to tell where write the data. On the other hand, if we make the parameter of Fread an "out" parameter, we would have to make Fread a procedure, instead of a function, and, then the number of bytes read would also have to be an "out" parameter. This was my compromise in favor of preserving the C syntax. This code also illustrates the use of the Ada.Command_Line package, as well as some other Ada Features. The style is somewhat verbose, but I prefer to make the code sufficiently descriptive that the need for comments is reduced. ------------ source code begins --------------------- with Interfaces.C; with System; generic type ELEMENT_TYPE is private; type ELEMENT_ARRAY_TYPE is private; package stdio is -- This is only sufficiently completed so as to illustrate the principles package C renames Interfaces.C; use type C.INT; use type C.CHAR_ARRAY; use type C.SIZE_T; type FILE_TYPE is limited private; type FILE_ACCESS_TYPE is access FILE_TYPE; -- NOTE: From a strictly-Ada point-of-view, this type should be limited -- private, but to make it more closely mimic C, we make it assignable -- and copyable, etc., so Fopen can be a function instead of a procedure. function Fopen ( Name : in C.CHAR_ARRAY; Mode : in C.CHAR_ARRAY ) return FILE_ACCESS_TYPE; function Feof ( File : in FILE_ACCESS_TYPE ) return C.INT; function Fread ( Buffer : in ELEMENT_ARRAY_TYPE; Element_Size : in NATURAL := ELEMENT_TYPE'SIZE / System.STORAGE_UNIT; Number_Of_Elements : in NATURAL; File : in FILE_ACCESS_TYPE ) return C.SIZE_T; function Fclose ( File : in FILE_ACCESS_TYPE ) return C.INT; private type FILE_TYPE is null record; -- NOTE: Since we don't manipulate any of the components of C's * FILE -- directly, and since Fopen and Fclose handle allocation and deallocation, -- we don't really care what the Ada type is. pragma IMPORT (C, Fopen, "fopen"); pragma IMPORT (C, Feof, "feof"); pragma IMPORT (C, Fread, "fread"); pragma IMPORT (C, Fclose, "fclose"); end Stdio; with Ada.Command_Line; with Interfaces.C; with Stdio; with Ada.Text_IO; procedure SKJ is package C renames Interfaces.C; package CL renames Ada.Command_line; package Text_IO renames Ada.Text_IO; type BYTE is mod 256; type BYTE_ARRAY_TYPE is array (0 .. 511) of aliased BYTE; package Byte_Stdio is new Stdio ( Element_Type => BYTE, Element_Array_Type => BYTE_ARRAY_TYPE ); package Byte_IO is new Text_IO.Modular_IO (BYTE); use type C.INT; use type C.CHAR_ARRAY; The_Number_Of_Bytes_Read : C.SIZE_T; The_File : Byte_Stdio.FILE_ACCESS_TYPE; The_Byte_Array : aliased BYTE_ARRAY_TYPE; The_Status : C.INT; begin if CL.Argument_Count /= 1 then Text_IO.Put_Line ( File => Text_IO.Standard_Error, Item => "USAGE: " & CL.Command_Name & " " ); CL.Set_Exit_Status (1); return; end if; The_File := Byte_Stdio.Fopen ( Name => C.To_C (CL.Argument (1)), Mode => "r" & C.NUL ); if Byte_Stdio."=" (The_File, null) then Text_IO.Put_Line ( File => Text_IO.Standard_Error, Item => "Attempt to open file '" & CL.Argument (1) & "' for read failed" ); CL.Set_Exit_Status (2); return; end if; loop The_Number_Of_Bytes_Read := Byte_Stdio.Fread ( Buffer => The_Byte_Array, Number_Of_Elements => The_Byte_Array'LENGTH, File => The_File ); Text_IO.Put_Line ("Bytes Read =>" & C.SIZE_T'IMAGE (The_Number_Of_Bytes_Read)); for i in 0 .. INTEGER(The_Number_Of_Bytes_Read) -1 loop Byte_IO.Put (The_Byte_Array (i)); end loop; for i in 0 .. INTEGER(The_Number_Of_Bytes_Read) -1 loop Text_IO.Put (CHARACTER'VAL(The_Byte_Array (i))); end loop; exit when Byte_Stdio.Feof (The_File) /= 0; end loop; The_Status := Byte_Stdio.Fclose (The_File); if The_Status = 0 then The_File := null; else Text_IO.Put_Line ( File => Text_IO.Standard_Error, Item => "Attempt to close file '" & CL.Argument (1) & "' failed" ); CL.Set_Exit_Status (3); return; end if; end SKJ; ------------ source code ends --------------------- Hope this helps. -- David C. Hoos, Sr., http://www.dbhwww.com http://www.ada95.com