[m-dev.] for review: destructive changes to string.m

Michael Day mikeday at corplink.com.au
Fri Nov 10 23:18:24 AEDT 2000


Estimated hours taken: 2

Allows checking string length without losing uniqueness and adds
predicates to allow changing arbitrary characters in a string, handy for
implementation of string streams.

library/string.m:
	Added a new mode definition to string__length using unique input
	so as not to destroy uniqueness when checking string length.

	Added three new predicates, string__set, set_det and unsafe_set
	that allow changing arbitrary characters in a string. These function
	similarly to the corresponding index, index_det and unsafe_index
	predicates. (Is set an appropriate name? Overloading index/3 with
	index/4 is presumably a bad idea).

Index: string.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/string.m,v
retrieving revision 1.134
diff -u -r1.134 string.m
--- string.m	2000/11/06 04:32:20	1.134
+++ string.m	2000/11/10 12:11:20
@@ -23,6 +23,7 @@
 
 :- pred string__length(string, int).
 :- mode string__length(in, uo) is det.
+:- mode string__length(ui, uo) is det.
 	% Determine the length of a string.
 	% An empty string has length zero.
 
@@ -215,6 +216,36 @@
 %	may be linear in the length of the string.
 %	Use with care!
 
+:- pred string__set(char, int, string, string).
+:- mode string__set(in, in, in, out) is semidet.
+:- mode string__set(in, in, di, uo) is semidet.
+%	string__set(Char, Index, String0, String):
+%	`String' is `String0' with the (`Index' + 1)-th character
+%	set to `Char'.
+%	Fails if `Index' is out of range (negative, or greater than or
+%	equal to the length of `String0').
+
+:- pred string__set_det(char, int, string, string).
+:- mode string__set_det(in, in, in, out) is det.
+:- mode string__set_det(in, in, di, uo) is det.
+%	string__set_det(Char, Index, String0, String):
+%	`String' is `String0' with the (`Index' + 1)-th character
+%	set to `Char'.
+%	Calls error/1 if `Index' is out of range (negative, or greater than or
+%	equal to the length of `String0').
+
+:- pred string__unsafe_set(char, int, string, string).
+:- mode string__unsafe_set(in, in, in, out) is det.
+:- mode string__unsafe_set(in, in, di, uo) is det.
+%	string__unsafe_set(Char, Index, String0, String):
+%	`String' is `String0' with the (`Index' + 1)-th character
+%	set to `Char'.
+%	WARNING: behavior is UNDEFINED if `Index' is out of range
+%	(negative, or greater than or equal to the length of `String0').
+%	This version is constant time, whereas string__set_det
+%	may be linear in the length of the string.
+%	Use with care!
+
 :- pred string__foldl(pred(char, T, T), string, T, T).
 :- mode string__foldl(pred(in, in, out) is det, in, in, out) is det.
 :- mode string__foldl(pred(in, di, uo) is det, in, di, uo) is det.
@@ -489,6 +520,13 @@
 		error("string__index_det: index out of range")
 	).
 
+string__set_det(Char, Int, String0, String) :-
+	( string__set(Char, Int, String0, String1) ->
+		String = String1
+	;
+		error("string__set_det: index out of range")
+	).
+
 string__foldl(Closure, String, Acc0, Acc) :-
 	string__length(String, Length),
 	string__foldl2(Closure, String, 0, Length, Acc0, Acc).
@@ -1445,14 +1483,81 @@
 /*-----------------------------------------------------------------------*/
 
 /*
+:- pred string__set(char, int, string, string).
+:- mode string__set(in, in, in, out) is semidet.
+*/
+:- pragma c_code(string__set(Ch::in, Index::in, Str0::in, Str::out),
+		[will_not_call_mercury, thread_safe], "
+	size_t len = strlen(Str0);
+	if ((MR_Word) Index >= len) {
+		SUCCESS_INDICATOR = FALSE;
+	} else {
+		SUCCESS_INDICATOR = TRUE;
+		MR_allocate_aligned_string_msg(Str, len, MR_PROC_LABEL);
+		strcpy(Str, Str0);
+		Str[Index] = Ch;
+	}
+").
+
+/*
+:- pred string__set(char, int, string, string).
+:- mode string__set(in, in, di, uo) is semidet.
+*/
+:- pragma c_code(string__set(Ch::in, Index::in, Str0::di, Str::uo),
+		[will_not_call_mercury, thread_safe], "
+	if ((MR_Word) Index >= strlen(Str0)) {
+		SUCCESS_INDICATOR = FALSE;
+	} else {
+		SUCCESS_INDICATOR = TRUE;
+		Str = Str0;
+		Str[Index] = Ch;
+	}
+").
+
+/*-----------------------------------------------------------------------*/
+
+/*
+:- pred string__unsafe_set(char, int, string, string).
+:- mode string__unsafe_set(in, in, in, out) is det.
+*/
+:- pragma c_code(string__unsafe_set(Ch::in, Index::in, Str0::in, Str::out),
+		[will_not_call_mercury, thread_safe], "
+	size_t len = strlen(Str0);
+	MR_allocate_aligned_string_msg(Str, len, MR_PROC_LABEL);
+	strcpy(Str, Str0);
+	Str[Index] = Ch;
+").
+
+/*
+:- pred string__unsafe_set(char, int, string, string).
+:- mode string__unsafe_set(in, in, di, uo) is det.
+*/
+:- pragma c_code(string__unsafe_set(Ch::in, Index::in, Str0::di, Str::uo),
+		[will_not_call_mercury, thread_safe], "
+	Str = Str0;
+	Str[Index] = Ch;
+").
+
+/*-----------------------------------------------------------------------*/
+
+/*
 :- pred string__length(string, int).
-:- mode string__length(in, out) is det.
+:- mode string__length(in, uo) is det.
 */
 :- pragma c_code(string__length(Str::in, Length::uo),
 		[will_not_call_mercury, thread_safe], "
 	Length = strlen(Str);
 ").
 
+/*
+:- pred string__length(string, int).
+:- mode string__length(ui, uo) is det.
+*/
+:- pragma c_code(string__length(Str::ui, Length::uo),
+		[will_not_call_mercury, thread_safe], "
+	Length = strlen(Str);
+").
+
 /*-----------------------------------------------------------------------*/
 
 /*
@@ -1718,6 +1823,7 @@
 :- interface.
 
 :- func string__length(string) = int.
+:- mode string__length(in) = uo is det.
 
 :- func string__append(string, string) = string.
 

--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list