{ import: Object } { import: TestCase } "Utility miscellaneous snipets. I hope these are included in the standard library." "----------------------------------------------------------------" "Bug fix" OrderedCollection makeRoomAtLast [ (self size == 0 and: [array size > 0]) ifTrue: [^self resetToBeginning]. (self size * 2 < array size) ifTrue: [^self shiftToBeginning]. array := (array new: self size + (array size max: 2)) replaceFrom: firstIndex to: lastIndex - 1 with: array startingAt: firstIndex; yourself. ] "----------------------------------------------------------------" Object inspect [ | slots value | StdErr nextPutAll: '=========='; cr. StdErr nextPutAll: self debugName; cr. StdErr nextPutAll: '----------'; cr. slots := self slots. slots keys do: [:key | StdErr nextPutAll: key, ' : '. value := self _oopAt: (slots at: key) key / 4. StdErr nextPutAll: value printString; cr]. ] Object browse [ StdErr nextPutAll: '=========='; cr. StdErr nextPutAll: self debugName; cr. StdErr nextPutAll: '----------'; cr. self _vtable selectors do: [ :selector | StdErr nextPutAll: selector printString; cr ]. ] Object err [ StdErr nextPutAll: self printString; cr ] "stupid short cut" Collection remove: anObject [ ^self remove: anObject ifAbsent: [self errorNotFound: anObject] ] Collection select: aBlock [ | newCollection | newCollection := self new. self do: [:each | (aBlock value: each) ifTrue: [newCollection add: each]]. ^newCollection ] "----------------------------------------------------------------" "for debugging" OrderedCollection _printOn: aStream [ super printOn: aStream. aStream cr. aStream nextPutAll: 'array: ', array printString; cr. aStream nextPutAll: 'firstIndex: ', firstIndex printString; cr. aStream nextPutAll: 'lastIndex: ', lastIndex printString; cr. ] SequenceableCollection findBinary: aBlock ifNone: exceptionBlock [ "Search for an element in the receiver using binary search. The argument aBlock is a one-element block returning 0 - if the element is the one searched for <0 - if the search should continue in the first half >0 - if the search should continue in the second half If no matching element is found, evaluate exceptionBlock." | index low high test item | low := 0. high := self size - 1. [index := high + low // 2. low > high] whileFalse:[ test := aBlock value: (item := self at: index). test = 0 ifTrue:[^item] ifFalse:[test > 0 ifTrue: [low := index + 1] ifFalse: [high := index - 1]]]. ^exceptionBlock value ] SequenceableCollection replaceFrom: first size: size with: aCollection [ ^ self replaceFrom: first to: first + size - 1 with: aCollection ] SequenceableCollection copyFrom: first size: size [ ^ self copyFrom: first to: first + size - 1 ] SequenceableCollection split: delimiter [ | lines start | "Splits the collection into a list of collections. Delimiters and empty elements are preserved. The behavior is different against Perl, Python, or Ruby." lines := WriteStream on: (Array new: 8). start := 0. self doWithIndex: [ :char :end | char = delimiter ifTrue: [ lines nextPut: (self copyFrom: start to: end). start := end + 1 ]]. start <= self size ifTrue: [ lines nextPut: (self copyFrom: start to: self size - 1)]. ^ lines contents ] "----------------------------------------------------------------" UtilityTest : TestCase () UtilityTest testSplit [ self assert: ('12345X12345' split: $X) size equals: 2. self assert: ('12345X12345X' split: $X) size equals: 3. self assert: ('12345X12345X' split: $X) second equals: '12345X'. self assert: ('12345X12345X' split: $X) third equals: ''. self assert: ('X' split: $X) size equals: 2. self assert: ('12345X12345X' asArray split: $X) size equals: 3. ]