[squeak-dev] The Trunk: Collections-cmm.1020.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Jul 14 02:16:13 UTC 2022


Chris Muller uploaded a new version of Collections to project The Trunk:
http://source.squeak.org/trunk/Collections-cmm.1020.mcz

==================== Summary ====================

Name: Collections-cmm.1020
Author: cmm
Time: 13 July 2022, 9:16:12.177315 pm
UUID: 4a9e11ba-f983-4c7b-b701-ddabf2f10c73
Ancestors: Collections-cmm.1019

In addition to ascii letters and numbers, let #format: accept  _/-.,!@#$%^&*()[]=;: in the token names.  There is no performance hit thanks to the use of a new CharacterSet.

=============== Diff against Collections-cmm.1019 ===============

Item was changed:
  ArrayedCollection subclass: #String
  	instanceVariableNames: ''
+ 	classVariableNames: 'AsciiOrder CSMacroCharacters CaseInsensitiveOrder CaseSensitiveOrder CrLfExchangeTable FormatCharacterSet FormatTokenCharacters HtmlEntities LowercasingTable Tokenish UppercasingTable'
- 	classVariableNames: 'AsciiOrder CSMacroCharacters CaseInsensitiveOrder CaseSensitiveOrder CrLfExchangeTable FormatCharacterSet HtmlEntities LowercasingTable Tokenish UppercasingTable'
  	poolDictionaries: ''
  	category: 'Collections-Strings'!
  
  !String commentStamp: '<historical>' prior: 0!
  A String is an indexed collection of Characters. Class String provides the abstract super class for ByteString (that represents an array of 8-bit Characters) and WideString (that represents an array of  32-bit characters).  In the similar manner of LargeInteger and SmallInteger, those subclasses are chosen accordingly for a string; namely as long as the system can figure out so, the String is used to represent the given string.
  
  Strings support a vast array of useful methods, which can best be learned by browsing and trying out examples as you find them in the code.
  
  Here are a few useful methods to look at...
  	String match:
  	String contractTo:
  
  String also inherits many useful methods from its hierarchy, such as
  	SequenceableCollection ,
  	SequenceableCollection copyReplaceAll:with:
  !

Item was changed:
  ----- Method: String class>>initialize (in category 'initialization') -----
  initialize   "self initialize"
  
  	| order |
  	AsciiOrder := (0 to: 255) as: ByteArray.
  
  	CaseInsensitiveOrder := AsciiOrder copy.
  	($a to: $z) do:
  		[:c | CaseInsensitiveOrder at: c asciiValue + 1
  				put: (CaseInsensitiveOrder at: c asUppercase asciiValue +1)].
  
  	"Case-sensitive compare sorts space, digits, letters, all the rest..."
  	CaseSensitiveOrder := ByteArray new: 256 withAll: 255.
  	order := -1.
  	' 0123456789' do:  "0..10"
  		[:c | CaseSensitiveOrder at: c asciiValue + 1 put: (order := order+1)].
  	($a to: $z) do:     "11-64"
  		[:c | CaseSensitiveOrder at: c asUppercase asciiValue + 1 put: (order := order+1).
  		CaseSensitiveOrder at: c asciiValue + 1 put: (order := order+1)].
  	1 to: CaseSensitiveOrder size do:
  		[:i | (CaseSensitiveOrder at: i) = 255 ifTrue:
  			[CaseSensitiveOrder at: i put: (order := order+1)]].
  	order = 255 ifFalse: [self error: 'order problem'].
  
  	"a table for translating to lower case"
  	LowercasingTable := String withAll: (Character allByteCharacters collect: [:c | c asLowercase]).
  
  	"a table for translating to upper case"
  	UppercasingTable := String withAll: (Character allByteCharacters collect: [:c | c asUppercase]).
  
  	"a table for testing tokenish (for fast numArgs)"
  	Tokenish := String withAll: (Character allByteCharacters collect:
  									[:c | c tokenish ifTrue: [c] ifFalse: [$~]]).
   
  	"% and < for #expandMacros*"
  	CSMacroCharacters := CharacterSet newFrom: '%<'.
  
  	"{\ used by #format:"
  	FormatCharacterSet := CharacterSet newFrom: '{\'.
+ 	FormatTokenCharacters := CharacterSet newFrom: ($A to: $Z), ($a to: $z), ($0 to: $9), '_/-.,!!@#$%^&*()[]=;:'.
  	
  	"a table for exchanging cr with lf and vica versa"
  	CrLfExchangeTable := Character allByteCharacters collect: [ :each |
  		each
  			caseOf: {
  				[ Character cr ] -> [ Character lf ].
  				[ Character lf ] -> [ Character cr ] }
  			otherwise: [ each ] ]!

Item was changed:
  ----- Method: String>>format: (in category 'formatting') -----
  format: aCollection 
  	"Substitute tokens in the receiver with element values of aCollection.  The tokens are indicated in curly-braces and may be either numeric, e.g., {1}, {2}, etc. and map to a SequenceableCollection, OR, alphanumeric, e.g., {name}, {date}, etc., in which case aCollection should be a Dictionary.
  	The values can be static or, with the specification of a Block element, dynamic.
  	 
  	Simplest examples:
  		'foo {date} bar' format: ({'date'->Date today} as: Dictionary).
  
  	Dynamic calculation is allowed via Blocks.
  		'foo {NOW} bar' format: ({'NOW'-> [DateAndTime now]} as: Dictionary).
  
  	Backward-compatible with numeric-only #format:
  		'foo {1} bar' format: {Date today}.
  
  	Now with block support:
  		'foo {1} bar' format: {[Date today]}.
  	 
  	Complete example with escaped characters:  
  		'\{ \} \\ foo {1} bar {2}' format: {12. 'string'}.
  		'\{ \} \\ foo {FOO} bar {BAR}' format: ({'FOO'->12. 'BAR'->'string'} as: Dictionary)."
  	^ self class
  		new: self size * 11 // 10 "ready for +10% growth"
  		streamContents:
  			[ : output | | lastIndex nextIndex key |
  			lastIndex := 1.
  			key := 0.
  			[ "stream to output until first { or \"
  			(nextIndex := self indexOfAnyOf: FormatCharacterSet startingAt: lastIndex) = 0 ] whileFalse:
  				[ nextIndex = lastIndex ifFalse:
  					[ output next: nextIndex - lastIndex putAll: self startingAt: lastIndex ].
  				"special char hit, escape char?"
  				(self at: nextIndex) == $\
  					ifTrue: 
  						[ "transfer the escaped character. "
  						output nextPut: (self at: (nextIndex := nextIndex + 1)) ]
  					ifFalse:
  						[ | nextKeyChar |
  						"${ char, parse the key"
  						[ nextKeyChar := self at: (nextIndex := nextIndex + 1).
+ 						FormatTokenCharacters includes: nextKeyChar ] whileTrue:
- 						nextKeyChar isAscii and: [ nextKeyChar isAlphaNumeric ] ] whileTrue:
  							[ (key isInteger and: [ nextKeyChar between: $0 and: $9 ])
  								ifTrue: [ key := key * 10 + nextKeyChar digitValue ]
  								ifFalse:
  									[ key isInteger ifTrue:
  										[ key := WriteStream with:
  											(key isZero
  												ifTrue: [ String empty ]
  												ifFalse: [ key asString ]) ].
  									key nextPut: nextKeyChar ] ].
  						nextKeyChar == $} ifFalse: [ self error: '$} expected' translated ].
  						key isInteger
  							ifTrue:
  								[ output nextPutAll: (aCollection at: key) value asString.
  								key := 0 ]
  							ifFalse:
  								[ output nextPutAll: (aCollection at: key contents) value asString.
  								key reset ] ].
  				lastIndex := nextIndex + 1 ].
  			lastIndex <= self size ifTrue:
  				[ output next: self size - lastIndex + 1 putAll: self startingAt: lastIndex ] ]!



More information about the Squeak-dev mailing list