1 (* Copyright (C
) 2009,2014 Matthew Fluet
.
2 * Copyright (C
) 1999-2006 Henry Cejtin
, Matthew Fluet
, Suresh
3 * Jagannathan
, and Stephen Weeks
.
5 * MLton is released under a BSD
-style license
.
6 * See the file MLton
-LICENSE for details
.
9 structure String: STRING
=
13 fun unfold (n
, a
, f
) =
27 case Vector.length ss
of
29 |
1 => Vector.sub (ss
, 0)
33 Vector.fold (ss
, 0, fn (s
, n
) => n
+ size s
)
34 val a
= Array
.new (n
, #
"a")
38 fold (s
, i
, fn (c
, i
) =>
39 (Array
.update (a
, i
, c
);
42 tabulate (n
, fn i
=> Array
.sub (a
, i
))
46 tabulate (Vector.length cs
, fn i
=> Vector.sub (cs
, i
))
48 fun existsi (s
, f
) = Int.exists (0, size s
, fn i
=> f (i
, sub (s
, i
)))
50 fun exists (s
, f
) = existsi (s
, f
o #
2)
52 fun keepAll (s
: t
, f
: char
-> bool): t
=
54 (fold (s
, [], fn (c
, ac
) => if f c
then c
:: ac
else ac
)))
56 fun memoizeList (init
: string -> 'a
, l
: (t
* 'a
) list
): t
-> 'a
=
58 val set
: (word * t
* 'a
) HashSet
.t
= HashSet
.new
{hash
= #
1}
59 fun lookupOrInsert (s
, f
) =
62 in HashSet
.lookupOrInsert
64 fn (hash
', s
', _
) => hash
= hash
' andalso s
= s
',
65 fn () => (hash
, s
, f ()))
68 List.foreach (l
, fn (s
, a
) =>
69 ignore (lookupOrInsert (s
, fn () => a
)))
71 fn s
=> #
3 (lookupOrInsert (s
, fn () => init s
))
74 fun memoize init
= memoizeList (init
, [])
76 fun posToLineCol (s
: string): int -> {line
: int, col
: int} =
81 (List.rev (foldi (s
, [0], fn (i
, c
, is
) =>
88 valOf (BinarySearch
.largest (lineStarts
, fn x
=> x
<= pos
))
89 (* The
1+'s are to make stuff one based
*)
91 col
= 1 + pos
- Array
.sub (lineStarts
, line
)}
96 fun substituteFirst (s
, {substring
, replacement
}) =
97 case findSubstring (s
, {substring
= substring
}) of
101 val n
= length substring
102 val prefix
= Substring
.substring (s
, {start
= 0, length
= i
})
103 val suffix
= Substring
.extract (s
, i
+ n
, NONE
)
105 Substring
.concat
[prefix
, Substring
.full replacement
, suffix
]
107 fun substituteAll (s
, {substring
, replacement
}) =
108 case findSubstring (s
, {substring
= substring
}) of
113 val lss
= length substring
114 val prefix
= dropSuffix (s
, ls
- i
)
115 val suffix
= substituteAll (dropPrefix (s
, i
+ lss
),
116 {substring
= substring
,
117 replacement
= replacement
})
119 concat
[prefix
, replacement
, suffix
]
123 structure ZString
= String (* CM bug ??
-- see instream
.sml
*)