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