(* extstr.sml * * COPYRIGHT (c) 1991 by AT&T Bell Laboratories. * * Extensible string data type. * * Copied from widgets/text/extstr.sml of eXene release *) signature EXTSTR = sig type ext_str exception BadIndex of int val mkExtStr : string -> ext_str val es_len : ext_str -> int val es_gets : ext_str -> string val es_subs : (ext_str * int * int) -> string val es_ins : (ext_str * int * char) -> ext_str val es_del : (ext_str * int) -> ext_str val es_charAt : (ext_str * int) -> char end (* EXTSTR *) structure ExtStr : EXTSTR = struct datatype ext_str = ExtStr of { suffix : string, listc : char list, listl : int } exception BadIndex of int (* mkExtStr str returns an extensible string with the contents of str *) fun mkExtStr s = ExtStr{suffix="", listc = rev(explode s),listl=size s} (* es_len extstr returns the length of an extensible string *) fun es_len (ExtStr{suffix,listl,...}) = size suffix + listl (* es_gets extstr returns the string corresponding to extstr *) fun es_gets (ExtStr{suffix,listc,...}) = (implode(rev listc)) ^ suffix (* es_subs (extstr, index, len) returns the substring of extstr of length len, if i+len is greater than the length of extstr, then it returns the longest possible substring*) fun es_subs (extstr, i, len) = let val s = es_gets extstr in (substring (s, i, Int.min((size s)-i, len))) handle Substring => raise BadIndex i end (* es_split (extstr, i) returns a pair of substrings corresponding to: the part of extstr before position i, and the part of extstr beginning at position i *) fun es_split (extstr, i) = let val s = es_gets extstr in (substring(s,0,i),substring (s, i, (size s)-i)) handle Substring => raise BadIndex i end (* es_ins (extstr, i, char) returns the extensible string corrpesponding to extstr with character c inserted at position i *) fun es_ins (s as ExtStr{suffix,listc,listl},i,c) = if i < 0 then raise BadIndex i else if i = listl then ExtStr{suffix=suffix,listc=c::listc,listl=listl+1} else let val (pref,suff) = es_split (s, i) in ExtStr{suffix=suff,listc=c::(rev(explode pref)),listl=i+1} end (* es_del (extstr, i) returns the extensible string corrpesponding to extstr with the character at position i removed *) fun es_del (s as ExtStr{suffix,listc,listl},i) = if i <= 0 then raise BadIndex i else if i = listl then ExtStr{suffix=suffix,listc=tl listc, listl = listl-1} else let val (pref,suff) = es_split (s, i) in ExtStr{suffix=suff,listc=tl(rev(explode pref)),listl=i-1} end (* es_charAt (extstr, i) returns the character at index 'i' of the extensible string extstr *) fun es_charAt (s as ExtStr{suffix,listc,listl},i) = if i <= 0 then raise BadIndex i else if i = listl then hd listc else String.sub(es_gets s, i-1) end (* ExtStr *)