<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2017-11-30 21:57 GMT+01:00 <span dir="ltr"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Nicolas Cellier uploaded a new version of Collections to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Collections-nice.771.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/<wbr>trunk/Collections-nice.771.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Collections-nice.771<br>
Author: nice<br>
Time: 30 November 2017, 9:57:27.873964 pm<br>
UUID: d8b64711-6119-429b-b3f5-<wbr>259b46ef864b<br>
Ancestors: Collections-nice.770<br>
<br>
Fix awfully broken CharacterSetComplement select:/reject:<br>
<br>
If we want to select:/reject:, we must not only enumerate the absent characters, but rather all the characters in the complement.<br>
<br>
That's way two many, thus we prefer to do it with a LazyCharacterSet, anything else is unfeasible (we don't even know the upper limit of the set of characters...).<br>
<br>
Introduce an AbstractCharacterSet superclass of all the CharacterSet family in order to begin factoring some behavior.<br>
<br>
TODO: we should better rename<br>
CharacterSet -> ByteCharacterSet<br>
AbstractCharacterSet -> CharacterSet.<br>
<br>
We delay this quite technical operation, because we don't want to break existing instances, AND we want to redirect (Byte)CharacterSet references to (Abstract)CharacterSet, the Abstract one becoming a factory.<br>
<br>
=============== Diff against Collections-nice.770 ===============<br>
<br>
Item was added:<br>
+ Collection subclass: #AbstractCharacterSet<br>
+ instanceVariableNames: ''<br>
+ classVariableNames: ''<br>
+ poolDictionaries: ''<br>
+ category: 'Collections-Support'!<br>
<br>
Item was added:<br>
+ ----- Method: AbstractCharacterSet>><wbr>byteArrayMap (in category 'accessing') -----<br>
+ byteArrayMap<br>
+ ^self subclassReponsibility!<br>
<br>
Item was added:<br>
+ ----- Method: AbstractCharacterSet>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'enumerating') -----<br>
+ findFirstInByteString: aByteString startingAt: startIndex<br>
+ "Double dispatching: since we know this is a ByteString, we can use a superfast primitive using a ByteArray map with 0 slots for byte characters not included and 1 for byte characters included in the receiver."<br>
+ ^ByteString<br>
+ findFirstInString: aByteString<br>
+ inSet: self byteArrayMap<br>
+ startingAt: startIndex!<br>
<br>
Item was added:<br>
+ ----- Method: AbstractCharacterSet>><wbr>occurrencesOf: (in category 'enumerating') -----<br>
+ occurrencesOf: anObject<br>
+ "Answer how many of the receiver's elements are equal to anObject. Optimized version."<br>
+<br>
+ (self includes: anObject) ifTrue: [ ^1 ].<br>
+ ^0!<br>
<br>
Item was added:<br>
+ ----- Method: AbstractCharacterSet>><wbr>removeAll (in category 'removing') -----<br>
+ removeAll<br>
+ self becomeForward: CharacterSet new!<br>
<br>
Item was changed:<br>
+ AbstractCharacterSet subclass: #CharacterSet<br>
- Collection subclass: #CharacterSet<br>
instanceVariableNames: 'map tally'<br>
classVariableNames: 'CrLf NonSeparators Separators'<br>
poolDictionaries: ''<br>
category: 'Collections-Support'!<br>
<br>
!CharacterSet commentStamp: '<historical>' prior: 0!<br>
A set of characters. Lookups for inclusion are very fast.!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>= (in category 'comparing') -----<br>
- ----- Method: CharacterSet>>= (in category 'comparison') -----<br>
= anObject<br>
<br>
self species == anObject species ifFalse: [ ^false ].<br>
anObject size = tally ifFalse: [ ^false ].<br>
^self byteArrayMap = anObject byteArrayMap!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>add: (in category 'adding') -----<br>
- ----- Method: CharacterSet>>add: (in category 'collection ops') -----<br>
add: aCharacter<br>
"I automatically become a WideCharacterSet if you add a wide character to myself"<br>
<br>
| index |<br>
(index := aCharacter asInteger + 1) <= 256 ifFalse: [<br>
| wide |<br>
wide := WideCharacterSet new.<br>
wide addAll: self.<br>
wide add: aCharacter.<br>
self becomeForward: wide.<br>
^aCharacter ].<br>
(map at: index) = 1 ifFalse: [<br>
map at: index put: 1.<br>
tally := tally + 1 ].<br>
^aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>do: (in category 'enumerating') -----<br>
- ----- Method: CharacterSet>>do: (in category 'collection ops') -----<br>
do: aBlock<br>
"evaluate aBlock with each character in the set"<br>
<br>
| index |<br>
tally >= 128 ifTrue: [ "dense"<br>
index := 0.<br>
[ (index := index + 1) <= 256 ] whileTrue: [<br>
(map at: index) = 1 ifTrue: [<br>
aBlock value: (Character value: index - 1) ] ].<br>
^self ].<br>
"sparse"<br>
index := 0.<br>
[ (index := map indexOf: 1 startingAt: index + 1) = 0 ] whileFalse: [<br>
aBlock value: (Character value: index - 1) ].<br>
!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'enumerating') -----<br>
- ----- Method: CharacterSet>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'collection ops') -----<br>
findFirstInByteString: aByteString startingAt: startIndex<br>
"Double dispatching: since we know this is a ByteString, we can use a superfast primitive using a ByteArray map with 0 slots for byte characters not included and 1 for byte characters included in the receiver."<br>
^ByteString<br>
findFirstInString: aByteString<br>
inSet: self byteArrayMap<br>
startingAt: startIndex!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>hash (in category 'comparing') -----<br>
- ----- Method: CharacterSet>>hash (in category 'comparison') -----<br>
hash<br>
^self byteArrayMap hash!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>includes: (in category 'testing') -----<br>
- ----- Method: CharacterSet>>includes: (in category 'collection ops') -----<br>
includes: anObject<br>
<br>
| index |<br>
anObject isCharacter ifFalse: [ ^false ].<br>
(index := anObject asInteger + 1) > 256 ifTrue: [ ^false ].<br>
^(map at: index) > 0!<br>
<br>
Item was removed:<br>
- ----- Method: CharacterSet>>occurrencesOf: (in category 'enumerating') -----<br>
- occurrencesOf: anObject<br>
- "Answer how many of the receiver's elements are equal to anObject. Optimized version."<br>
-<br>
- (self includes: anObject) ifTrue: [ ^1 ].<br>
- ^0!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>remove: (in category 'removing') -----<br>
- ----- Method: CharacterSet>>remove: (in category 'collection ops') -----<br>
remove: aCharacter<br>
<br>
^self remove: aCharacter ifAbsent: aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>remove:ifAbsent: (in category 'removing') -----<br>
- ----- Method: CharacterSet>>remove:ifAbsent: (in category 'collection ops') -----<br>
remove: aCharacter ifAbsent: aBlock<br>
<br>
| index |<br>
(index := aCharacter asciiValue + 1) <= 256 ifFalse: [ ^aBlock value ].<br>
(map at: index) = 0 ifTrue: [ ^aBlock value ].<br>
map at: index put: 0.<br>
tally := tally - 1.<br>
^aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>size (in category 'accessing') -----<br>
- ----- Method: CharacterSet>>size (in category 'collection ops') -----<br>
size<br>
<br>
^tally!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>species (in category 'comparing') -----<br>
- ----- Method: CharacterSet>>species (in category 'comparison') -----<br>
species<br>
^CharacterSet!<br>
<br>
Item was changed:<br>
+ AbstractCharacterSet subclass: #CharacterSetComplement<br>
- Collection subclass: #CharacterSetComplement<br>
instanceVariableNames: 'absent byteArrayMapCache'<br>
classVariableNames: ''<br>
poolDictionaries: ''<br>
category: 'Collections-Support'!<br>
<br>
!CharacterSetComplement commentStamp: 'nice 8/31/2008 14:53' prior: 0!<br>
CharacterSetComplement is a space efficient implementation of (CharacterSet complement) taking care of WideCharacter (code > 255)<br>
<br>
However, it will maintain a byteArrayMap for character <= 255 in a cache keeping<br>
<br>
instance variables:<br>
absent <CharacterSet> contains character that are not in the set (i.e. my complement)<br>
byteArrayMapCache <ByteArray | nil> cache this information because it has to be used in tight loops where efficiency matters!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>>add: (in category 'adding') -----<br>
- ----- Method: CharacterSetComplement>>add: (in category 'collection ops') -----<br>
add: aCharacter<br>
"a character is present if not absent, so adding a character is removing it from the absent"<br>
<br>
(absent includes: aCharacter)<br>
ifTrue:<br>
[byteArrayMapCache := nil.<br>
absent remove: aCharacter].<br>
^ aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>>do: (in category 'enumerating') -----<br>
- ----- Method: CharacterSetComplement>>do: (in category 'collection ops') -----<br>
do: aBlock<br>
"evaluate aBlock with each character in the set.<br>
don't do it, there are too many..."<br>
<br>
self shouldNotImplement!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'enumerating') -----<br>
- ----- Method: CharacterSetComplement>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'collection ops') -----<br>
findFirstInByteString: aByteString startingAt: startIndex<br>
"Double dispatching: since we know this is a ByteString, we can use a superfast primitive using a ByteArray map with 0 slots for byte characters not included and 1 for byte characters included in the receiver."<br>
^ByteString<br>
findFirstInString: aByteString<br>
inSet: self byteArrayMap<br>
startingAt: startIndex!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>includes: (in category 'testing') -----<br>
- ----- Method: CharacterSetComplement>><wbr>includes: (in category 'collection ops') -----<br>
includes: anObject<br>
<br>
anObject isCharacter ifFalse: [ ^false ].<br>
(absent includes: anObject) ifTrue: [ ^false ].<br>
^true!<br>
<br>
Item was removed:<br>
- ----- Method: CharacterSetComplement>><wbr>occurrencesOf: (in category 'enumerating') -----<br>
- occurrencesOf: anObject<br>
- "Answer how many of the receiver's elements are equal to anObject. Optimized version."<br>
-<br>
- (self includes: anObject) ifTrue: [ ^1 ].<br>
- ^0!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>reject: (in category 'enumerating') -----<br>
- ----- Method: CharacterSetComplement>><wbr>reject: (in category 'collection ops') -----<br>
reject: aBlock<br>
+ ^LazyCharacterSet including: [:c | (absent includes: c) not and: [(aBlock value: c) not]]!<br>
- "Implementation note: rejecting present is selecting absent"<br>
-<br>
- ^(absent select: aBlock) complement!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>remove: (in category 'removing') -----<br>
- ----- Method: CharacterSetComplement>><wbr>remove: (in category 'collection ops') -----<br>
remove: aCharacter<br>
"This means aCharacter is now absent from myself.<br>
It must be added to my absent."<br>
<br>
byteArrayMapCache := nil.<br>
^absent add: aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>remove:ifAbsent: (in category 'removing') -----<br>
- ----- Method: CharacterSetComplement>><wbr>remove:ifAbsent: (in category 'collection ops') -----<br>
remove: aCharacter ifAbsent: aBlock<br>
(self includes: aCharacter) ifFalse: [^aBlock value].<br>
^self remove: aCharacter!<br>
<br>
Item was removed:<br>
- ----- Method: CharacterSetComplement>><wbr>removeAll (in category 'collection ops') -----<br>
- removeAll<br>
-<br>
- self becomeForward: CharacterSet new!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>select: (in category 'enumerating') -----<br>
- ----- Method: CharacterSetComplement>><wbr>select: (in category 'collection ops') -----<br>
select: aBlock<br>
+ ^LazyCharacterSet including: [:c | (absent includes: c) not and: [aBlock value: c]]!<br>
- "Implementation note: selecting present is rejecting absent"<br>
-<br>
- ^(absent reject: aBlock) complement!<br>
<br>
Item was removed:<br>
- ----- Method: CharacterSetComplement>>size (in category 'collection ops') -----<br>
- size<br>
- "Is this 2**32-absent size ?"<br>
-<br>
- ^self shouldNotImplement!<br>
<br>
Item was added:<br>
+ ----- Method: Interval>>copyFrom:to: (in category 'copying') -----<br>
+ copyFrom: startIndex to: stopIndex<br>
+ stopIndex < startIndex ifTrue: [^self copyEmpty].<br>
+ ^(self at: startIndex) to: (self at: stopIndex) by: step!<br>
<br></blockquote><div><br></div><div>Arghh, sorry, the Interval>>copyFrom:to: was a totally unrelated experiment</div><div><br></div><div>I think it is a good change, but it might break some tests and should have better gone in its own change set/commit.</div><div><br></div><div>By now I let it there, but if any one bark, I will revert.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Item was added:<br>
+ AbstractCharacterSet subclass: #LazyCharacterSet<br>
+ instanceVariableNames: 'block byteArrayMapCache'<br>
+ classVariableNames: ''<br>
+ poolDictionaries: ''<br>
+ category: 'Collections-Support'!<br>
+<br>
+ !LazyCharacterSet commentStamp: 'nice 11/30/2017 21:40' prior: 0!<br>
+ A LazyCharacterSet is a kind of CharacterSet which does not know in advance which Character it contains or not.<br>
+ If will lazily evaluate a block on demand if ever one ask whether it includes: a character.<br>
+ It is not feasible to enumerate a LazyCharacterSet, because there are way too many characters.<br>
+<br>
+ Instance Variables<br>
+ block: <BlockContext | Symbol><br>
+ byteArrayMapCache: <ByteArray | nil><br>
+<br>
+ block<br>
+ - a valuable, answering either true or false when sent the message value: - true means that this set includes the character passed as value: argument.<br>
+<br>
+ byteArrayMapCache<br>
+ - a cache holding 0 or 1 for the first 256 character codes - 0 meaning not included, 1 included. This is used in some priitives<br>
+ !<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet class>>including: (in category 'instance creation') -----<br>
+ including: aBlock<br>
+ "Create the set of Character for which aBlock evaluates to true"<br>
+ ^self class new block: aBlock!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>add: (in category 'adding') -----<br>
+ add: aCharacter<br>
+ self block: [:c | c = aCharacter or: [block value: c]].<br>
+ ^aCharacter!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>addAll: (in category 'adding') -----<br>
+ addAll: aCollection<br>
+ self block: [:c | (aCollection includes: c) or: [block value: c]].<br>
+ ^aCollection!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>block (in category 'accessing') -----<br>
+ block<br>
+ ^block!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>block: (in category 'accessing') -----<br>
+ block: aValuable<br>
+ "Set the block used to determine if I include a Character or not.<br>
+ aValuable is an object that shoud answer true or false when sent value:"<br>
+<br>
+ byteArrayMapCache := nil.<br>
+ ^block := aValuable!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>byteArrayMap (in category 'accessing') -----<br>
+ byteArrayMap<br>
+ "return a ByteArray mapping each ascii value to a 1 if that ascii value is in the set, and a 0 if it isn't. Intended for use by primitives only"<br>
+<br>
+ ^byteArrayMapCache ifNil: [byteArrayMapCache := (0 to: 255) collect: [:i | self includes: (Character value: i)]]!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>complement (in category 'converting') -----<br>
+ complement<br>
+ ^self class including: [:char | (block value: char) not]!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>do: (in category 'enumerating') -----<br>
+ do: aBlock<br>
+ "evaluate aBlock with each character in the set.<br>
+ don't do it, there are too many loop..."<br>
+<br>
+ self shouldNotImplement!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>includes: (in category 'testing') -----<br>
+ includes: aCharacter<br>
+ ^block value: aCharacter!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>reject: (in category 'enumerating') -----<br>
+ reject: aBlock<br>
+ ^self class including: [:char | (aBlock value: char) not and: [block value: char]]!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>remove: (in category 'removing') -----<br>
+ remove: aCharacter<br>
+ self block: [:c | (c = aCharacter) not and: [block value: c]].<br>
+ ^aCharacter!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>remove:<wbr>ifAbsent: (in category 'removing') -----<br>
+ remove: aCharacter ifAbsent: aBlock<br>
+ (self includes: aCharacter) ifFalse: [^aBlock value].<br>
+ ^self remove: aCharacter!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>removeAll: (in category 'removing') -----<br>
+ removeAll: aCollection<br>
+ self block: [:c | (aCollection include: c) not and: [block value: c]].<br>
+ ^aCollection!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>select: (in category 'enumerating') -----<br>
+ select: aBlock<br>
+ ^self class including: [:char | (block value: char) and: [aBlock value: char]]!<br>
<br>
Item was changed:<br>
+ AbstractCharacterSet subclass: #WideCharacterSet<br>
- Collection subclass: #WideCharacterSet<br>
instanceVariableNames: 'map byteArrayMap bitsetCapacity highBitsShift lowBitsMask'<br>
classVariableNames: ''<br>
poolDictionaries: ''<br>
category: 'Collections-Support'!<br>
<br>
!WideCharacterSet commentStamp: 'nice 12/10/2009 19:17' prior: 0!<br>
WideCharacterSet is used to store a Set of WideCharacter with fast access and inclusion test.<br>
<br>
Implementation should be efficient in memory if sets are sufficently sparse.<br>
<br>
Wide Characters are at most 32bits.<br>
We split them into 16 highBits and 16 lowBits.<br>
<br>
map is a dictionary key: 16 highBits value: map of 16 lowBits.<br>
<br>
Maps of lowBits are stored as arrays of bits in a ByteArray.<br>
If a bit is set to 1, this indicate that corresponding character is present.<br>
8192 bytes are necessary in each lowmap.<br>
Empty lowmap are removed from the map Dictionary.<br>
<br>
A byteArrayMap is maintained in parallel with map for fast handling of ByteString.<br>
(byteArrayMap at: i+1) = 0 means that character of asciiValue i is absent, = 1 means present.!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>add: (in category 'adding') -----<br>
- ----- Method: WideCharacterSet>>add: (in category 'collection ops') -----<br>
add: aCharacter<br>
<br>
| value highBits lowBits |<br>
(value := aCharacter asInteger) < 256 ifTrue: [<br>
byteArrayMap at: value + 1 put: 1 ].<br>
highBits := value bitShift: highBitsShift.<br>
lowBits := value bitAnd: lowBitsMask.<br>
(map at: highBits ifAbsentPut: [ Bitset new: bitsetCapacity ])<br>
setBitAt: lowBits.<br>
^aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>do: (in category 'enumerating') -----<br>
- ----- Method: WideCharacterSet>>do: (in category 'collection ops') -----<br>
do: aBlock<br>
<br>
map keysAndValuesDo: [ :index :bitset |<br>
| highBits |<br>
highBits := index * bitsetCapacity.<br>
bitset do: [ :lowBits |<br>
aBlock value: (Character value: highBits + lowBits) ] ]!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'enumerating') -----<br>
- ----- Method: WideCharacterSet>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'collection ops') -----<br>
findFirstInByteString: aByteString startingAt: startIndex<br>
"Double dispatching: since we know this is a ByteString, we can use a superfast primitive using a ByteArray map with 0 slots for byte characters not included and 1 for byte characters included in the receiver."<br>
<br>
^ByteString<br>
findFirstInString: aByteString<br>
inSet: byteArrayMap<br>
startingAt: startIndex!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>includes: (in category 'testing') -----<br>
- ----- Method: WideCharacterSet>>includes: (in category 'collection ops') -----<br>
includes: anObject<br>
<br>
| value |<br>
anObject isCharacter ifFalse: [ ^false ].<br>
(value := anObject asInteger) < 256 ifTrue: [<br>
^(byteArrayMap at: value + 1) ~= 0 ].<br>
^((map at: (value bitShift: highBitsShift) ifAbsent: nil) ifNil: [ ^false ])<br>
includes: (value bitAnd: lowBitsMask)!<br>
<br>
Item was removed:<br>
- ----- Method: WideCharacterSet>><wbr>occurrencesOf: (in category 'enumerating') -----<br>
- occurrencesOf: anObject<br>
- "Answer how many of the receiver's elements are equal to anObject. Optimized version."<br>
-<br>
- (self includes: anObject) ifTrue: [ ^1 ].<br>
- ^0!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>remove: (in category 'removing') -----<br>
- ----- Method: WideCharacterSet>>remove: (in category 'collection ops') -----<br>
remove: aCharacter<br>
"Don't signal an error when aCharacter is not present."<br>
<br>
^self remove: aCharacter ifAbsent: aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>remove:<wbr>ifAbsent: (in category 'removing') -----<br>
- ----- Method: WideCharacterSet>>remove:<wbr>ifAbsent: (in category 'collection ops') -----<br>
remove: aCharacter ifAbsent: aBlock<br>
<br>
| value highBits lowBits bitset |<br>
(value := aCharacter asInteger) < 256 ifTrue: [<br>
(byteArrayMap at: value + 1) = 0 ifTrue: [ ^aBlock value ].<br>
byteArrayMap at: value + 1 put: 0 ].<br>
highBits := value bitShift: highBitsShift.<br>
lowBits := value bitAnd: lowBitsMask.<br>
bitset := (map at: highBits ifAbsent: nil) ifNil: [ ^aBlock value ].<br>
((bitset clearBitAt: lowBits) and: [ bitset size = 0 ]) ifTrue: [<br>
map removeKey: highBits ].<br>
^aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>removeAll (in category 'removing') -----<br>
- ----- Method: WideCharacterSet>>removeAll (in category 'collection ops') -----<br>
removeAll<br>
<br>
map isEmpty ifTrue: [ ^self ].<br>
map removeAll.<br>
byteArrayMap atAllPut: 0!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>size (in category 'accessing') -----<br>
- ----- Method: WideCharacterSet>>size (in category 'collection ops') -----<br>
size<br>
<br>
^map detectSum: [ :each | each size ]!<br>
<br>
<br>
</blockquote></div><br></div></div>