diff: io__read_line_as_string (second round)
Andrew Bromage
bromage at cs.mu.OZ.AU
Thu Feb 12 13:00:19 AEDT 1998
G'day all.
Fergus, here as requested is the amended diff.
Cheers,
Andrew Bromage
Estimated hours taken: 3
Add io__read_line_as_string/{3,4}, make io__read_line a bit more
efficient.
runtime/mercury_misc.c:
runtime/mercury_misc.h:
Add checked_realloc() as a complement to checked_malloc(). Used
in library/io.m.
library/io.m:
Changes detailed above.
samples/cat.m:
samples/sort.m:
Update to use the new predicates.
Index: runtime/mercury_misc.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_misc.c,v
retrieving revision 1.3
diff -u -r1.3 mercury_misc.c
--- mercury_misc.c 1998/01/23 15:26:33 1.3
+++ mercury_misc.c 1998/01/27 05:55:39
@@ -471,16 +471,30 @@
exit(1);
}
- /* Note: checked_malloc()ed structures */
- /* never contain pointers into GCed */
- /* memory, so we don't need to */
- /* GC_malloc() them. (cf. newmem()) */
+ /* Note: checked_malloc()ed and */
+ /* checked_realloc()ed structures */
+ /* never contain pointers into GCed */
+ /* memory, so we don't need to */
+ /* GC_malloc() them. (cf. newmem()) */
void *
checked_malloc(size_t n)
{
reg void *p;
p = malloc(n);
+ if (p == NULL && n != 0) {
+ fatal_error("ran out of memory");
+ }
+
+ return p;
+}
+
+void *
+checked_realloc(void *old, size_t n)
+{
+ reg void *p;
+
+ p = realloc(old, n);
if (p == NULL && n != 0) {
fatal_error("ran out of memory");
}
Index: runtime/mercury_misc.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_misc.h,v
retrieving revision 1.3
diff -u -r1.3 mercury_misc.h
--- mercury_misc.h 1998/01/23 15:26:35 1.3
+++ mercury_misc.h 1998/01/27 05:55:40
@@ -64,9 +64,11 @@
extern void fatal_error(const char *msg) NO_RETURN;
/*
-** XXX checked_malloc() should be moved to mercury_memory.h or mercury_heap.h
+** XXX checked_malloc() and checked_realloc() should be moved to
+** mercury_memory.h or mercury_heap.h
*/
#include <stddef.h> /* for size_t */
void *checked_malloc(size_t n);
+void *checked_realloc(void *old, size_t n);
#endif /* not MERCURY_MISC_H */
Index: library/io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/io.m,v
retrieving revision 1.149
diff -u -r1.149 io.m
--- io.m 1998/02/04 07:18:34 1.149
+++ io.m 1998/02/12 01:51:13
@@ -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.
@@ -139,7 +145,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).
@@ -1122,15 +1135,14 @@
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]) }
;
@@ -1146,7 +1158,93 @@
{ Result = ok([Char]) }
)
)
+ ;
+ % XXX improve error message
+ { Result = error("read error") }
+ ).
+
+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
+ ;
+ % XXX improve error message
+ Result = error("read error")
+ )
+ ;
+ 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, String::out,
+ IO0::di, IO::uo),
+"
+#define READ_LINE_GROW(n) ((n) * 3 / 2)
+#define BYTES_TO_WORDS(n) (((n) + sizeof(Word)) / sizeof(Word))
+#define READ_LINE_START 2048
+
+ Char initial_read_buffer[READ_LINE_START];
+ Char *read_buffer = initial_read_buffer;
+ size_t read_buf_size = READ_LINE_START;
+ Integer i;
+ Char 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;
+ }
+ else {
+ Res = 0;
+ }
+ break;
+ }
+ if (char_code != (char_code & 0xFF)) {
+ 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(
+ BYTES_TO_WORDS(read_buf_size
+ * sizeof(Char)));
+ memcpy(read_buffer, initial_read_buffer,
+ READ_LINE_START);
+ }
+ else {
+ read_buffer = checked_realloc(read_buffer,
+ BYTES_TO_WORDS(read_buf_size
+ * sizeof(Char)));
+ }
+ }
+ }
+ if (Res == 0) {
+ incr_hp_atomic(String, (i + sizeof(Word)) / sizeof(Word));
+ memcpy((char *)String, read_buffer, i * sizeof(Char));
+ ((Char *)String)[i] = '\\0';
+ }
+ else {
+ String = NULL;
+ }
+ if (read_buffer != initial_read_buffer) {
+ free(read_buffer);
+ }
+ update_io(IO0, IO);
+").
io__read_file(Result) -->
io__input_stream(Stream),
Index: samples/cat.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/samples/cat.m,v
retrieving revision 1.2
diff -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 -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).
More information about the developers
mailing list