class: CharacterArray
authorClaus Gittinger <cg@exept.de>
Sat, 31 Aug 2013 21:22:51 +0200
changeset 15734 d89a293a56e7
parent 15733 86c03a903221
child 15735 395899428c2f
class: CharacterArray added:10 methods comment/format in: #paddedTo: changed:12 methods unified the interface to methods with an ignoreCase/caseSensitive argument; now the recommended interface to call is the *caseSensitive:* variant, for compatibility with other smalltalks (and also, more so, to avoid the confusion when reading code) The old *ignoreCase* methods remain in the system marked as obsolete (but without an obsoleteMethodWarning, for a very long time, because lots of code out there is using that.
CharacterArray.st
--- a/CharacterArray.st	Sat Aug 31 15:28:11 2013 +0200
+++ b/CharacterArray.st	Sat Aug 31 21:22:51 2013 +0200
@@ -335,7 +335,7 @@
     ^ $\
 !
 
-matchScan:matchScanArray from:matchStart to:matchStop with:aString from:start to:stop ignoreCase:ignoreCase
+matchScan:matchScanArray from:matchStart to:matchStop with:aString from:start to:stop caseSensitive:caseSensitive
     "helper for match; return true if the characters from start to stop in
      aString are matching the scan in matchScan from matchStart to matchStop.
      The matchScan is as created by asMatchScanArray.
@@ -364,160 +364,160 @@
 "/ Transcript showCR:('match: ''' , (aString copyFrom:sStart to:sStop) ,
 "/                    ''' against:' , (matchScanArray copyFrom:mStart to:mStop) printString).
 
-	mSize := mStop - mStart + 1.
-	sSize := sStop - sStart + 1.
-
-	"empty strings match"
-	(mSize == 0) ifTrue:[^ (sSize == 0)].
-
-	matchEntry := matchScanArray at:mStart.
-
-	"/ the most common case first:
-	(sSize ~~ 0
-	and:[(checkChar := (aString at:sStart)) = matchEntry]) ifTrue:[
-	    "advance by one and continue"
-	    mStart := mStart + 1.
-	    sStart := sStart + 1
-	] ifFalse:[
-	    (matchEntry == #any) ifTrue:[
-		"restString empty -> no match"
-		(sSize == 0) ifTrue:[^ false].
-		"# matches single character"
-		((sSize == 1) and:[mSize == 1]) ifTrue:[^ true].
-		"advance by one and continue"
-		mStart := mStart + 1.
-		sStart := sStart + 1
-	    ] ifFalse:[
-		(matchEntry == #anyString) ifTrue:[
-		    "* alone matches anything"
-		    (mSize == 1) ifTrue:[^ true].
-		    "restString empty & matchString not empty -> no match"
-		    (sSize == 0) ifTrue:[^ false].
-
-		    "
-		     try to avoid some of the recursion by checking last
-		     character and continue with shortened strings if possible
-		    "
-		    quickCheck := false.
-		    (mStop >= mStart) ifTrue:[
-			matchLast := matchScanArray at:mStop.
-			(matchLast ~~ #anyString) ifTrue:[
-			    (matchLast == #any) ifTrue:[
-				quickCheck := true
-			    ] ifFalse:[
-				matchLast == (aString at:sStop) ifTrue:[
-				    quickCheck := true
-				] ifFalse:[
-				    matchLast isString ifTrue:[
-					quickCheck := matchLast includes:(aString at:sStop)
-				    ]
-				]
-			    ]
-			]
-		    ].
-		    quickCheck ifTrue:[
-			"
-			 quickCheck ok, advance from the right
-			"
-			mStop := mStop - 1.
-			sStop := sStop - 1
-		    ] ifFalse:[
-			"/ no quick check;
-			"/ look for the next character(s)
-			"/ and try matching there
-			"/ (to avoid recursion)
-
-			mStart < mStop ifTrue:[
-			    nextMatchEntry := matchScanArray at:mStart+1.
-			    nextMatchEntry isCharacter ifTrue:[
-				sStart <= sStop ifTrue:[
-				    [true] whileTrue:[
-					ignoreCase ifFalse:[
-					    index := aString indexOf:nextMatchEntry startingAt:sStart
-					] ifTrue:[
-					    index := aString findFirst:[:c | c asLowercase = nextMatchEntry asLowercase]
-							   startingAt:sStart.
-					].
-					(index == 0 or:[index > sStop]) ifTrue:[
-					    ^ false
-					].
-					(self matchScan:matchScanArray
-					      from:(mStart + 1)
-					      to:mStop
-					      with:aString
-					      from:index
-					      to:sStop
-					      ignoreCase:ignoreCase
-					) ifTrue:[
-					    ^ true
-					].
-					sStart := index + 1.
-				    ]
-				]
-			    ]
-			].
-
-			"
-			 no quick check possible;
-			 loop over all possible substrings
-			"
-			index := sStart.
-			[index <= sStop] whileTrue:[
-			    (self matchScan:matchScanArray
-				  from:(mStart + 1)
-				  to:mStop
-				  with:aString
-				  from:index
-				  to:sStop
-				  ignoreCase:ignoreCase
-			    ) ifTrue:[
-				^ true
-			    ].
-			    index := index + 1
-			].
-			^ false
-		    ].
-		] ifFalse:[
-		    (matchEntry isString) ifTrue:[
-			"testString empty -> no match"
-			(sSize == 0) ifTrue:[^ false].
-
-			included := false.
-			"/ checkChar := aString at:sStart.
-			included := matchEntry includes:checkChar.
-			included ifFalse:[
-			    ignoreCase ifTrue:[
-				checkChar isUppercase ifTrue:[
-				    included := matchEntry includes:checkChar asLowercase.
-				] ifFalse:[
-				    included := matchEntry includes:checkChar asUppercase.
-				]
-			    ].
-			].
-			mStart := mStart + 1.
-			mSize := mSize - 1.
-			included ifFalse:[^ false].
-
-			((sSize == 1) and:[mSize == 0]) ifTrue:[^ true].
-		    ] ifFalse:[
-			"/ must be single character
-
-			"testString empty ?"
-			(sSize == 0) ifTrue:[^ false].
-
-			"first characters equal ?"
-			"/ checkChar := aString at:sStart.
-			ignoreCase ifFalse:[^ false].
-			(checkChar asUppercase ~= matchEntry asUppercase) ifTrue:[^ false].
-
-			"advance and continue"
-			mStart := mStart + 1.
-		    ].
-		    "cut off 1st char and continue"
-		    sStart := sStart + 1
-		]
-	    ]
-	]
+        mSize := mStop - mStart + 1.
+        sSize := sStop - sStart + 1.
+
+        "empty strings match"
+        (mSize == 0) ifTrue:[^ (sSize == 0)].
+
+        matchEntry := matchScanArray at:mStart.
+
+        "/ the most common case first:
+        (sSize ~~ 0
+        and:[(checkChar := (aString at:sStart)) = matchEntry]) ifTrue:[
+            "advance by one and continue"
+            mStart := mStart + 1.
+            sStart := sStart + 1
+        ] ifFalse:[
+            (matchEntry == #any) ifTrue:[
+                "restString empty -> no match"
+                (sSize == 0) ifTrue:[^ false].
+                "# matches single character"
+                ((sSize == 1) and:[mSize == 1]) ifTrue:[^ true].
+                "advance by one and continue"
+                mStart := mStart + 1.
+                sStart := sStart + 1
+            ] ifFalse:[
+                (matchEntry == #anyString) ifTrue:[
+                    "* alone matches anything"
+                    (mSize == 1) ifTrue:[^ true].
+                    "restString empty & matchString not empty -> no match"
+                    (sSize == 0) ifTrue:[^ false].
+
+                    "
+                     try to avoid some of the recursion by checking last
+                     character and continue with shortened strings if possible
+                    "
+                    quickCheck := false.
+                    (mStop >= mStart) ifTrue:[
+                        matchLast := matchScanArray at:mStop.
+                        (matchLast ~~ #anyString) ifTrue:[
+                            (matchLast == #any) ifTrue:[
+                                quickCheck := true
+                            ] ifFalse:[
+                                matchLast == (aString at:sStop) ifTrue:[
+                                    quickCheck := true
+                                ] ifFalse:[
+                                    matchLast isString ifTrue:[
+                                        quickCheck := matchLast includes:(aString at:sStop)
+                                    ]
+                                ]
+                            ]
+                        ]
+                    ].
+                    quickCheck ifTrue:[
+                        "
+                         quickCheck ok, advance from the right
+                        "
+                        mStop := mStop - 1.
+                        sStop := sStop - 1
+                    ] ifFalse:[
+                        "/ no quick check;
+                        "/ look for the next character(s)
+                        "/ and try matching there
+                        "/ (to avoid recursion)
+
+                        mStart < mStop ifTrue:[
+                            nextMatchEntry := matchScanArray at:mStart+1.
+                            nextMatchEntry isCharacter ifTrue:[
+                                sStart <= sStop ifTrue:[
+                                    [true] whileTrue:[
+                                        caseSensitive ifTrue:[
+                                            index := aString indexOf:nextMatchEntry startingAt:sStart
+                                        ] ifFalse:[
+                                            index := aString findFirst:[:c | c asLowercase = nextMatchEntry asLowercase]
+                                                             startingAt:sStart.
+                                        ].
+                                        (index == 0 or:[index > sStop]) ifTrue:[
+                                            ^ false
+                                        ].
+                                        (self matchScan:matchScanArray
+                                              from:(mStart + 1)
+                                              to:mStop
+                                              with:aString
+                                              from:index
+                                              to:sStop
+                                              caseSensitive:caseSensitive
+                                        ) ifTrue:[
+                                            ^ true
+                                        ].
+                                        sStart := index + 1.
+                                    ]
+                                ]
+                            ]
+                        ].
+
+                        "
+                         no quick check possible;
+                         loop over all possible substrings
+                        "
+                        index := sStart.
+                        [index <= sStop] whileTrue:[
+                            (self matchScan:matchScanArray
+                                  from:(mStart + 1)
+                                  to:mStop
+                                  with:aString
+                                  from:index
+                                  to:sStop
+                                  caseSensitive:caseSensitive
+                            ) ifTrue:[
+                                ^ true
+                            ].
+                            index := index + 1
+                        ].
+                        ^ false
+                    ].
+                ] ifFalse:[
+                    (matchEntry isString) ifTrue:[
+                        "testString empty -> no match"
+                        (sSize == 0) ifTrue:[^ false].
+
+                        included := false.
+                        "/ checkChar := aString at:sStart.
+                        included := matchEntry includes:checkChar.
+                        included ifFalse:[
+                            caseSensitive ifFalse:[
+                                checkChar isUppercase ifTrue:[
+                                    included := matchEntry includes:checkChar asLowercase.
+                                ] ifFalse:[
+                                    included := matchEntry includes:checkChar asUppercase.
+                                ]
+                            ].
+                        ].
+                        mStart := mStart + 1.
+                        mSize := mSize - 1.
+                        included ifFalse:[^ false].
+
+                        ((sSize == 1) and:[mSize == 0]) ifTrue:[^ true].
+                    ] ifFalse:[
+                        "/ must be single character
+
+                        "testString empty ?"
+                        (sSize == 0) ifTrue:[^ false].
+
+                        "first characters equal ?"
+                        "/ checkChar := aString at:sStart.
+                        caseSensitive ifTrue:[^ false].
+                        (checkChar asUppercase ~= matchEntry asUppercase) ifTrue:[^ false].
+
+                        "advance and continue"
+                        mStart := mStart + 1.
+                    ].
+                    "cut off 1st char and continue"
+                    sStart := sStart + 1
+                ]
+            ]
+        ]
     ].
 
     "
@@ -526,13 +526,13 @@
      scanArray := self matchScanArrayFrom:'*hello'.
      s := 'foo bar hello world'.
      CharacterArray
-	 matchScan:scanArray
-	 from:1
-	 to:scanArray size
-	 with:s
-	 from:1
-	 to:s size
-	 ignoreCase:false
+         matchScan:scanArray
+         from:1
+         to:scanArray size
+         with:s
+         from:1
+         to:s size
+         caseSensitive:true
     "
     "
      |scanArray s|
@@ -540,13 +540,59 @@
      scanArray := self matchScanArrayFrom:'*hello*'.
      s := 'foo bar hello world'.
      CharacterArray
-	 matchScan:scanArray
-	 from:1
-	 to:scanArray size
-	 with:s
-	 from:1
-	 to:s size
-	 ignoreCase:false
+         matchScan:scanArray
+         from:1
+         to:scanArray size
+         with:s
+         from:1
+         to:s size
+         caseSensitive:true
+    "
+
+    "Modified: / 24-07-2011 / 07:17:03 / cg"
+    "Modified (comment): / 24-07-2011 / 08:55:14 / cg"
+!
+
+matchScan:matchScanArray from:matchStart to:matchStop with:aString from:start to:stop ignoreCase:ignoreCase
+    <resource: #obsolete>
+    "helper for match; return true if the characters from start to stop in
+     aString are matching the scan in matchScan from matchStart to matchStop.
+     The matchScan is as created by asMatchScanArray.
+
+     This algorithm is not at all the most efficient;
+     for heavy duty pattern matching, an interface (primitive) to the regex
+     pattern matching package should be added."
+
+    ^ self
+        matchScan:matchScanArray from:matchStart to:matchStop with:aString from:start to:stop caseSensitive:ignoreCase not
+
+    "
+     |scanArray s|
+
+     scanArray := self matchScanArrayFrom:'*hello'.
+     s := 'foo bar hello world'.
+     CharacterArray
+         matchScan:scanArray
+         from:1
+         to:scanArray size
+         with:s
+         from:1
+         to:s size
+         ignoreCase:false
+    "
+    "
+     |scanArray s|
+
+     scanArray := self matchScanArrayFrom:'*hello*'.
+     s := 'foo bar hello world'.
+     CharacterArray
+         matchScan:scanArray
+         from:1
+         to:scanArray size
+         with:s
+         from:1
+         to:s size
+         ignoreCase:false
     "
 
     "Modified: / 24-07-2011 / 07:17:03 / cg"
@@ -2215,7 +2261,24 @@
     "Modified: 22.4.1996 / 15:56:17 / cg"
 !
 
+sameAs:aString caseSensitive:caseSensitive
+    "Compare the receiver with the argument.
+     If caseSensitive is false, this is the same as #sameAs:,
+     if false, this is the same as #=."
+
+    caseSensitive ifFalse:[
+        ^ self sameAs:aString
+    ].
+    ^ self = aString
+
+    "
+     'foo' sameAs:'Foo' caseSensitive:false
+     'foo' sameAs:'foo' caseSensitive:true
+    "
+!
+
 sameAs:aString ignoreCase:ignoreCase
+    <resource: #obsolete>
     "Compare the receiver with the argument.
      If ignoreCase is true, this is the same as #sameAs:,
      if false, this is the same as #=."
@@ -3971,11 +4034,11 @@
      This is usable with fileName pattern fields.
 
      NOTICE: match-meta character interpretation is like in unix-matching (glob),
-	     NOT the ST-80 meaning.
+             NOT the ST-80 meaning.
      NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
      NOTICE: the receiver is the match pattern"
 
-    ^self compoundMatch:aString ignoreCase:false
+    ^self compoundMatch:aString caseSensitive:true
 
     "
      'f*' match:'foo'
@@ -3990,27 +4053,54 @@
     "Modified: / 16.12.1999 / 01:22:08 / cg"
 !
 
-compoundMatch:aString ignoreCase:ignoreCase
+compoundMatch:aString caseSensitive:caseSensitive
     "like match, but the receiver may be a compound match pattern,
      consisting of multiple simple GLOB patterns, separated by semicolons.
      This is usable with fileName pattern fields.
 
      NOTICE: match-meta character interpretation is like in unix-matching (glob),
-	     NOT the ST-80 meaning.
+             NOT the ST-80 meaning.
      NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
      NOTICE: the receiver is the match pattern"
 
     |matchers|
 
     matchers := self asCollectionOfSubstringsSeparatedBy:$;.
-    ^ matchers contains:[:aPattern |
-	aPattern match:aString ignoreCase:ignoreCase escapeCharacter:nil
-      ].
-
-"/    matchers do:[:aPattern |
-"/        (aPattern match:aString ignoreCase:ignoreCase) ifTrue:[^ true].
-"/    ].
-"/    ^ false.
+    ^ matchers 
+        contains:[:aPattern |
+            aPattern match:aString ignoreCase:caseSensitive not escapeCharacter:nil
+        ].
+
+    "
+     'f*' match:'foo'
+     'b*' match:'foo'
+     'f*;b*' match:'foo'
+     'f*;b*' match:'bar'
+     'f*;b*' compoundMatch:'foo'
+     'f*;b*' compoundMatch:'bar'
+     'f*;b*' compoundMatch:'Foo' caseSensitive:false
+     'f*;b*' compoundMatch:'Bar' caseSensitive:false
+     'f*;b*' compoundMatch:'ccc' caseSensitive:false
+    "
+
+    "Modified: / 15.4.1997 / 15:50:33 / cg"
+    "Modified: / 30.1.1998 / 11:40:18 / stefan"
+    "Created: / 16.12.1999 / 01:21:35 / cg"
+!
+
+compoundMatch:aString ignoreCase:ignoreCase
+    <resource: #obsolete>
+
+    "like match, but the receiver may be a compound match pattern,
+     consisting of multiple simple GLOB patterns, separated by semicolons.
+     This is usable with fileName pattern fields.
+
+     NOTICE: match-meta character interpretation is like in unix-matching (glob),
+             NOT the ST-80 meaning.
+     NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
+     NOTICE: the receiver is the match pattern"
+
+    ^ self compoundMatch:aString caseSensitive:ignoreCase not
 
     "
      'f*' match:'foo'
@@ -4055,7 +4145,7 @@
     ^ self findMatchString:matchString startingAt:index ignoreCase:false ifAbsent:0
 !
 
-findMatchString:matchString startingAt:index ignoreCase:ignoreCase ifAbsent:exceptionBlock
+findMatchString:matchString startingAt:index caseSensitive:caseSensitive ifAbsent:exceptionBlock
     "like findString, but allowing GLOB match patterns.
      find matchstring, starting at index. if found, return the index;
      if not found, return the result of evaluating exceptionBlock.
@@ -4089,7 +4179,7 @@
 
     firstChar asString includesMatchCharacters ifTrue:[
         index to:mySize do:[:col |
-            (realMatchString match:self from:col to:mySize ignoreCase:ignoreCase)
+            (realMatchString match:self from:col to:mySize caseSensitive:caseSensitive)
             ifTrue:[^ col]
         ].
         ^ exceptionBlock value.
@@ -4097,14 +4187,14 @@
 
     lcChar := firstChar asLowercase.
     ucChar := firstChar asUppercase.
-    (ignoreCase and:[ lcChar ~= ucChar]) ifTrue:[
+    (caseSensitive not and:[ lcChar ~= ucChar ]) ifTrue:[
         firstSet := Array with:ucChar with:lcChar.
         startIndex := self indexOfAny:firstSet startingAt:index.
     ] ifFalse:[
         startIndex := self indexOf:firstChar startingAt:index.
     ].
     [startIndex == 0] whileFalse:[
-        (realMatchString match:self from:startIndex to:mySize ignoreCase:ignoreCase)
+        (realMatchString match:self from:startIndex to:mySize caseSensitive:caseSensitive)
         ifTrue:[^ startIndex].
 
         firstSet notNil ifTrue:[
@@ -4118,6 +4208,34 @@
     "
      'one two three four' findMatchString:'o[nu]'
      'one two three four' findMatchString:'o[nu]' startingAt:3
+     'one two three four one' findMatchString:'ONE' startingAt:3 caseSensitive:false ifAbsent:0
+     'one two three four one' findMatchString:'ONE' startingAt:3 caseSensitive:true ifAbsent:0
+     'one two three four ONE' findMatchString:'O#E' startingAt:1 caseSensitive:false ifAbsent:0
+     'one two three four ONE' findMatchString:'O#E' startingAt:1 caseSensitive:true ifAbsent:0
+      12345678901234567890
+    "
+
+    "Modified: 13.9.1997 / 06:31:22 / cg"
+!
+
+findMatchString:matchString startingAt:index ignoreCase:ignoreCase ifAbsent:exceptionBlock
+    <resource: #obsolete>
+    "like findString, but allowing GLOB match patterns.
+     find matchstring, starting at index. if found, return the index;
+     if not found, return the result of evaluating exceptionBlock.
+     This is a q&d hack - not very efficient.
+
+     NOTICE: match-meta character interpretation is like in unix-matching (glob),
+             NOT the ST-80 meaning.
+     NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
+     NOTICE: the argument is the match pattern"
+
+    ^ self 
+        findMatchString:matchString startingAt:index caseSensitive:ignoreCase not ifAbsent:exceptionBlock
+
+    "
+     'one two three four' findMatchString:'o[nu]'
+     'one two three four' findMatchString:'o[nu]' startingAt:3
      'one two three four one' findMatchString:'ONE' startingAt:3 ignoreCase:true ifAbsent:0
     "
 
@@ -4179,11 +4297,11 @@
      The escape character is the backQuote.
 
      NOTICE: match-meta character interpretation is like in unix-matching (glob),
-	     NOT the ST-80 meaning.
+             NOT the ST-80 meaning.
      NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
      NOTICE: the receiver is the match pattern"
 
-    ^ self match:aString from:1 to:aString size ignoreCase:false
+    ^ self match:aString from:1 to:aString size caseSensitive:true
 
     "
      '\*f*' match:'f'
@@ -4204,6 +4322,87 @@
     "Modified: / 9.6.1998 / 18:50:00 / cg"
 !
 
+match:aString caseSensitive:caseSensitive
+    "return true if aString matches self, where self may contain GLOB meta-match
+     characters $* (to match any string) or $# (to match any character)
+     or [...] to match a set of characters.
+     If caseSensitive is false, lower/uppercase are considered the same.
+     The escape character is the backQuote.
+
+     NOTICE: match-meta character interpretation is like in unix-matching (glob),
+             NOT the ST-80 meaning.
+     NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
+     NOTICE: the receiver is the match pattern"
+
+    ^ self match:aString from:1 to:aString size caseSensitive:caseSensitive
+
+    "
+     '*ute*' match:'COMPUTER' caseSensitive:false
+     '*uter' match:'COMPUTER' caseSensitive:true
+     '[abcd]*' match:'computer' caseSensitive:true
+     '[abcd]*' match:'Computer' caseSensitive:true
+     '[a-k]*' match:'komputer' caseSensitive:true
+     '[a-k]*' match:'zomputer' caseSensitive:true
+     '[a-k]*' match:'Komputer' caseSensitive:true
+     '[a-k]*' match:'Komputer' caseSensitive:false
+     '*some*compl*ern*' match:'this is some more complicated pattern match' caseSensitive:false
+     '*some*compl*ern*' match:'this is another complicated pattern match' caseSensitive:false
+
+     Time millisecondsToRun:[
+        Symbol allInstancesDo:[:sym |
+            '[ab]*' match:sym caseSensitive:true
+        ]
+     ].
+     Time millisecondsToRun:[
+        Symbol allInstancesDo:[:sym |
+            '*at:*' match:sym caseSensitive:true
+        ]
+     ].
+    "
+
+    "Modified: 2.4.1997 / 17:28:58 / cg"
+!
+
+match:aString caseSensitive:caseSensitive escapeCharacter:escape
+    "return true if aString matches self, where self may contain GLOB meta-match
+     characters $* (to match any string) or $# (to match any character)
+     or [...] to match a set of characters.
+     If caseSensitive is false, lower/uppercase are considered the same.
+
+     NOTICE: match-meta character interpretation is like in unix-matching (glob),
+             NOT the ST-80 meaning.
+     NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
+     NOTICE: the receiver is the match pattern"
+
+    ^ self match:aString from:1 to:aString size caseSensitive:caseSensitive escapeCharacter:escape
+
+    "
+     '*ute*' match:'COMPUTER' caseSensitive:false
+     '*uter' match:'COMPUTER' caseSensitive:true
+     '[abcd]*' match:'computer' caseSensitive:true
+     '[abcd]*' match:'Computer' caseSensitive:true
+     '[a-k]*' match:'komputer' caseSensitive:true
+     '[a-k]*' match:'zomputer' caseSensitive:true
+     '[a-k]*' match:'Komputer' caseSensitive:true
+     '[a-k]*' match:'Komputer' caseSensitive:false
+     '*some*compl*ern*' match:'this is some more complicated pattern match' caseSensitive:false
+     '*some*compl*ern*' match:'this is another complicated pattern match' caseSensitive:false
+
+     Time millisecondsToRun:[
+        Symbol allInstancesDo:[:sym |
+            '[ab]*' match:sym caseSensitive:true
+        ]
+     ].
+     Time millisecondsToRun:[
+        Symbol allInstancesDo:[:sym |
+            '*at:*' match:sym caseSensitive:true
+        ]
+     ].
+    "
+
+    "Modified: 2.4.1997 / 17:28:58 / cg"
+!
+
 match:aString escapeCharacter:escape
     "return true if aString matches self, where self may contain GLOB meta-match
      characters $* (to match any string) or $# (to match any character).
@@ -4223,7 +4422,80 @@
     "
 !
 
+match:aString from:start to:stop caseSensitive:caseSensitive
+    "return true if part of aString matches myself,
+     where self may contain GLOB meta-match
+     characters $* (to match any string) or $# (to match any character)
+     or [...] to match a set of characters.
+     If caseSensitive is false, lower/uppercase are considered the same.
+     The escape character is the backQuote.
+
+     NOTICE: match-meta character interpretation is like in unix-matching (glob),
+             NOT the ST-80 meaning.
+     NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
+     NOTICE: the receiver is the match pattern"
+
+    ^ self
+        match:aString from:start to:stop caseSensitive:caseSensitive
+        escapeCharacter:(self class matchEscapeCharacter)
+
+    "
+     '*ute*' match:'12345COMPUTER' from:1 to:5 caseSensitive:false
+     '*ute*' match:'12345COMPUTER' from:6 to:13 caseSensitive:false
+    "
+
+    "Modified: / 10.11.1998 / 21:43:46 / cg"
+!
+
+match:aString from:start to:stop caseSensitive:caseSensitive escapeCharacter:escape
+    "return true if part of aString matches myself,
+     where self may contain GLOB meta-match
+     characters $* (to match any string) or $# (to match any character)
+     or [...] to match a set of characters.
+     If caseSensitive is false, lower/uppercase are considered the same.
+
+     NOTICE: match-meta character interpretation is like in unix-matching (glob),
+             NOT the ST-80 meaning.
+     NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
+     NOTICE: the receiver is the match pattern"
+
+    |matchScanArray|
+
+    "
+     keep the matchScanArray from the most recent match -
+     avoids parsing the pattern over-and over if multiple searches
+     are done with the same pattern.
+    "
+    (PreviousMatch notNil
+    and:[PreviousMatch key = self]) ifTrue:[
+        matchScanArray := PreviousMatch value
+    ] ifFalse:[
+        matchScanArray := self class matchScanArrayFrom:self escapeCharacter:escape.
+        matchScanArray isNil ifTrue:[
+            'CharacterArray [info]: invalid matchpattern:''' infoPrint. self infoPrint. ''' comparing for equality.' infoPrintCR.
+            ^ self = aString
+"/            ^ false
+        ].
+        PreviousMatch := self -> matchScanArray.
+    ].
+
+    ^ self class
+        matchScan:matchScanArray
+        from:1 to:matchScanArray size
+        with:aString
+        from:start to:stop
+        caseSensitive:caseSensitive
+
+    "
+     '*ute*' match:'12345COMPUTER' from:1 to:5 caseSensitive:false
+     '*ute*' match:'12345COMPUTER' from:6 to:13 caseSensitive:false
+    "
+
+    "Modified: / 10.11.1998 / 21:43:46 / cg"
+!
+
 match:aString from:start to:stop ignoreCase:ignoreCase
+    <resource: #obsolete>
     "return true if part of aString matches myself,
      where self may contain GLOB meta-match
      characters $* (to match any string) or $# (to match any character)
@@ -4249,6 +4521,7 @@
 !
 
 match:aString from:start to:stop ignoreCase:ignoreCase escapeCharacter:escape
+    <resource: #obsolete>
     "return true if part of aString matches myself,
      where self may contain GLOB meta-match
      characters $* (to match any string) or $# (to match any character)
@@ -4256,36 +4529,14 @@
      If ignoreCase is true, lower/uppercase are considered the same.
 
      NOTICE: match-meta character interpretation is like in unix-matching (glob),
-	     NOT the ST-80 meaning.
+             NOT the ST-80 meaning.
      NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
      NOTICE: the receiver is the match pattern"
 
-    |matchScanArray|
-
-    "
-     keep the matchScanArray from the most recent match -
-     avoids parsing the pattern over-and over if multiple searches
-     are done with the same pattern.
-    "
-    (PreviousMatch notNil
-    and:[PreviousMatch key = self]) ifTrue:[
-	matchScanArray := PreviousMatch value
-    ] ifFalse:[
-	matchScanArray := self class matchScanArrayFrom:self escapeCharacter:escape.
-	matchScanArray isNil ifTrue:[
-	    'CharacterArray [info]: invalid matchpattern:''' infoPrint. self infoPrint. ''' comparing for equality.' infoPrintCR.
-	    ^ self = aString
-"/            ^ false
-	].
-	PreviousMatch := self -> matchScanArray.
-    ].
-
-    ^ self class
-	matchScan:matchScanArray
-	from:1 to:matchScanArray size
-	with:aString
-	from:start to:stop
-	ignoreCase:ignoreCase
+    ^ self 
+        match:aString from:start to:stop 
+        caseSensitive:ignoreCase not 
+        escapeCharacter:escape
 
     "
      '*ute*' match:'12345COMPUTER' from:1 to:5 ignoreCase:true
@@ -4296,6 +4547,7 @@
 !
 
 match:aString ignoreCase:ignoreCase
+    <resource: #obsolete>
     "return true if aString matches self, where self may contain GLOB meta-match
      characters $* (to match any string) or $# (to match any character)
      or [...] to match a set of characters.
@@ -4303,10 +4555,11 @@
      The escape character is the backQuote.
 
      NOTICE: match-meta character interpretation is like in unix-matching (glob),
-	     NOT the ST-80 meaning.
+             NOT the ST-80 meaning.
      NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
      NOTICE: the receiver is the match pattern"
 
+    "/ leave it this way, in case a customer has redefined it for performance (for a while)
     ^ self match:aString from:1 to:aString size ignoreCase:ignoreCase
 
     "
@@ -4322,14 +4575,14 @@
      '*some*compl*ern*' match:'this is another complicated pattern match' ignoreCase:true
 
      Time millisecondsToRun:[
-	Symbol allInstancesDo:[:sym |
-	    '[ab]*' match:sym ignoreCase:false
-	]
+        Symbol allInstancesDo:[:sym |
+            '[ab]*' match:sym ignoreCase:false
+        ]
      ].
      Time millisecondsToRun:[
-	Symbol allInstancesDo:[:sym |
-	    '*at:*' match:sym ignoreCase:false
-	]
+        Symbol allInstancesDo:[:sym |
+            '*at:*' match:sym ignoreCase:false
+        ]
      ].
     "
 
@@ -4337,6 +4590,7 @@
 !
 
 match:aString ignoreCase:ignoreCase escapeCharacter:escape
+    <resource: #obsolete>
     "return true if aString matches self, where self may contain GLOB meta-match
      characters $* (to match any string) or $# (to match any character)
      or [...] to match a set of characters.
@@ -4390,7 +4644,21 @@
     ^ aPatternString match:self
 !
 
+matches:aPatternString caseSensitive:caseSensitive
+    "return true if the receiver matches aString, where aPatternString may contain GLOB meta-match
+     characters $* (to match any string) or $# (to match any character).
+     or [...] to match a set of characters.
+
+     NOTICE: match-meta character interpretation is like in unix-matching (glob),
+             NOT the ST-80 meaning.
+     NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
+     NOTICE: the receiver is the match pattern"
+
+    ^ aPatternString match:self caseSensitive:caseSensitive
+!
+
 matches:aPatternString ignoreCase:ignoreCase
+    <resource: #obsolete>
     "return true if the receiver matches aString, where aPatternString may contain GLOB meta-match
      characters $* (to match any string) or $# (to match any character).
      or [...] to match a set of characters.
@@ -4401,7 +4669,7 @@
      NOTICE: this is GLOB, which is different from regex matching (see matchesRegex:)
      NOTICE: the receiver is the match pattern"
 
-    ^ aPatternString match:self ignoreCase:ignoreCase
+    ^ aPatternString match:self caseSensitive:ignoreCase not
 
     "Created: / 08-03-2012 / 03:11:11 / cg"
 ! !
@@ -4558,6 +4826,7 @@
     "
      'foo' paddedTo:10
      123 printString paddedTo:10
+     '12345678901234' paddedTo:10
     "
 ! !
 
@@ -5909,6 +6178,18 @@
     "
 !
 
+findString:subString caseSensitive:caseSensitive
+    "find a substring. if found, return the index;
+     if not found, return 0."
+
+    ^ self indexOfSubCollection:subString startingAt:1 ifAbsent:0 caseSensitive:caseSensitive
+
+    "
+     'hello world' findString:'LLo' caseSensitive:true
+     'hello world' findString:'LLo' caseSensitive:false
+    "
+!
+
 findString:subString ifAbsent:exceptionBlock
     "find a substring. If found, return the index;
      if not found, return the result of evaluating exceptionBlock."
@@ -5917,6 +6198,7 @@
 !
 
 findString:subString ignoreCase:ignoreCase
+    <resource: #obsolete>
     "find a substring. if found, return the index;
      if not found, return 0."
 
@@ -6433,11 +6715,11 @@
 !CharacterArray class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/CharacterArray.st,v 1.512 2013-08-27 07:30:41 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/CharacterArray.st,v 1.513 2013-08-31 19:22:51 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/CharacterArray.st,v 1.512 2013-08-27 07:30:41 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/CharacterArray.st,v 1.513 2013-08-31 19:22:51 cg Exp $'
 ! !