View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2001-2019, University of Amsterdam
    7                              VU University Amsterdam
    8                              CWI, Amsterdam
    9    All rights reserved.
   10
   11    Redistribution and use in source and binary forms, with or without
   12    modification, are permitted provided that the following conditions
   13    are met:
   14
   15    1. Redistributions of source code must retain the above copyright
   16       notice, this list of conditions and the following disclaimer.
   17
   18    2. Redistributions in binary form must reproduce the above copyright
   19       notice, this list of conditions and the following disclaimer in
   20       the documentation and/or other materials provided with the
   21       distribution.
   22
   23    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   24    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   25    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   26    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   27    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   28    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   29    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   30    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   31    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   33    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34    POSSIBILITY OF SUCH DAMAGE.
   35*/
   36
   37:- module(read_util,
   38          [ read_line_to_codes/2,       % +Stream, -Codes (without trailing \n)
   39            read_line_to_codes/3,       % +Stream, -Codes, ?Tail
   40            read_stream_to_codes/2,     % +Stream, -Codes
   41            read_stream_to_codes/3,     % +Stream, -Codes, ?Tail
   42            read_file_to_codes/3,       % +File, -Codes, +Options
   43
   44            read_line_to_string/2,      % +Stream, -Line (without trailing \n)
   45            read_file_to_string/3,      % +File, -Codes, +Options
   46
   47            read_file_to_terms/3        % +File, -Terms, +Options
   48          ]).   49:- use_module(library(shlib)).   50:- use_module(library(error)).   51:- use_module(library(option)).

Read utilities

This library provides some commonly used reading predicates. As these predicates have proven to be time-critical in some applications we moved them to C. For compatibility as well as to reduce system dependency, we link the foreign code at runtime and fallback to the Prolog implementation if the shared object cannot be found.

See also
- library(pure_input) allows for processing files with DCGs.
- library(lazy_lists) for creating lazy lists from input. */
   65:- predicate_options(read_file_to_codes/3, 3,
   66                     [ tail(list_or_partial_list),
   67                       pass_to(system:open/4, 4)
   68                     ]).   69:- predicate_options(read_file_to_string/3, 3,
   70                     [ pass_to(system:open/4, 4)
   71                     ]).   72:- predicate_options(read_file_to_terms/3, 3,
   73                     [ tail(list_or_partial_list),
   74                       pass_to(read_stream_to_terms/4, 4),
   75                       pass_to(system:absolute_file_name/3, 3),
   76                       pass_to(system:open/4, 4)
   77                     ]).   78
   79:- volatile
   80    read_line_to_codes/2,
   81    read_line_to_codes/3,
   82    read_stream_to_codes/2,
   83    read_stream_to_codes/3.   84
   85link_foreign :-
   86    catch(load_foreign_library(foreign(readutil)), _, fail),
   87    !.
   88link_foreign :-
   89    assertz((read_line_to_codes(Stream, Line) :-
   90            pl_read_line_to_codes(Stream, Line))),
   91    assertz((read_line_to_codes(Stream, Line, Tail) :-
   92            pl_read_line_to_codes(Stream, Line, Tail))),
   93    assertz((read_stream_to_codes(Stream, Content) :-
   94            pl_read_stream_to_codes(Stream, Content))),
   95    assertz((read_stream_to_codes(Stream, Content, Tail) :-
   96            pl_read_stream_to_codes(Stream, Content, Tail))),
   97    compile_predicates([ read_line_to_codes/2,
   98                         read_line_to_codes/3,
   99                         read_stream_to_codes/2,
  100                         read_stream_to_codes/3
  101                       ]).
  102
  103:- initialization(link_foreign, now).  104
  105
  106                 /*******************************
  107                 *             LINES            *
  108                 *******************************/
 read_line_to_codes(+Stream, -Line:codes) is det
Read the next line of input from Stream. Unify content of the lines as a list of character codes with Line after the line has been read. A line is ended by a newline character or end-of-file. Unlike read_line_to_codes/3, this predicate removes a trailing newline character.
  118pl_read_line_to_codes(Stream, Codes) :-
  119    get_code(Stream, C0),
  120    (   C0 == -1
  121    ->  Codes0 = end_of_file
  122    ;   read_1line_to_codes(C0, Stream, Codes0)
  123    ),
  124    Codes = Codes0.
  125
  126read_1line_to_codes(-1, _, []) :- !.
  127read_1line_to_codes(10, _, []) :- !.
  128read_1line_to_codes(13, Stream, L) :-
  129    !,
  130    get_code(Stream, C2),
  131    read_1line_to_codes(C2, Stream, L).
  132read_1line_to_codes(C, Stream, [C|T]) :-
  133    get_code(Stream, C2),
  134    read_1line_to_codes(C2, Stream, T).
 read_line_to_codes(+Stream, -Line, ?Tail) is det
Difference-list version to read an input line to a list of character codes. Reading stops at the newline or end-of-file character, but unlike read_line_to_codes/2, the newline is retained in the output. This predicate is especially useful for reading a block of lines up to some delimiter. The following example reads an HTTP header ended by a blank line:
read_header_data(Stream, Header) :-
    read_line_to_codes(Stream, Header, Tail),
    read_header_data(Header, Stream, Tail).

read_header_data("\r\n", _, _) :- !.
read_header_data("\n", _, _) :- !.
read_header_data("", _, _) :- !.
read_header_data(_, Stream, Tail) :-
    read_line_to_codes(Stream, Tail, NewTail),
    read_header_data(Tail, Stream, NewTail).
  158pl_read_line_to_codes(Stream, Codes, Tail) :-
  159    get_code(Stream, C0),
  160    read_line_to_codes(C0, Stream, Codes0, Tail),
  161    Codes = Codes0.
  162
  163read_line_to_codes(-1, _, Tail, Tail) :-
  164    !,
  165    Tail = [].
  166read_line_to_codes(10, _, [10|Tail], Tail) :- !.
  167read_line_to_codes(C, Stream, [C|T], Tail) :-
  168    get_code(Stream, C2),
  169    read_line_to_codes(C2, Stream, T, Tail).
 read_line_to_string(+Stream, -String) is det
Read the next line from Stream into String. String does not contain the line terminator. String is unified with the atom end_of_file if the end of the file is reached.
See also
- read_string/5 can be used to read lines with separated records without creating intermediate strings.
  181read_line_to_string(Stream, String) :-
  182    read_string(Stream, '\n', '\r', Sep, String0),
  183    (   Sep \== -1
  184    ->  String = String0
  185    ;   String0 == ""
  186    ->  String = end_of_file
  187    ;   String = String0
  188    ).
  189
  190
  191                 /*******************************
  192                 *     STREAM (ENTIRE INPUT)    *
  193                 *******************************/
 read_stream_to_codes(+Stream, -Codes) is det
 read_stream_to_codes(+Stream, -Codes, ?Tail) is det
Read input from Stream to a list of character codes. The version read_stream_to_codes/3 creates a difference-list.
  201pl_read_stream_to_codes(Stream, Codes) :-
  202    pl_read_stream_to_codes(Stream, Codes, []).
  203pl_read_stream_to_codes(Stream, Codes, Tail) :-
  204    get_code(Stream, C0),
  205    read_stream_to_codes(C0, Stream, Codes0, Tail),
  206    Codes = Codes0.
  207
  208read_stream_to_codes(-1, _, Tail, Tail) :- !.
  209read_stream_to_codes(C, Stream, [C|T], Tail) :-
  210    get_code(Stream, C2),
  211    read_stream_to_codes(C2, Stream, T, Tail).
 read_stream_to_terms(+Stream, -Terms, ?Tail, +Options) is det
  216read_stream_to_terms(Stream, Terms, Tail, Options) :-
  217    read_term(Stream, C0, Options),
  218    read_stream_to_terms(C0, Stream, Terms0, Tail, Options),
  219    Terms = Terms0.
  220
  221read_stream_to_terms(end_of_file, _, Tail, Tail, _) :- !.
  222read_stream_to_terms(C, Stream, [C|T], Tail, Options) :-
  223    read_term(Stream, C2, Options),
  224    read_stream_to_terms(C2, Stream, T, Tail, Options).
  225
  226
  227                 /*******************************
  228                 *      FILE (ENTIRE INPUT)     *
  229                 *******************************/
 read_file_to_codes(+Spec, -Codes, +Options) is det
Read the file Spec into a list of Codes. Options is split into options for absolute_file_name/3 and open/4. In addition, the following option is provided:
tail(?Tail)
Read the data into a difference list Codes\Tail.
See also
- phrase_from_file/3 and read_file_to_string/3.
  242read_file_to_codes(Spec, Codes, Options) :-
  243    must_be(list, Options),
  244    option(tail(Tail), Options, []),
  245    absolute_file_name(Spec,
  246                       [ access(read)
  247                       | Options
  248                       ],
  249                       Path),
  250    setup_call_cleanup(
  251        open(Path, read, Stream, Options),
  252        read_stream_to_codes(Stream, Codes, Tail),
  253        close(Stream)).
 read_file_to_string(+Spec, -String, +Options) is det
Read the file Spec into a the string String. Options is split into options for absolute_file_name/3 and open/4.
See also
- phrase_from_file/3 and read_file_to_codes/3.
  262read_file_to_string(Spec, Codes, Options) :-
  263    must_be(list, Options),
  264    absolute_file_name(Spec,
  265                       [ access(read)
  266                       | Options
  267                       ],
  268                       Path),
  269    setup_call_cleanup(
  270        open(Path, read, Stream, Options),
  271        read_string(Stream, _Len, Codes),
  272        close(Stream)).
 read_file_to_terms(+Spec, -Terms, +Options) is det
Read the file Spec into a list of terms. Options is split over absolute_file_name/3, open/4 and read_term/3. In addition, the following option is processed:
tail(?Tail)
If present, Terms\Tail forms a difference list.

Note that the output options of read_term/3, such as variable_names or subterm_positions will cause read_file_to_terms/3 to fail if Spec contains multiple terms because the values for the different terms will not unify.

  288read_file_to_terms(Spec, Terms, Options) :-
  289    must_be(list, Options),
  290    option(tail(Tail), Options, []),
  291    absolute_file_name(Spec,
  292                       [ access(read)
  293                       | Options
  294                       ],
  295                       Path),
  296    setup_call_cleanup(
  297        open(Path, read, Stream, Options),
  298        read_stream_to_terms(Stream, Terms, Tail, Options),
  299        close(Stream))