View source with formatted 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]).   52
   53
   54/** <module> Read utilities
   55
   56This library provides some commonly used   reading  predicates. As these
   57predicates have proven to be time-critical in some applications we moved
   58them to C. For compatibility as well  as to reduce system dependency, we
   59link  the  foreign  code  at  runtime    and   fallback  to  the  Prolog
   60implementation if the shared object cannot be found.
   61
   62@see library(pure_input) allows for processing files with DCGs.
   63@see library(lazy_lists) for creating lazy lists from input.
   64*/
   65
   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                 *******************************/
  113
  114%!  read_line_to_codes(+Stream, -Line:codes) is det.
  115%
  116%   Read the next line of input from  Stream. Unify content of the lines
  117%   as a list of character codes  with   Line  _after_ the line has been
  118%   read. A line is ended by a  newline character or end-of-file. Unlike
  119%   read_line_to_codes/3, this predicate  removes   a  trailing  newline
  120%   character.
  121
  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).
  139
  140%!  read_line_to_codes(+Stream, -Line, ?Tail) is det.
  141%
  142%   Difference-list version to read an input line to a list of character
  143%   codes. Reading stops at the newline   or  end-of-file character, but
  144%   unlike read_line_to_codes/2, the newline is  retained in the output.
  145%   This predicate is especially useful for reading  a block of lines up
  146%   to some delimiter. The following example  reads an HTTP header ended
  147%   by a blank line:
  148%
  149%   ```
  150%   read_header_data(Stream, Header) :-
  151%       read_line_to_codes(Stream, Header, Tail),
  152%       read_header_data(Header, Stream, Tail).
  153%
  154%   read_header_data("\r\n", _, _) :- !.
  155%   read_header_data("\n", _, _) :- !.
  156%   read_header_data("", _, _) :- !.
  157%   read_header_data(_, Stream, Tail) :-
  158%       read_line_to_codes(Stream, Tail, NewTail),
  159%       read_header_data(Tail, Stream, NewTail).
  160%   ```
  161
  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).
  174
  175
  176%!  read_line_to_string(+Stream, -String) is det.
  177%
  178%   Read the next line from Stream into  String. String does not contain
  179%   the line terminator. String is unified with the _atom_ `end_of_file`
  180%   if the end of the file is reached.
  181%
  182%   @see    read_string/5 can be used to read lines with separated
  183%           records without creating intermediate strings.
  184
  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                 *******************************/
  198
  199%!  read_stream_to_codes(+Stream, -Codes) is det.
  200%!  read_stream_to_codes(+Stream, -Codes, ?Tail) is det.
  201%
  202%   Read input from Stream to a list of character codes. The version
  203%   read_stream_to_codes/3 creates a difference-list.
  204
  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).
  216
  217
  218%!  read_stream_to_terms(+Stream, -Terms, ?Tail, +Options) is det.
  219
  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                 *******************************/
  234
  235%!  read_file_to_codes(+Spec, -Codes, +Options) is det.
  236%
  237%   Read the file Spec into a list   of Codes. Options is split into
  238%   options for absolute_file_name/3 and open/4.   In  addition, the
  239%   following option is provided:
  240%
  241%     * tail(?Tail)
  242%     Read the data into a _difference list_ Codes\Tail.
  243%
  244%   @see phrase_from_file/3 and read_file_to_string/3.
  245
  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)).
  258
  259%!  read_file_to_string(+Spec, -String, +Options) is det.
  260%
  261%   Read the file Spec into a the   string  String. Options is split
  262%   into options for absolute_file_name/3 and open/4.
  263%
  264%   @see phrase_from_file/3 and read_file_to_codes/3.
  265
  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)).
  277
  278%!  read_file_to_terms(+Spec, -Terms, +Options) is det.
  279%
  280%   Read the file Spec into a list   of terms. Options is split over
  281%   absolute_file_name/3, open/4 and  read_term/3.  In addition, the
  282%   following option is processed:
  283%
  284%     * tail(?Tail)
  285%     If present, Terms\Tail forms a _difference list_.
  286%
  287%   Note  that  the  _output_  options    of  read_term/3,  such  as
  288%   =variable_names=    or    =subterm_positions=      will    cause
  289%   read_file_to_terms/3 to fail if  Spec   contains  multiple terms
  290%   because the values for the different terms will not unify.
  291
  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))