#BUGFIX by stefan
authorStefan Vogel <sv@exept.de>
Thu, 21 Sep 2017 15:58:22 +0200
changeset 22278 dd1e56c2ad85
parent 22277 fa9b693b2809
child 22279 3b4d8c69aa0d
#BUGFIX by stefan class: StringCollection added: #collect: #collect:thenSelect: #select:thenCollect: changed: #asString #copyEmpty: #copyEmptyAndGrow: class: StringCollection class added: #newWithCapacity: 1. collect:... now returns an OrderedCollection, if there are elements which are non-strings. 2. printString/asString does not DNU, if there are non-string elements in StringCollection
StringCollection.st
--- a/StringCollection.st	Thu Sep 21 15:27:23 2017 +0200
+++ b/StringCollection.st	Thu Sep 21 15:58:22 2017 +0200
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
 "
  COPYRIGHT (c) 1989 by Claus Gittinger
 	      All Rights Reserved
@@ -95,6 +97,18 @@
     "
 !
 
+newWithCapacity:size
+    "return a new empty string collection with size capacity"
+
+    ^ super new:size.
+
+    "   
+     StringCollection newWithCapacity:10
+    "
+
+    "Created: / 21-09-2017 / 15:37:49 / stefan"
+!
+
 newWithSize:size
     "return a new string collection with size empty lines"
 
@@ -106,11 +120,23 @@
 asString
     "return myself as a string with embedded cr's"
 
-    ^ self 
-        asStringWith:Character cr
-        from:1 to:(self size) 
-        compressTabs:false 
-        final:Character cr
+    ^ [
+        self 
+            asStringWith:Character cr
+            from:1 to:(self size) 
+            compressTabs:false 
+            final:Character cr
+    ] on:ConversionError do:[:ex|
+        "non-string elements trigger a ComversionError. Fall back..."
+        super printString.
+    ].
+
+    "
+        #('This' 'is' 'some' 'text') asStringCollection asString
+        #('This' 22 'some' 'text') asStringCollection asString
+    "
+
+    "Modified (format): / 21-09-2017 / 12:52:00 / stefan"
 !
 
 asStringCollection
@@ -223,16 +249,23 @@
      does allocate size nil lines (it does an implicit #grow: size).
      In order to get #collect: working, we should not perform this implicit grow"
 
-    ^ super copyEmpty:0.
+    ^ self class newWithCapacity:size.
 
-    "Created: 14.2.1996 / 11:05:47 / stefan"
+    "Created: / 14-02-1996 / 11:05:47 / stefan"
+    "Modified: / 21-09-2017 / 15:43:49 / stefan"
 !
 
 copyEmptyAndGrow:size
     "performance optimization: 
-     StringCollections are always grown to size after #new: / #copyEmpty:"
+     StringCollections are always grown to size after #new: (containing nil elements)"
+
+    ^ self species new:size.
 
-    ^ super copyEmpty:size.
+    "
+        #('some' 'text' 'bla') asStringCollection copyEmptyAndGrow:20
+    "
+
+    "Modified: / 21-09-2017 / 15:46:18 / stefan"
 !
 
 withoutLeadingAndTrailingBlankLines
@@ -329,6 +362,115 @@
     "
 ! !
 
+!StringCollection methodsFor:'enumerating'!
+
+collect:aBlock
+    "evaluate the argument, aBlock for every element in the collection
+     and return a collection of the results.
+
+     Redefined, to change the result collection to an OrderedCollection if
+     not all elements are valid for a StringCollection (must be string or nil)."
+
+    |newCollection newElement onlyStrings
+     start  "{ Class:SmallInteger }"
+     stop   "{ Class:SmallInteger }" |
+
+    onlyStrings := true.    "/ ... until proven otherwise         
+    newCollection := self class newWithCapacity:(self size).
+    stop := lastIndex.
+    start := firstIndex.
+    start to:stop do:[:index |
+        newElement := aBlock value:(contentsArray at:index).
+        (onlyStrings and:[newElement notNil and:[newElement isString not]]) ifTrue:[
+            onlyStrings := false.
+            newCollection := newCollection asOrderedCollection.
+        ].
+        newCollection add:newElement.
+    ].
+    ^ newCollection
+
+    "
+     #('this' 'is' 'some' nil 'text') asStringCollection collect:[:i | i]
+     #('this' true 'some' nil 'text') asStringCollection collect:[:i | i ]
+    "
+
+    "Created: / 21-09-2017 / 14:31:31 / stefan"
+    "Modified: / 21-09-2017 / 15:55:21 / stefan"
+!
+
+collect:collectBlock thenSelect:selectBlock
+    "combination of collect followed by select;
+     redefined to avoid the creation of an intermediate (garbage) collection.
+
+     Redefined, to change the result collection to an OrderedCollection if
+     not all elements are valid for a StringCollection (must be string or nil)."
+
+    |newCollection newElement onlyStrings
+     start  "{ Class:SmallInteger }"
+     stop   "{ Class:SmallInteger }" |
+
+    onlyStrings := true.    "/ ... until proven otherwise         
+    newCollection := self class newWithCapacity:(self size).
+    stop := lastIndex.
+    start := firstIndex.
+    start to:stop do:[:index |
+        newElement := collectBlock value:(contentsArray at:index).
+        (selectBlock value:newElement) ifTrue:[
+            (onlyStrings and:[newElement notNil and:[newElement isString not]]) ifTrue:[
+                onlyStrings := false.
+                newCollection := newCollection asOrderedCollection.
+            ].
+            newCollection add:newElement.
+        ]
+    ].
+    ^ newCollection
+
+    "
+     #('this' 'is' 'some' nil 'text') asStringCollection collect:[:i | i] thenSelect:[:e| e notNil]
+     #('this' true 'some' nil 'text') asStringCollection collect:[:i | i ] thenSelect:[:e| e notNil]
+    "
+
+    "Created: / 21-09-2017 / 14:34:46 / stefan"
+    "Modified: / 21-09-2017 / 15:55:05 / stefan"
+!
+
+select:selectBlock thenCollect:collectBlock
+    "combination of select followed by collect;
+     redefined to avoid the creation of an intermediate (garbage) collection.
+
+     Redefined, to change the result collection to an OrderedCollection if
+     not all elements are valid for a StringCollection (must be string or nil)."
+
+    |newCollection element newElement onlyStrings
+     start  "{ Class:SmallInteger }"
+     stop   "{ Class:SmallInteger }" |
+
+    onlyStrings := true.    "/ ... until proven otherwise         
+    newCollection := self class newWithCapacity:(self size).
+    stop := lastIndex.
+    start := firstIndex.
+    start to:stop do:[:index |
+        element := contentsArray at:index.
+        (selectBlock value:element) ifTrue:[
+            newElement := collectBlock value:element.
+            (onlyStrings and:[newElement notNil and:[newElement isString not]]) ifTrue:[
+                onlyStrings := false.
+                newCollection := newCollection asOrderedCollection.
+            ].
+            newCollection add:newElement.
+        ]
+    ].
+    ^ newCollection
+
+    "
+     #('this' 'is' 'some' nil 'text') asStringCollection select:[:e| e notNil] thenCollect:[:i | i]
+     #('this' true 'some' nil 'text') asStringCollection select:[:e| e notNil] thenCollect:[:i | i]
+    "
+
+    "Created: / 21-09-2017 / 14:42:20 / stefan"
+    "Modified: / 21-09-2017 / 15:54:33 / stefan"
+! !
+
 
 !StringCollection methodsFor:'printing & storing'!