PetitCommonMark/software/PetitParser/PPContextMemento.class.st

138 lines
3.7 KiB
Smalltalk

"
I am an implementation of the memento design pattern.
My goal is to remember the state of a PPContext to eventually be able to restore its state later.
I should be instantiated using PPContext>>#memorize method.
A PPContext can restore its state by providing the memento to PPContext>>#restore:.
"
Class {
#name : 'PPContextMemento',
#superclass : 'Object',
#instVars : [
'stream',
'position',
'properties'
],
#category : 'PetitParser-Core'
}
{ #category : 'comparing' }
PPContextMemento >> = anObject [
(self == anObject) ifTrue: [ ^ true ].
(anObject class = PPContextMemento) ifFalse: [ ^ false ].
(anObject stream == stream) ifFalse: [ ^ false ].
(anObject position == position) ifFalse: [ ^ false ].
(self propertiesSize == anObject propertiesSize) ifFalse: [ ^ false ].
self keysAndValuesDo: [ :key :value |
(anObject hasProperty: key) ifFalse: [ ^ false ].
((anObject propertyAt: key) = value) ifFalse: [ ^ false ].
].
^ true.
]
{ #category : 'accessing - properties' }
PPContextMemento >> hasProperty: aKey [
"Test if the property aKey is present."
^ properties notNil and: [ properties includesKey: aKey ]
]
{ #category : 'comparing' }
PPContextMemento >> hash [
^ (position hash bitXor: stream hash) bitXor: properties hash.
]
{ #category : 'accessing - properties' }
PPContextMemento >> keysAndValuesDo: aBlock [
properties ifNil: [ ^ self ].
properties keysAndValuesDo: [ :key :value | aBlock value: key value: value copy ]
]
{ #category : 'accessing' }
PPContextMemento >> position [
^ position
]
{ #category : 'accessing' }
PPContextMemento >> position: anInteger [
position := anInteger
]
{ #category : 'accessing - properties' }
PPContextMemento >> propertiesSize [
properties ifNil: [ ^ 0 ].
^ properties size.
]
{ #category : 'accessing - properties' }
PPContextMemento >> propertyAt: aKey [
"Answer the property value associated with aKey."
^ self propertyAt: aKey ifAbsent: [ self error: 'Property not found' ]
]
{ #category : 'accessing - properties' }
PPContextMemento >> propertyAt: aKey ifAbsent: aBlock [
"Answer the property value associated with aKey or, if aKey isn't found, answer the result of evaluating aBlock."
properties isNil
ifTrue: [ ^ aBlock value ]
ifFalse: [
(properties includesKey: aKey) ifTrue: [
^ (properties at: aKey) copy
].
^ aBlock value
]
]
{ #category : 'accessing - properties' }
PPContextMemento >> propertyAt: aKey ifAbsentPut: aBlock [
"Answer the property associated with aKey or, if aKey isn't found store the result of evaluating aBlock as new value."
^ self propertyAt: aKey ifAbsent: [ self propertyAt: aKey put: aBlock value ]
]
{ #category : 'accessing - properties' }
PPContextMemento >> propertyAt: aKey put: anObject [
"Set the property at aKey to be anObject. If aKey is not found, create a new entry for aKey and set is value to anObject. Answer anObject."
^ (properties ifNil: [ properties := Dictionary new: 1 ])
at: aKey put: (anObject copy)
]
{ #category : 'accessing - properties' }
PPContextMemento >> removeProperty: aKey [
"Remove the property with aKey. Answer the property or raise an error if aKey isn't found."
^ self removeProperty: aKey ifAbsent: [ self error: 'Property not found' ]
]
{ #category : 'accessing - properties' }
PPContextMemento >> removeProperty: aKey ifAbsent: aBlock [
"Remove the property with aKey. Answer the value or, if aKey isn't found, answer the result of evaluating aBlock."
| answer |
properties isNil ifTrue: [ ^ aBlock value ].
answer := properties removeKey: aKey ifAbsent: aBlock.
properties isEmpty ifTrue: [ properties := nil ].
^ answer
]
{ #category : 'accessing' }
PPContextMemento >> stream [
^ stream
]
{ #category : 'accessing' }
PPContextMemento >> stream: aStream [
stream := aStream
]