• String view of file

    From Jesper Quorning@21:1/5 to All on Mon Nov 21 00:30:00 2022
    I like to ask about

    Is it possible to write something like this with ADA

    ```Ada
    package my_rw_file is new file
    (name => "whatever"
    ,mode => read_write
    ,implementation => standard -- or portable or fast
    );
    package as_string is new. xxx(from => my_rw_file);

    -- parse (as_string);
    package data is new parse (as_string, format => markdown); -- or whatever
    ```

    Sorry, im new to ada


    Jesper Q

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From G.B.@21:1/5 to Jesper Quorning on Mon Nov 21 14:01:01 2022
    On 21.11.22 09:30, Jesper Quorning wrote:
    I like to ask about

    Is it possible to write something like this with ADA

    ```Ada
    package my_rw_file is new file
    (name => "whatever"
    ,mode => read_write
    ,implementation => standard -- or portable or fast
    );
    package as_string is new. xxx(from => my_rw_file);

    -- parse (as_string);
    package data is new parse (as_string, format => markdown); -- or whatever
    ```

    Do you mean, gobble up a file into a string
    and then parse that? Yes, that's possible
    in a number of ways.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Jesper Quorning on Mon Nov 21 14:48:47 2022
    On 2022-11-21 09:30, Jesper Quorning wrote:

    Is it possible to write something like this with ADA

    "Ada" is a woman's name, not an acronymn.

    package my_rw_file is new file
    (name => "whatever"
    ,mode => read_write
    ,implementation => standard -- or portable or fast
    );
    package as_string is new. xxx(from => my_rw_file);

    -- parse (as_string);
    package data is new parse (as_string, format => markdown); -- or whatever

    If I presume that the '.' in the declaration of As_String is a typo, what you have here is a sequence of related generic pkg instantiations, so you can write this in Ada if you have the corresponding generic pkgs. I have no idea what the result would provide.

    If you want to read the arbitrary contents of a file into a String, that's easily done:

    with Ada.Directories;

    package String_A_File is
    use type Ada.Directories.File_Size;

    function File_As_String (Name : in String) return String with
    Pre => Ada.Directories.Exists (Name) and then
    Ada.Directories.Size (Name) <=
    Ada.Directories.File_Size (Integer'Last),
    Post => File_As_String'Result'First = 1 and
    File_As_String'Result'Last =
    Integer (Ada.Directories.Size (Name) );
    end String_A_File;

    with Ada.Sequential_IO;

    package body String_A_File is
    function File_As_String (Name : in String) return String is
    subtype FAS is String (1 .. Integer (Ada.Directories.Size (Name) ) );

    package FAS_IO is new Ada.Sequential_IO (Element_Type => FAS);

    File : FAS_IO.File_Type;
    Result : FAS;
    begin -- File_As_String
    FAS_IO.Open (File => File, Mode => FAS_IO.In_File, Name => Name);
    FAS_IO.Read (File => File, Item => Result;
    FAS_IO.Close (File => File);

    return Result;
    end File_As_String;
    end String_A_File;

    This presumes that Result will fit on the stack. If that's likely to be a problem, then you will need to use Unbounded_String and read the file Character by Character.

    --
    Jeff Carter
    "I have a very small head and I had
    better learn to live with it ..."
    Edsger Dijkstra
    158

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Niklas Holsti@21:1/5 to Jeffrey R.Carter on Mon Nov 21 17:52:14 2022
    On 2022-11-21 15:48, Jeffrey R.Carter wrote:
    On 2022-11-21 09:30, Jesper Quorning wrote:

    Is it possible to write something like this with ADA

    "Ada" is a woman's name, not an acronymn.

    package my_rw_file is new file
       (name => "whatever"
        ,mode => read_write
        ,implementation => standard -- or portable or fast
       );
    package as_string is new. xxx(from => my_rw_file);

    -- parse (as_string);
    package data is new parse (as_string, format => markdown); -- or whatever

    If I presume that the '.' in the declaration of As_String is a typo,
    what you have here is a sequence of related generic pkg instantiations,
    so you can write this in Ada if you have the corresponding generic pkgs.
    I have no idea what the result would provide.

    If you want to read the arbitrary contents of a file into a String,
    that's easily done:

    with Ada.Directories;

    package String_A_File is
       use type Ada.Directories.File_Size;

       function File_As_String (Name : in String) return String with
          Pre  => Ada.Directories.Exists (Name) and then
                  Ada.Directories.Size (Name) <=
                  Ada.Directories.File_Size (Integer'Last),
          Post => File_As_String'Result'First = 1 and
                  File_As_String'Result'Last =
                  Integer (Ada.Directories.Size (Name) );
    end String_A_File;

    with Ada.Sequential_IO;

    package body String_A_File is
       function File_As_String (Name : in String) return String is
          subtype FAS is String (1 .. Integer (Ada.Directories.Size (Name) ) );

          package FAS_IO is new Ada.Sequential_IO (Element_Type => FAS);

          File   : FAS_IO.File_Type;
          Result : FAS;
       begin -- File_As_String
          FAS_IO.Open (File => File, Mode => FAS_IO.In_File, Name => Name);
          FAS_IO.Read (File => File, Item => Result;
          FAS_IO.Close (File => File);

          return Result;
       end File_As_String;
    end String_A_File;

    This presumes that Result will fit on the stack. If that's likely to be
    a problem, then you will need to use Unbounded_String and read the file Character by Character.


    For the OP's benefit (Jeffrey of course knows this): an alternative to Unbounded_String is to allocate the Result string on the heap, and
    return an access to the heap string. With that method, you can still
    read the entire string with one call of FAS_IO.Read instead of Character
    by Character.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Jesper Quorning on Mon Nov 21 16:18:48 2022
    On 2022-11-21 09:30, Jesper Quorning wrote:

    Is it possible to write something like this with ADA

    ```Ada
    package my_rw_file is new file
    (name => "whatever"
    ,mode => read_write
    ,implementation => standard -- or portable or fast
    );
    package as_string is new. xxx(from => my_rw_file);

    -- parse (as_string);
    package data is new parse (as_string, format => markdown); -- or whatever

    It is difficult to guess what you want to achieve. What it looks to me
    is a design opposite to the customary approach:

    abstract code source (generic and/or tagged)
    / | \
    / | \
    string text_file stream

    Since string and file cannot be derived, in a tagged case some mix-in is
    used.

    The parser from simple-components has multi-line and single-line
    sources. A single-line source can be set on a string. Multi-line source
    is for files and streams.

    --
    Regards,
    Dmitry A. Kazakov
    http://www.dmitry-kazakov.de

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marius Amado-Alves@21:1/5 to All on Mon Nov 21 08:11:05 2022
    Use Ada.Sequential_IO (Character), load to an Unbounded_String, save from a String or Unbounded_String.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Niklas Holsti on Mon Nov 21 17:42:56 2022
    On 2022-11-21 16:52, Niklas Holsti wrote:

    For the OP's benefit (Jeffrey of course knows this): an alternative to Unbounded_String is to allocate the Result string on the heap, and return an access to the heap string. With that method, you can still read the entire string with one call of FAS_IO.Read instead of Character by Character.

    I know it, and I deliberately reject it. Having access types in a pkg spec is poor design. Delegating the associated memory management and all its opportunities for error to the pkg client is very poor design.

    If access types are used, they should be hidden and encapsulated with their memory management. This makes it easier to get the memory management correct. Since this is what using Unbounded_String does for you, I think it's better to use it than to expend extra effort doing something similar.

    --
    Jeff Carter
    "I have a very small head and I had
    better learn to live with it ..."
    Edsger Dijkstra
    158

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Qunying@21:1/5 to All on Mon Nov 21 09:29:49 2022
    If you are using gnat with gnatcoll, then you may try its mmap facility, https://docs.adacore.com/gnatcoll-docs/mmap.html

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Niklas Holsti@21:1/5 to Jeffrey R.Carter on Mon Nov 21 19:29:12 2022
    On 2022-11-21 18:42, Jeffrey R.Carter wrote:
    On 2022-11-21 16:52, Niklas Holsti wrote:

    For the OP's benefit (Jeffrey of course knows this): an alternative to
    Unbounded_String is to allocate the Result string on the heap, and
    return an access to the heap string. With that method, you can still
    read the entire string with one call of FAS_IO.Read instead of
    Character by Character.

    I know it, and I deliberately reject it. Having access types in a pkg
    spec is poor design. Delegating the associated memory management and all
    its opportunities for error to the pkg client is very poor design.


    I agree in general, but there are design trade-offs that depend on
    issues not made clear in the original question, such as the size of the
    file and the performance requirements. So I thought that the OP should
    know of the heap alternative, even if it has some poorer properties too.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gautier write-only address@21:1/5 to All on Mon Nov 21 13:43:39 2022
    You may be interested by this: https://github.com/zertovitch/zip-ada/blob/master/zip_lib/zip_streams.ads#L148 It can be actually used out of the context of Zip archives.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jesper Quorning@21:1/5 to All on Sun Jan 1 15:36:59 2023
    The original post was a bit of a mess, and I am not quite new to Ada. But I lack some skills regarding software construction and software engineering.

    What I want goes something like this:
    - Zero copy access to a (read-only) file.
    - Get lines of file one by one as a stream of lines.
    - Use a package instance as file representation.
    - Stretch goal: Multiple implementations of File Instance (Standard, Fast, Compatible ..)

    Refined version:
    ```Ada
    package File
    is new File_Instance
    (Filename => "whatever",
    Implementation => Standard);
    ---
    for Line of File.As_Line_Stream loop
    Parse (Line);
    end loop;
    ```

    I think Dewar has written something about string view of some data. I saw some tricky tricks in the GNAT.Snobol implementation. Links to papers anyone?

    Sorry for the late follow-up.


    /Jesper

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Leake@21:1/5 to Jesper Quorning on Mon Jan 2 10:57:11 2023
    Jesper Quorning <jesper.quorning@gmail.com> writes:

    The original post was a bit of a mess, and I am not quite new to Ada. But I lack some skills regarding software construction and software engineering.

    What I want goes something like this:
    - Zero copy access to a (read-only) file.

    You can use gnatcoll mmap to get a memory-mapped view of a file. To get
    a zero-copy string, you'll have to find the line boundaries yourself,
    and use unchecked-conversion on a string pointer, or an address clause
    on a local variable.

    - Get lines of file one by one as a stream of lines.

    'stream' has a specific meaning in Ada; better say "collection of lines"
    here.

    You can define an iterator for your File type.

    - Use a package instance as file representation.

    Why do you want to do this? The alternative is to define your own File
    type, and provide an Open; then you can reuse that package for multiple
    files. Closer to Ada standard practice for files.

    - Stretch goal: Multiple implementations of File Instance (Standard, Fast, Compatible ..)

    If you want to choose the implementation at compile time, you can use
    separate bodies in implementation-specific directories, and choose the directory in the project file.

    If you want to chose the implementation at run time, you have to make
    File a dispatching type. Then you pick the implementation via the
    package name:

    My_File : Files.Implementation_1.File;

    for Line of File.As_Line_Stream loop
    Parse (Line);
    end loop;

    You probably know that you can get close to this in standard Ada, at the
    cost of a copy:

    while not End_of_file (File) loop
    declare
    Line : get_line (file);
    begin
    Parse (line);
    end;
    end loop;

    An really aggressive optimizing compiler could get rid of the local
    variable Line to avoid the copy, but it's not very likely.

    This violates your requirement, but it could easily be that the copy is
    very cheap; have you measured it in your actual application, and is
    eliminating it worth the bother?

    --
    -- Stephe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Jesper Quorning on Tue Jan 3 17:37:34 2023
    On 2023-01-02 00:36, Jesper Quorning wrote:

    - Zero copy access to a (read-only) file.

    So far as I know, any access to a file involves copying information from the external medium into memory, so this may be impossible.

    --
    Jeff Carter
    "Any noun can be verbed."
    Alan Perlis
    "Verbing weirds language."
    Calvin and Hobbes
    206

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Jeffrey R.Carter on Tue Jan 3 18:02:54 2023
    On 2023-01-03 17:37, Jeffrey R.Carter wrote:
    On 2023-01-02 00:36, Jesper Quorning wrote:

    - Zero copy access to a (read-only) file.

    So far as I know, any access to a file involves copying information from
    the external medium into memory, so this may be impossible.

    ... in many cases copying drastically improves performance, e.g.
    caching, read ahead techniques etc.

    --
    Regards,
    Dmitry A. Kazakov
    http://www.dmitry-kazakov.de

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)