for review: io__read_line_as_string (round 2)
Andrew Bromage
bromage at cs.mu.OZ.AU
Tue Sep 8 11:52:53 AEST 1998
G'day all.
As before, Fergus' fixes are all incorporated in this diff.
Cheers,
Andrew Bromage
Estimated hours taken: 10
library/io.m:
library/io.nu.nl:
Implement io__read_line_as_string/{3,4}.
Also sneaked in here are some trivial whitespace fixes in some
of the pragma c_code which did not comply with our coding
standards (to do with type casting).
samples/cat.m:
samples/sort.m:
Use io__read_line_as_string.
tests/general/Mmakefile:
tests/general/read_line_as_string.exp:
tests/general/read_line_as_string.m:
Test case for io__read_line_as_string.
NEWS:
Mention the above change.
--- NEWS Tue Sep 8 11:40:08 1998
+++ NEWS.io-rlas-changes Tue Sep 8 11:41:24 1998
@@ -325,8 +325,8 @@
bag__least_upper_bound/3, bag__remove_list/3, bag__det_remove_list/3,
det_univ_to_type/2, list__take_upto/3, set__count/2, set_ordlist__count/2,
store__new_cyclic_mutvar/4, relation__add_values/4,
- relation__from_assoc_list/2, relation__compose/3, varset__select/3
- and eqvclass__same_eqvclass_list/2.
+ relation__from_assoc_list/2, relation__compose/3, varset__select/3,
+ eqvclass__same_eqvclass_list/2 and io__read_line_as_string/{3,4}.
Also the old relation__to_assoc_list/2 predicate has been renamed as
relation__to_key_assoc_list/2; there is a new relation__to_assoc_list/2
Index: samples/cat.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/samples/cat.m,v
retrieving revision 1.2
diff -u -t -u -r1.2 cat.m
--- cat.m 1997/09/10 11:00:15 1.2
+++ cat.m 1998/02/11 03:31:38
@@ -60,16 +60,15 @@
:- pred cat(io__state::di, io__state::uo) is det.
cat -->
- io__read_line(Result),
+ io__read_line_as_string(Result),
cat_2(Result).
-:- pred cat_2(io__result(list(char))::in, io__state::di, io__state::uo) is det.
+:- pred cat_2(io__result(string)::in, io__state::di, io__state::uo) is det.
cat_2(Result) -->
- ( { Result = ok(CharList) },
- { string__from_char_list(CharList, String) },
- io__write_string(String),
- io__read_line(NextResult),
+ ( { Result = ok(Line) },
+ io__write_string(Line),
+ io__read_line_as_string(NextResult),
cat_2(NextResult)
; { Result = eof }
; { Result = error(Error) },
Index: samples/sort.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/samples/sort.m,v
retrieving revision 1.2
diff -u -t -u -r1.2 sort.m
--- sort.m 1997/09/10 11:00:19 1.2
+++ sort.m 1998/02/11 05:54:37
@@ -79,11 +79,11 @@
sort -->
sort_2([]).
-:- pred sort_2(list(list(char)), io__state, io__state).
+:- pred sort_2(list(string), io__state, io__state).
:- mode sort_2(in, di, uo) is det.
sort_2(Lines0) -->
- io__read_line(Result),
+ io__read_line_as_string(Result),
(
{ Result = error(Error) },
{ io__error_message(Error, Msg) },
@@ -110,11 +110,10 @@
L = [H | NT]
).
-:- pred sort_output(list(list(char)), io__state, io__state).
+:- pred sort_output(list(string), io__state, io__state).
:- mode sort_output(in, di, uo) is det.
sort_output([]) --> [].
sort_output([Line | Lines]) -->
- { string__from_char_list(Line, LineStr) },
- io__write_string(LineStr),
+ io__write_string(Line),
sort_output(Lines).
Index: library/io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/io.m,v
retrieving revision 1.162
diff -u -t -u -r1.162 io.m
--- io.m 1998/08/24 04:45:20 1.162
+++ io.m 1998/09/08 01:06:29
@@ -113,7 +113,13 @@
:- pred io__read_line(io__result(list(char)), io__state, io__state).
:- mode io__read_line(out, di, uo) is det.
-% Reads a line from the current input stream.
+% Reads a line from the current input stream, returns the
+% the result as a list of chars.
+
+:- pred io__read_line_as_string(io__result(string), io__state, io__state).
+:- mode io__read_line_as_string(out, di, uo) is det.
+% Reads a line from the current input stream, returns the
+% result as a string.
:- pred io__read_file(io__result(list(char)), io__state, io__state).
:- mode io__read_file(out, di, uo) is det.
@@ -145,7 +151,14 @@
:- pred io__read_line(io__input_stream, io__result(list(char)),
io__state, io__state).
:- mode io__read_line(in, out, di, uo) is det.
-% Reads a line from specified stream.
+% Reads a line from specified stream, returning the result
+% as a list of chars.
+
+:- pred io__read_line_as_string(io__input_stream, io__result(string),
+ io__state, io__state).
+:- mode io__read_line_as_string(in, out, di, uo) is det.
+% Reads a line from specified stream, returning the
+% result as a string.
:- pred io__read_file(io__input_stream, io__result(list(char)),
io__state, io__state).
@@ -1203,32 +1216,125 @@
io__read_line(Stream, Result).
io__read_line(Stream, Result) -->
- io__read_char(Stream, CharResult),
+ io__read_char_code(Stream, Code),
(
- { CharResult = error(Error) },
- { Result = error(Error) }
- ;
- { CharResult = eof },
+ { Code = -1 }
+ ->
{ Result = eof }
;
- { CharResult = ok(Char) },
+ { char__to_int(Char, Code) }
+ ->
( { Char = '\n' } ->
{ Result = ok([Char]) }
;
- io__read_line(Stream, Result0),
- (
- { Result0 = ok(Chars) },
- { Result = ok([Char | Chars]) }
- ;
- { Result0 = error(_) },
- { Result = Result0 }
- ;
- { Result0 = eof },
- { Result = ok([Char]) }
- )
+ io__read_line_2(Stream, Result0),
+ { Result = ok([Char | Result0]) }
+ )
+ ;
+ io__make_err_msg("read failed: ", Msg),
+ { Result = error(Msg) }
+ ).
+
+:- pred io__read_line_2(io__input_stream, list(char), io__state, io__state).
+:- mode io__read_line_2(in, out, di, uo) is det.
+
+io__read_line_2(Stream, Result) -->
+ io__read_char_code(Stream, Code),
+ (
+ { Code = -1 }
+ ->
+ { Result = [] }
+ ;
+ { char__to_int(Char, Code) }
+ ->
+ ( { Char = '\n' } ->
+ { Result = [Char] }
+ ;
+ io__read_line_2(Stream, Chars),
+ { Result = [Char | Chars] }
)
+ ;
+ { Result = [] }
).
+io__read_line_as_string(Result) -->
+ io__input_stream(Stream),
+ io__read_line_as_string(Stream, Result).
+
+io__read_line_as_string(Stream, Result, IO0, IO) :-
+ io__read_line_as_string_2(Stream, Res, String, IO0, IO),
+ ( Res < 0 ->
+ ( Res = -1 ->
+ Result = eof
+ ;
+ io__make_err_msg("read failed: ", Msg),
+ { Result = error(Msg) }
+ )
+ ;
+ Result = ok(String)
+ ).
+
+:- pred io__read_line_as_string_2(io__input_stream, int, string,
+ io__state, io__state).
+:- mode io__read_line_as_string_2(in, out, out, di, uo) is det.
+
+:- pragma c_code(io__read_line_as_string_2(File::in, Res :: out,
+ RetString::out, IO0::di, IO::uo),
+ [will_not_call_mercury, thread_safe],
+"
+#define READ_LINE_GROW(n) ((n) * 3 / 2)
+#define BYTES_TO_WORDS(n) (((n) + sizeof(Word) - 1) / sizeof(Word))
+#define READ_LINE_START 1024
+
+ Char initial_read_buffer[READ_LINE_START];
+ Char *read_buffer = initial_read_buffer;
+ size_t read_buf_size = READ_LINE_START;
+ size_t i;
+ int char_code = '\\0';
+
+ Res = 0;
+ for (i = 0; char_code != '\\n'; ) {
+ char_code = mercury_getc((MercuryFile *) File);
+ if (char_code == -1) {
+ if (i == 0) {
+ Res = -1;
+ }
+ break;
+ }
+ if (char_code != (Char) char_code) {
+ Res = -2;
+ break;
+ }
+ read_buffer[i++] = char_code;
+ MR_assert(i <= read_buf_size);
+ if (i == read_buf_size) {
+ /* Grow the read buffer */
+ read_buf_size = READ_LINE_GROW(read_buf_size);
+ if (read_buffer == initial_read_buffer) {
+ read_buffer = checked_malloc(read_buf_size
+ * sizeof(Char));
+ memcpy(read_buffer, initial_read_buffer,
+ READ_LINE_START);
+ } else {
+ read_buffer = checked_realloc(read_buffer,
+ read_buf_size * sizeof(Char));
+ }
+ }
+ }
+ if (Res == 0) {
+ incr_hp_atomic(RetString,
+ BYTES_TO_WORDS((i + 1) * sizeof(Char)));
+ memcpy((void *) RetString, read_buffer, i * sizeof(Char));
+ ((Char *) RetString)[i] = '\\0';
+ } else {
+ RetString = NULL;
+ }
+ if (read_buffer != initial_read_buffer) {
+ free(read_buffer);
+ }
+ update_io(IO0, IO);
+").
+
io__read_file(Result) -->
io__input_stream(Stream),
io__read_file(Stream, Result).
@@ -2527,7 +2633,7 @@
:- pragma c_code(io__putback_char(File::in, Character::in, IO0::di, IO::uo),
will_not_call_mercury, "{
- MercuryFile* mf = (MercuryFile *)File;
+ MercuryFile* mf = (MercuryFile *) File;
if (Character == '\\n') {
mf->line_number--;
}
@@ -2540,7 +2646,7 @@
:- pragma c_code(io__putback_byte(File::in, Character::in, IO0::di, IO::uo),
will_not_call_mercury, "{
- MercuryFile* mf = (MercuryFile *)File;
+ MercuryFile* mf = (MercuryFile *) File;
/* XXX should work even if ungetc() fails */
if (ungetc(Character, mf->file) == EOF) {
fatal_error(""io__putback_byte: ungetc failed"");
@@ -2843,7 +2949,7 @@
io__set_input_stream(NewStream::in, OutStream::out, IO0::di, IO::uo),
will_not_call_mercury, "
OutStream = (Word) mercury_current_text_input;
- mercury_current_text_input = (MercuryFile*) NewStream;
+ mercury_current_text_input = (MercuryFile *) NewStream;
update_io(IO0, IO);
").
@@ -2851,7 +2957,7 @@
io__set_output_stream(NewStream::in, OutStream::out, IO0::di, IO::uo),
will_not_call_mercury, "
OutStream = (Word) mercury_current_text_output;
- mercury_current_text_output = (MercuryFile*) NewStream;
+ mercury_current_text_output = (MercuryFile *) NewStream;
update_io(IO0, IO);
").
@@ -2859,7 +2965,7 @@
io__set_binary_input_stream(NewStream::in, OutStream::out,
IO0::di, IO::uo), will_not_call_mercury, "
OutStream = (Word) mercury_current_binary_input;
- mercury_current_binary_input = (MercuryFile*) NewStream;
+ mercury_current_binary_input = (MercuryFile *) NewStream;
update_io(IO0, IO);
").
@@ -2867,7 +2973,7 @@
io__set_binary_output_stream(NewStream::in, OutStream::out,
IO0::di, IO::uo), will_not_call_mercury, "
OutStream = (Word) mercury_current_binary_output;
- mercury_current_binary_output = (MercuryFile*) NewStream;
+ mercury_current_binary_output = (MercuryFile *) NewStream;
update_io(IO0, IO);
").
@@ -2888,25 +2994,25 @@
:- pragma c_code(io__close_input(Stream::in, IO0::di, IO::uo),
[will_not_call_mercury, thread_safe], "
- mercury_close((MercuryFile*)Stream);
+ mercury_close((MercuryFile *) Stream);
update_io(IO0, IO);
").
:- pragma c_code(io__close_output(Stream::in, IO0::di, IO::uo),
[will_not_call_mercury, thread_safe], "
- mercury_close((MercuryFile*)Stream);
+ mercury_close((MercuryFile *) Stream);
update_io(IO0, IO);
").
:- pragma c_code(io__close_binary_input(Stream::in, IO0::di, IO::uo),
[will_not_call_mercury, thread_safe], "
- mercury_close((MercuryFile*)Stream);
+ mercury_close((MercuryFile *) Stream);
update_io(IO0, IO);
").
:- pragma c_code(io__close_binary_output(Stream::in, IO0::di, IO::uo),
[will_not_call_mercury, thread_safe], "
- mercury_close((MercuryFile*)Stream);
+ mercury_close((MercuryFile *) Stream);
update_io(IO0, IO);
").
Index: library/io.nu.nl
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/io.nu.nl,v
retrieving revision 1.63
diff -u -t -u -r1.63 io.nu.nl
--- io.nu.nl 1998/07/28 02:21:57 1.63
+++ io.nu.nl 1998/07/28 03:27:02
@@ -315,6 +315,10 @@
Result = ok(Term)
}.
+ % In Prolog, strings and lists of chars are the same.
+io__read_line_as_string(S, Result) -->
+ io__read_line(S, Result).
+
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: tests/general//Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/tests/general/Mmakefile,v
retrieving revision 1.20
diff -u -t -u -r1.20 Mmakefile
--- Mmakefile 1998/08/07 05:13:09 1.20
+++ Mmakefile 1998/09/06 23:21:58
@@ -53,6 +53,7 @@
prune_switch \
semi_fail_in_non_ite \
semidet_lambda \
+ read_line_as_string \
semidet_map \
set_test \
string_format_test \
New File: tests/general//read_line_as_string.exp
===================================================================
Hello
world
[Line consisting of 2047 a's deleted for review purposes]
New File: tests/general//read_line_as_string.m
===================================================================
:- module read_line_as_string.
:- interface.
:- import_module io.
:- pred main(io__state :: di, io__state :: uo) is det.
:- implementation.
main -->
io__open_input("read_line_as_string.exp", Result),
( { Result = ok(Stream) } ->
io__set_input_stream(Stream, _),
io__read_line_as_string(Result2),
cat(Result2)
;
io__write_string("Error opening file!")
).
:- pred cat(io__result(string)::in, io__state::di, io__state::uo) is det.
cat(Result) -->
( { Result = ok(Line) },
io__write_string(Line),
io__read_line_as_string(NextResult),
cat(NextResult)
; { Result = eof }
; { Result = error(_Error) },
io__write_string("Error reading file!")
).
More information about the developers
mailing list