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:- autoload(library(error),[must_be/2]).   50:- autoload(library(option),[option/3]).   51:- autoload(library(shlib),[load_foreign_library/1]).

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. */
   66:- predicate_options(read_file_to_codes/3, 3,
   67                     [ tail(list_or_partial_list),
   68                       pass_to(system:open/4, 4)
   69                     ]).   70:- predicate_options(read_file_to_string/3, 3,
   71                     [ pass_to(system:open/4, 4)
   72                     ]).   73:- predicate_options(read_file_to_terms/3, 3,
   74                     [ tail(list_or_partial_list),
   75                       pass_to(read_stream_to_terms/4, 4),
   76                       pass_to(system:absolute_file_name/3, 3),
   77                       pass_to(system:open/4, 4)
   78                     ]).   79:- predicate_options(read_stream_to_terms/4, 4,
   80                     [ pass_to(read_term/3, 3)
   81                     ]).   82
   83:- volatile
   84    read_line_to_codes/2,
   85    read_line_to_codes/3,
   86    read_stream_to_codes/2,
   87    read_stream_to_codes/3.   88
   89link_foreign :-
   90    catch(load_foreign_library(foreign(readutil)), _, fail),
   91    !.
   92link_foreign :-
   93    assertz((read_line_to_codes(Stream, Line) :-
   94            pl_read_line_to_codes(Stream, Line))),
   95    assertz((read_line_to_codes(Stream, Line, Tail) :-
   96            pl_read_line_to_codes(Stream, Line, Tail))),
   97    assertz((read_stream_to_codes(Stream, Content) :-
   98            pl_read_stream_to_codes(Stream, Content))),
   99    assertz((read_stream_to_codes(Stream, Content, Tail) :-
  100            pl_read_stream_to_codes(Stream, Content, Tail))),
  101    compile_predicates([ read_line_to_codes/2,
  102                         read_line_to_codes/3,
  103                         read_stream_to_codes/2,
  104                         read_stream_to_codes/3
  105                       ]).
  106
  107:- initialization(link_foreign, now).  108
  109
  110                 /*******************************
  111                 *             LINES            *
  112                 *******************************/
 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.
  122pl_read_line_to_codes(Stream, Codes) :-
  123    get_code(Stream, C0),
  124    (   C0 == -1
  125    ->  Codes0 = end_of_file
  126    ;   read_1line_to_codes(C0, Stream, Codes0)
  127    ),
  128    Codes = Codes0.
  129
  130read_1line_to_codes(-1, _, []) :- !.
  131read_1line_to_codes(10, _, []) :- !.
  132read_1line_to_codes(13, Stream, L) :-
  133    !,
  134    get_code(Stream, C2),
  135    read_1line_to_codes(C2, Stream, L).
  136read_1line_to_codes(C, Stream, [C|T]) :-
  137    get_code(Stream, C2),
  138    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).
  162pl_read_line_to_codes(Stream, Codes, Tail) :-
  163    get_code(Stream, C0),
  164    read_line_to_codes(C0, Stream, Codes0, Tail),
  165    Codes = Codes0.
  166
  167read_line_to_codes(-1, _, Tail, Tail) :-
  168    !,
  169    Tail = [].
  170read_line_to_codes(10, _, [10|Tail], Tail) :- !.
  171read_line_to_codes(C, Stream, [C|T], Tail) :-
  172    get_code(Stream, C2),
  173    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.
  185read_line_to_string(Stream, String) :-
  186    read_string(Stream, '\n', '\r', Sep, String0),
  187    (   Sep \== -1
  188    ->  String = String0
  189    ;   String0 == ""
  190    ->  String = end_of_file
  191    ;   String = String0
  192    ).
  193
  194
  195                 /*******************************
  196                 *     STREAM (ENTIRE INPUT)    *
  197                 *******************************/
 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.
  205pl_read_stream_to_codes(Stream, Codes) :-
  206    pl_read_stream_to_codes(Stream, Codes, []).
  207pl_read_stream_to_codes(Stream, Codes, Tail) :-
  208    get_code(Stream, C0),
  209    read_stream_to_codes(C0, Stream, Codes0, Tail),
  210    Codes = Codes0.
  211
  212read_stream_to_codes(-1, _, Tail, Tail) :- !.
  213read_stream_to_codes(C, Stream, [C|T], Tail) :-
  214    get_code(Stream, C2),
  215    read_stream_to_codes(C2, Stream, T, Tail).
 read_stream_to_terms(+Stream, -Terms, ?Tail, +Options) is det
  220read_stream_to_terms(Stream, Terms, Tail, Options) :-
  221    read_term(Stream, C0, Options),
  222    read_stream_to_terms(C0, Stream, Terms0, Tail, Options),
  223    Terms = Terms0.
  224
  225read_stream_to_terms(end_of_file, _, Tail, Tail, _) :- !.
  226read_stream_to_terms(C, Stream, [C|T], Tail, Options) :-
  227    read_term(Stream, C2, Options),
  228    read_stream_to_terms(C2, Stream, T, Tail, Options).
  229
  230
  231                 /*******************************
  232                 *      FILE (ENTIRE INPUT)     *
  233                 *******************************/
 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.
  246read_file_to_codes(Spec, Codes, Options) :-
  247    must_be(list, Options),
  248    option(tail(Tail), Options, []),
  249    absolute_file_name(Spec,
  250                       [ access(read)
  251                       | Options
  252                       ],
  253                       Path),
  254    setup_call_cleanup(
  255        open(Path, read, Stream, Options),
  256        read_stream_to_codes(Stream, Codes, Tail),
  257        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.
  266read_file_to_string(Spec, Codes, Options) :-
  267    must_be(list, Options),
  268    absolute_file_name(Spec,
  269                       [ access(read)
  270                       | Options
  271                       ],
  272                       Path),
  273    setup_call_cleanup(
  274        open(Path, read, Stream, Options),
  275        read_string(Stream, _Len, Codes),
  276        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.

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