! ========================================================================
! Copyright (C) by VMware, Inc. 1991-2011.  All Rights Reserved
!
! $Id: doublebytesymbol.gs,v 1.12 2008-01-09 22:50:10 stever Exp $
!
! ========================================================================
removeallmethods DoubleByteSymbol
removeallclassmethods DoubleByteSymbol

category: 'For Documentation Installation only'
classmethod: DoubleByteSymbol
installDocumentation

| doc txt |
doc := GsClassDocumentation newForClass: self.

txt := (GsDocText new) details:
'A DoubleByteSymbol is an invariant String for which all comparisons are
 case-sensitive.  DoubleByteSymbols are used internally to represent variable
 names and selectors.  DoubleByteSymbols are always invariant and cannot be
 modified at any time after they are created.  Hence, the new and new: methods
 are disallowed.

 All Symbols and DoubleByteSymbols are canonical, which means that it is not
 possible to create two of them that have the same value.  If two canonical
 symbols compare as equal, then they are the same (identical) object.  Every
 instance of DoubleByteSymbol will contain at least one Character whose value is
 greater than 255.  A Symbol whose Character values are all less than 256 is
 always an instance of Symbol.

 GemStone does permit you to commit a canonical Symbol.
 GemStone also gathers
 all canonical symbols into one collection (a CanonicalStringDictionary) called
 AllSymbols.

 Since canonical symbols are universally visible, it is not recommended that 
 they be used for names that should remain private or secure.  Such objects
 should be instances of InvariantString instead.

 Since canonical symbols must be universally available, you cannot lock a
 Symbol or DoubleByteSymbol.

 Since each canonical symbol has a unique value, you cannot copy a Symbol or
 DoubleByteSymbol.  In addition, to guarantee canonicalization, you cannot send
 the become: or changeClassTo: messages to a Symbol or DoubleByteSymbol.

 DoubleByteSymbol is in the ClassHistory of Symbol, so instances of
 DoubleByteSymbol may be stored into instance variables that are constrained to
 hold instances of Symbol.  The inverse is not true, so you should always
 express symbol constraints as Symbol.

 EUCSymbols are not canonicalized and cannot be used interchangeably with
 canonical symbols.  They do not satisfy a constraint of Symbol, and are not
 accepted by the virtual machine as message selectors.' .
doc documentClassWith: txt.

self description: doc.
%

! ------------------- Class methods for DoubleByteSymbol
category: 'Instance Creation'
classmethod: DoubleByteSymbol
new

"Disallowed.  To create a new DoubleByteSymbol, use the class method 
 #withAll: instead."

self shouldNotImplement: #new
%

category: 'Instance Creation'
classmethod: DoubleByteSymbol
migrateNew

"Override default migrateNew behavior with #_basicNew."

^ self _basicNew
%

category: 'Instance Creation'
classmethod: DoubleByteSymbol

new: size

"Disallowed.  To create a new DoubleByteSymbol, use the class method #withAll: 
 instead."

self shouldNotImplement: #new:
%

category: 'Instance Creation'
classmethod: DoubleByteSymbol
withAll: aString

"Returns a canonical symbol that has the same Characters as aString.  Returns
 an existing canonical symbol if it is already in AllSymbols, or if it was
 created earlier in the current session.  Otherwise, creates and returns a new
 canonical symbol.

 The canonical symbol that this method returns is a Symbol if aString is a
 DoubleByteString with all Character values less than 255.  Otherwise, it
 returns a DoubleByteSymbol."

<primitive: 300> 
aString _validateClass: CharacterCollection.
^ self withAll: aString asDoubleByteString
%

category: 'Instance Creation'
classmethod: DoubleByteSymbol
_existingWithAll: aString

"Return an existing canonical symbol that has the same value as 'aString'.  
 If no such Symbol or DoubleByteSymbol already exists, returns nil."

<primitive: 310>
aString _validateClass: CharacterCollection.
^ self _existingWithAll: aString asString
%

category 'Instance Creation'
classmethod: DoubleByteSymbol
_newString

"Return a new instance of DoubleByteString."

^ DoubleByteString new
%

category 'Instance Creation'
classmethod: DoubleByteSymbol
_newString: aSize

"Return a new instance of DoubleByteString of the specified size."

^ DoubleByteString new: aSize
%

! ------------------- Instance methods for DoubleByteSymbol
category: 'Comparing'
method: DoubleByteSymbol
= anObject

"Returns true if anObject is equal to the receiver.  Since symbols and double 
 byte symbols are canonicalized, this method does the check based on the 
 identities of the receiver and the argument."

^ self == anObject. 
%

category: 'Converting'
method: DoubleByteSymbol
asDoubleByteString

"Returns a copy of the receiver as a DoubleByteString."

^ DoubleByteString withAll: self.
%

category: 'Converting'
method: DoubleByteSymbol
asDoubleByteSymbol

"Returns the receiver."

^ self.
%

category: 'Converting'
method: DoubleByteSymbol
asString

"Returns a copy of the receiver as a String."

^ String withAll: self.
%

category: 'Converting'
method: DoubleByteSymbol
asSymbol

"Returns the receiver.  All Symbols and DoubleByteSymbols are canonical."

^ self
%

category: 'Converting'
method: DoubleByteSymbol
asSymbolKind

"Returns the receiver.  All Symbols and DoubleByteSymbols are canonical."

^ self
%

category: 'Clustering'
method: DoubleByteSymbol
cluster

"Has no effect.  Clustering of DoubleByteSymbols is only performed by
 the clusterAllSymbols method in class System . "

^ true
%

category: 'Clustering'
method: DoubleByteSymbol
clusterInBucket: aClusterBucketOrId

"Has no effect.  Clustering of Symbols is only performed by
 the clusterAllSymbols method in class System . "

^ true
%


category: 'Copying'
method: DoubleByteSymbol
copy

"Returns self.  Copies of (canonical) double byte symbols are not allowed."

^ self
%

category: 'Concatenating'
method: DoubleByteSymbol
, aCharOrCharCollection

"Returns a new instance of DoubleByteString that contains the elements of
 the receiver followed by the elements of aCharOrCharCollection.
 A DoubleByteString is returned rather than a DoubleByteSymbol to avoid 
 the expense of unnecessary creation and canonicalization of Symbols."

| result |

result := DoubleByteString new.
result  addAll: self; addAll: aCharOrCharCollection.
^ result
%

category: 'Storing and Loading'
classmethod: DoubleByteSymbol
loadFrom: passiveObj

"Reads from passiveObj the passive form of an object.  Converts the object to
 its active form by loading the information into a new instance of the receiver.
 Returns the new instance."

| result inst theSize marker |

"since Symbols can't refer to other objects, the 'hasRead:' message
 may be sent after values have been filled in."

theSize := passiveObj readSize . 
inst := String new: theSize .
marker := passiveObj objectPositionMarker .
passiveObj next: theSize bytesTo: inst .
passiveObj next .
result := (inst _changeClassToDoubleByte: DoubleByteString) asSymbol .
passiveObj hasRead: result marker: marker .
^ result
%

category: 'Comparing'
method: DoubleByteSymbol
hash

"Returns a numeric hash key for the receiver."

^ self identityHash
%

category: 'Converting'
method: DoubleByteSymbol
-> anObject

"Returns a SymbolAssociation with the receiver as the key and the given object
 as the value."

^ SymbolAssociation newWithKey: self value: anObject
%

category: 'Converting'
method: DoubleByteSymbol
keywords

"Returns a collection of the keywords in the receiver if the receiver is
 a keyword message selector. Returns an empty Array otherwise."

| copy result |

copy := (String withAll: self) copyReplaceAll: ':' with: ' '.
result := copy asArrayOfSubstrings collect: [ :each | each , $:].
result do: [ :each | each isKeyword ifFalse: [ ^ #[] ]].

^ result.
%

category: 'Class Membership'
method: DoubleByteSymbol
species

"(R) Returns a class similar to, or the same as, the receiver's class which
 can be used for containing derived copies of the receiver."

^ DoubleByteString
%

! added based on code inspection , while working on 31257
category: 'Private'
method: DoubleByteSymbol
speciesForConversion

^ DoubleByteString .
%


category: 'Converting'
method: DoubleByteSymbol
asUppercase

"(R) Returns a new instance of DoubleByteString, with all lower-case
 characters in the receiver changed to upper-case."

| result |
result:= self species new: (self size).
1 to: (self size)
  do: [:i | result at: i put: (self at: i) asUppercase ].
^ result
%
category: 'Formatting'
method: DoubleByteSymbol
printOn: aStream

"Puts a displayable representation of the receiver on the given stream.
 That representation conforms to GemStone Smalltalk parsing rules."

| mySize |
(mySize := self size) == 0 ifTrue:[
  aStream nextPut: $# .
  aStream nextPut: $' .
  aStream nextPut: $' .
  ]
ifFalse:[
  mySize < 50 ifTrue:[
    self containsSeparator   "containsSeparator is expensive"
    ifFalse:[
      aStream nextPut: $# .
      aStream nextPutAll: self 
      ]
    ifTrue:[
      aStream nextPut: $# .
      super printOn: aStream 
      ]
    ]
  ifFalse:[
    "do it the efficient way for large Symbols"
    aStream nextPut: $# .
    super printOn: aStream 
    ]
  ]
%

category: 'New Indexing Comparison'
method: DoubleByteSymbol
_idxForCompareEqualTo: arg

""

^arg _idxForCompareEqualToDoubleByteSymbol: self
%

category: 'New Indexing Comparison - for Compare'
method: DoubleByteSymbol
_idxForCompareEqualToDoubleByteString: aString

""

^false
%
category: 'New Indexing Comparison - for Compare'
method: DoubleByteSymbol
_idxForCompareEqualToDoubleByteSymbol: aSymbol

""

^self _idxForSortEqualToCharacterCollection: aSymbol
%
category: 'New Indexing Comparison - for Compare'
method: DoubleByteSymbol
_idxForCompareEqualToString: aString

""

^false
%
category: 'New Indexing Comparison - for Compare'
method: DoubleByteSymbol
_idxForCompareEqualToSymbol: aSymbol

""

^self _idxForSortEqualToCharacterCollection: aSymbol
%
