@@ -24,36 +24,47 @@ module AutoOpenExtensionsStringBuilder =
2424 // TODO: add overload with length: sb.IndexOf (c:char, from:int, length:int )
2525
2626 /// Like list.IndexOf but for StringBuilder, returns -1 if not found
27- /// Throws ArgumentOutOfRangeException if 'from' is out of range
27+ /// Throws ArgumentOutOfRangeException if 'from' is negative.
2828 member sb.IndexOf ( c : char , from : int ) : int =
29- if from < 0 then ArgumentOutOfRangeException( " from" , $" StringBuilder.IndexOf: from ({from}) must be non-negative" ) |> raise
29+ if from < 0 then
30+ ArgumentOutOfRangeException( " from" , $" StringBuilder.IndexOf: from ({from}) must be non-negative" ) |> raise
3031 let len = sb.Length
31- if from >= len then ArgumentOutOfRangeException( " from" , $" StringBuilder.IndexOf: from ({from}) must be less than StringBuilder length ({len})" ) |> raise
32+ // if from >= len then
33+ // ArgumentOutOfRangeException("from",$"StringBuilder.IndexOf: from ({from}) must be less than StringBuilder length ({len})") |> raise
3234 let rec find i =
33- if i = len then - 1
34- elif sb.[ i] = c then i
35- else find ( i+ 1 )
35+ if i = len then
36+ - 1
37+ elif sb.[ i] = c then
38+ i
39+ else
40+ find ( i+ 1 )
3641 find( from)
3742
3843 /// Like list.IndexOf but for StringBuilder, returns -1 if not found
3944 /// Always uses StringComparison.Ordinal
40- /// Throws ArgumentOutOfRangeException if 'from' is out of range
45+ /// Throws ArgumentOutOfRangeException if 'from' is negative.
4146 member sb.IndexOf ( t : string , from : int ) : int =
4247 // could in theory be improved be using a rolling hash value
4348 // see also Array.findArray implementation
4449 // or https://stackoverflow.com/questions/12261344/fastest-search-method-in-stringbuilder
45- let ls = sb.Length
46- let lt = t.Length
47- if from < 0 then ArgumentOutOfRangeException( " from" , $" StringBuilder.IndexOf: from ({from}) must be non-negative" ) |> raise
48- if from >= ls then ArgumentOutOfRangeException( " from" , $" StringBuilder.IndexOf: from ({from}) must be less than StringBuilder length ({ls})" ) |> raise
49- //printfn "sb :%d t:%d" ls lt
50- let rec find ib it = // index in StringBuilder and index in search string
51- //printfn "Search at ib:%d %c for it:%d %c" ib sb.[ib] it t.[it]
52- if ib > ls- lt+ it then - 1 // not found! not enough chars left in StringBuilder to match remaining search string
53- elif sb.[ ib] = t.[ it] then
54- if it = lt-1 then ib - lt + 1 // found !
55- else find ( ib+ 1 ) ( it+ 1 )
56- else find ( ib+ 1 - it) 0
50+ let lenBuilder = sb.Length
51+ let lenText = t.Length
52+ if from < 0 then
53+ ArgumentOutOfRangeException( " from" , $" StringBuilder.IndexOf: from ({from}) must be non-negative" ) |> raise
54+
55+ // if from >= lenBuilder then
56+ // ArgumentOutOfRangeException("from",$"StringBuilder.IndexOf: from ({from}) must be less than StringBuilder length ({lenBuilder})") |> raise
57+
58+ let rec find idxBuilder idxText = // index in StringBuilder and index in search string
59+ if idxBuilder > lenBuilder- lenText+ idxText then
60+ - 1 // not found! not enough chars left in StringBuilder to match remaining search string
61+ elif sb.[ idxBuilder] = t.[ idxText] then
62+ if idxText = lenText-1 then
63+ idxBuilder - lenText + 1 // found !
64+ else
65+ find ( idxBuilder+ 1 ) ( idxText+ 1 )
66+ else
67+ find ( idxBuilder+ 1 - idxText) 0
5768 find from 0
5869
5970 /// Like list.IndexOf but for StringBuilder, returns -1 if not found
0 commit comments