Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours:
http://lists.squeakfoundation.org/pipermail/packages/2016-March/009508.html
Name: Files-mt.150
Ancestors: Files-cmm.149
Adds method to calculate size of directory including all its subdirectories. Complements #fileSize and #fileSizeString.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2016-March/009509.html
Name: Monticello-mt.628
Ancestors: Monticello-topa.627
For directory-based repositories, append local space requirements to the description string. Having this, the size of the package cache, for example, is revealed at a glance.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2016-March/009510.html
Name: Regex-Core-ul.49
Ancestors: Regex-Core-ul.48
- don't bother calling the match optimizer when it can't optimize anything. just throw it away instead
- removed some leftover methods from RxMatcher, RxmLookahead and RxmSubstring
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2016-March/009511.html
Name: Regex-Tests-Core-ul.5
Ancestors: Regex-Tests-Core-ul.4
Updated RxMatcherTest class >> #packageNamesUnderTest to return Regex-Core instead of VB-Regex. Perhaps it's not such a good idea to store the package name there, because no one noticed this slip for three years.
=============================================
Since DirectoryEntry already implements #fileSize, it wouldn't be too
crazy to also implement:
directorySize
"total size of the entry, if it's a directory"
^ 0
so that way wouldn't need to create a new sender of the type-check
(in DirectoryEntryDirectory>>directorySize)..
On Mon, Mar 28, 2016 at 6:07 AM, <commits(a)source.squeak.org> wrote:
> Marcel Taeumel uploaded a new version of Files to project The Trunk:
> http://source.squeak.org/trunk/Files-mt.150.mcz
>
> ==================== Summary ====================
>
> Name: Files-mt.150
> Author: mt
> Time: 28 March 2016, 1:07:09.732818 pm
> UUID: 4273cc14-a856-48f1-bfb4-eeb600da1b8b
> Ancestors: Files-cmm.149
>
> Adds method to calculate size of directory including all its subdirectories. Complements #fileSize and #fileSizeString.
>
> =============== Diff against Files-cmm.149 ===============
>
> Item was added:
> + ----- Method: DirectoryEntry>>directorySize (in category 'access') -----
> + directorySize
> + "Size of all files in that directory and all its sub-directories."
> +
> + ^ 0!
>
> Item was added:
> + ----- Method: DirectoryEntry>>directorySizeString (in category 'access') -----
> + directorySizeString
> +
> + ^ self directorySize asBytesDescription
> + !
>
> Item was added:
> + ----- Method: DirectoryEntryDirectory>>directorySize (in category 'access') -----
> + directorySize
> +
> + ^ self asFileDirectory entries
> + inject: 0
> + into: [:sum :entry | sum + (entry isDirectory ifTrue: [entry directorySize] ifFalse: [entry fileSize])]!
>
>
Levente Uzonyi uploaded a new version of Regex-Tests-Core to project The Trunk:
http://source.squeak.org/trunk/Regex-Tests-Core-ul.5.mcz
==================== Summary ====================
Name: Regex-Tests-Core-ul.5
Author: ul
Time: 28 March 2016, 5:46:00.424909 pm
UUID: d237739d-6e42-4b4b-bf3e-306bcbd2061f
Ancestors: Regex-Tests-Core-ul.4
Updated RxMatcherTest class >> #packageNamesUnderTest to return Regex-Core instead of VB-Regex. Perhaps it's not such a good idea to store the package name there, because no one noticed this slip for three years.
=============== Diff against Regex-Tests-Core-ul.4 ===============
Item was removed:
- ----- Method: RxMatcherTest class>>packageNamesUnderTest (in category 'accessing') -----
- packageNamesUnderTest
- ^ #('VB-Regex')!
Levente Uzonyi uploaded a new version of Regex-Core to project The Trunk:
http://source.squeak.org/trunk/Regex-Core-ul.49.mcz
==================== Summary ====================
Name: Regex-Core-ul.49
Author: ul
Time: 28 March 2016, 2:19:08.381924 am
UUID: 1cd17ad2-154c-4667-8211-ea6b76c1df92
Ancestors: Regex-Core-ul.48
- don't bother calling the match optimizer when it can't optimize anything. just throw it away instead
- removed some leftover methods from RxMatcher, RxmLookahead and RxmSubstring
=============== Diff against Regex-Core-ul.48 ===============
Item was changed:
----- Method: RxMatchOptimizer>>canStartMatch:in: (in category 'accessing') -----
canStartMatch: aCharacter in: aMatcher
"Answer whether a match could commence at the given lookahead
character, or in the current state of <aMatcher>. True answered
by this method does not mean a match will definitly occur, while false
answered by this method *does* guarantee a match will never occur."
aCharacter ifNil: [ ^true ].
- testBlock ifNil: [ ^true ].
^testBlock value: aCharacter value: aMatcher!
Item was added:
+ ----- Method: RxMatchOptimizer>>hasTestBlock (in category 'testing') -----
+ hasTestBlock
+
+ ^testBlock notNil!
Item was removed:
- ----- Method: RxMatcher>>atEnd (in category 'streaming') -----
- atEnd
-
- ^stream atEnd!
Item was changed:
----- Method: RxMatcher>>initialize:ignoreCase: (in category 'initialize-release') -----
initialize: syntaxTreeRoot ignoreCase: aBoolean
"Compile thyself for the regex with the specified syntax tree.
See comment and `building' protocol in this class and
#dispatchTo: methods in syntax tree components for details
on double-dispatch building.
The argument is supposedly a RxsRegex."
ignoreCase := aBoolean.
self buildFrom: syntaxTreeRoot.
self initializeMarkerPositions.
+ startOptimizer := RxMatchOptimizer new initialize: syntaxTreeRoot ignoreCase: aBoolean.
+ startOptimizer hasTestBlock ifFalse: [
+ startOptimizer := nil ]!
- startOptimizer := RxMatchOptimizer new initialize: syntaxTreeRoot ignoreCase: aBoolean!
Item was removed:
- ----- Method: RxMatcher>>lastResult (in category 'accessing') -----
- lastResult
-
- ^lastResult!
Item was removed:
- ----- Method: RxMatcher>>next (in category 'streaming') -----
- next
- ^ stream next!
Item was removed:
- ----- Method: RxmLookahead>>lookahead (in category 'accessing') -----
- lookahead
- ^ lookahead!
Item was removed:
- ----- Method: RxmSubstring>>character:ignoreCase: (in category 'initialize-release') -----
- character: aCharacter ignoreCase: aBoolean
- "Match exactly this character."
-
- sampleStream := (String with: aCharacter) readStream.
- ignoreCase := aBoolean!
Marcel Taeumel uploaded a new version of Monticello to project The Trunk:
http://source.squeak.org/trunk/Monticello-mt.628.mcz
==================== Summary ====================
Name: Monticello-mt.628
Author: mt
Time: 28 March 2016, 1:09:48.168818 pm
UUID: b1ae807a-b86d-4f3b-a3e2-02d7e835c6b5
Ancestors: Monticello-topa.627
For directory-based repositories, append local space requirements to the description string. Having this, the size of the package cache, for example, is revealed at a glance.
=============== Diff against Monticello-topa.627 ===============
Item was changed:
----- Method: MCDirectoryRepository>>description (in category 'accessing') -----
description
+ ^ '{1} ({2})' format: {directory pathName. directory directoryEntry directorySizeString}!
- ^ directory pathName!
Marcel Taeumel uploaded a new version of Files to project The Trunk:
http://source.squeak.org/trunk/Files-mt.150.mcz
==================== Summary ====================
Name: Files-mt.150
Author: mt
Time: 28 March 2016, 1:07:09.732818 pm
UUID: 4273cc14-a856-48f1-bfb4-eeb600da1b8b
Ancestors: Files-cmm.149
Adds method to calculate size of directory including all its subdirectories. Complements #fileSize and #fileSizeString.
=============== Diff against Files-cmm.149 ===============
Item was added:
+ ----- Method: DirectoryEntry>>directorySize (in category 'access') -----
+ directorySize
+ "Size of all files in that directory and all its sub-directories."
+
+ ^ 0!
Item was added:
+ ----- Method: DirectoryEntry>>directorySizeString (in category 'access') -----
+ directorySizeString
+
+ ^ self directorySize asBytesDescription
+ !
Item was added:
+ ----- Method: DirectoryEntryDirectory>>directorySize (in category 'access') -----
+ directorySize
+
+ ^ self asFileDirectory entries
+ inject: 0
+ into: [:sum :entry | sum + (entry isDirectory ifTrue: [entry directorySize] ifFalse: [entry fileSize])]!
Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours:
http://lists.squeakfoundation.org/pipermail/packages/2016-March/009505.html
Name: Regex-Tests-Core-ul.4
Ancestors: Regex-Tests-Core-ul.3
Added RxParserTest >> #testPredicates to cover the case sensitive/case insensitive predicates a bit better.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2016-March/009506.html
Name: Regex-Core-ul.48
Ancestors: Regex-Core-ul.47
- use double dispatch in #matchAgainst: of the subclasses of RxmLink. This allowed us to get rid of #currentState, #markerPositionAt:add: and #restoreState: from RxMatcher
- do not add both lowercase and uppercase characters to the set in RxsCharSet >> #enumerableSetIgnoringCase:, because that stops a few possible optimizations to work. The missing characters are added in #enumerablePartPredicateIgnoringCase: and RxMatchOptimizer's corresponding method. This change also let us have simpler #enumerateTo: methods
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2016-March/009507.html
Name: Network-ul.175
Ancestors: Network-ul.174
Socket changes:
- removed RegistryThreshold, because it was unused
- added DefaultReceiveBufferSize and DefaultSendBufferSize, both with the value of 8192. These can later be turned into preferences or something. All socket initialization methods use these variables. And this is the default size of a sent chunk in #sendData: too.
- don't waste seconds trying to look up the hostname for 0.0.0.0, just return nil in #peerName
- simplified #sendSomeData:startIndex:count:for:,
#waitForConnectionUntil:, #waitForDataFor:ifClosed:ifTimedOut:, #waitForDataIfClosed: and #waitForSendDoneFor:
- added #isOtherEndConnected and #isThisEndConnected to let waiting be possible in these cases as well, but they are not in use yet, because there are some issues to solve first
=============================================
Hi,
Just wanted to let you know that the Github builds are now all green (since now the DateAndTime issue in Squeak has been fixed), i.e.
Pharo-alpha, Pharo 5.0, Pharo 4.0,
Squeak-trunk, Squeak-4.6, Squeak-4.5
on both OS X and Linux.
See for yourself here: https://github.com/theseion/Fuel.
Note that the sources are still being hosted on Smalltalkhub. I’m triggering the builds through the TravisCI API when I run a build on the INRIA CI.
I’d like to thank Tobias Pape and Fabio Niephaus for their help in setting this up and for creating the SmalltalkCI infrastructure for TravisCI.
Cheers,
Max
Levente Uzonyi uploaded a new version of Network to project The Trunk:
http://source.squeak.org/trunk/Network-ul.175.mcz
==================== Summary ====================
Name: Network-ul.175
Author: ul
Time: 27 March 2016, 4:03:32.820897 am
UUID: 43c19bb9-e215-4b46-ad56-9a6466e93dc9
Ancestors: Network-ul.174
Socket changes:
- removed RegistryThreshold, because it was unused
- added DefaultReceiveBufferSize and DefaultSendBufferSize, both with the value of 8192. These can later be turned into preferences or something. All socket initialization methods use these variables. And this is the default size of a sent chunk in #sendData: too.
- don't waste seconds trying to look up the hostname for 0.0.0.0, just return nil in #peerName
- simplified #sendSomeData:startIndex:count:for:,
#waitForConnectionUntil:, #waitForDataFor:ifClosed:ifTimedOut:, #waitForDataIfClosed: and #waitForSendDoneFor:
- added #isOtherEndConnected and #isThisEndConnected to let waiting be possible in these cases as well, but they are not in use yet, because there are some issues to solve first
=============== Diff against Network-ul.174 ===============
Item was changed:
Object subclass: #Socket
instanceVariableNames: 'semaphore socketHandle readSemaphore writeSemaphore'
+ classVariableNames: 'Connected DeadServer DefaultReceiveBufferSize DefaultSendBufferSize InvalidSocket MaximumReadSemaphoreWaitTimeout OtherEndClosed Registry TCPSocketType ThisEndClosed UDPSocketType Unconnected WaitingForConnection'
- classVariableNames: 'Connected DeadServer InvalidSocket MaximumReadSemaphoreWaitTimeout OtherEndClosed Registry RegistryThreshold TCPSocketType ThisEndClosed UDPSocketType Unconnected WaitingForConnection'
poolDictionaries: ''
category: 'Network-Kernel'!
!Socket commentStamp: 'gk 12/13/2005 00:43' prior: 0!
A Socket represents a network connection point. Current sockets are designed to support the TCP/IP and UDP protocols. Sockets are the lowest level of networking object in Squeak and are not normally used directly. SocketStream is a higher level object wrapping a Socket in a stream like protocol.
ProtocolClient and subclasses are in turn wrappers around a SocketStream to provide support for specific network protocols such as POP, NNTP, HTTP, and FTP.!
Item was changed:
----- Method: Socket class>>initialize (in category 'class initialization') -----
initialize
"Socket initialize"
"Socket Types"
TCPSocketType := 0.
UDPSocketType := 1.
"Socket Status Values"
InvalidSocket := -1.
Unconnected := 0.
WaitingForConnection := 1.
Connected := 2.
OtherEndClosed := 3.
ThisEndClosed := 4.
+
+ "Default buffer sizes"
+ DefaultReceiveBufferSize := 8192.
+ DefaultSendBufferSize := 8192!
-
- RegistryThreshold := 100. "# of sockets"!
Item was removed:
- ----- Method: Socket class>>registryThreshold (in category 'registry') -----
- registryThreshold
- "Return the registry threshold above which socket creation may fail due to too many already open sockets. If the threshold is reached, a full GC will be issued if the creation of a socket fails."
- ^RegistryThreshold!
Item was removed:
- ----- Method: Socket class>>registryThreshold: (in category 'registry') -----
- registryThreshold: aNumber
- "Return the registry threshold above which socket creation may fail due to too many already open sockets. If the threshold is reached, a full GC will be issued if the creation of a socket fails."
- RegistryThreshold := aNumber!
Item was changed:
----- Method: Socket>>acceptFrom: (in category 'initialize-destroy') -----
acceptFrom: aSocket
"Initialize a new socket handle from an accept call"
self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex |
self
primAcceptFrom: aSocket socketHandle
+ receiveBufferSize: DefaultReceiveBufferSize
+ sendBufSize: DefaultSendBufferSize
- receiveBufferSize: 8000
- sendBufSize: 8000
semaIndex: semaIndex
readSemaIndex: readSemaIndex
writeSemaIndex: writeSemaIndex ]!
Item was changed:
----- Method: Socket>>initialize: (in category 'initialize-destroy') -----
initialize: socketType
"Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil."
self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex |
self primSocketCreateNetwork: 0
type: socketType
+ receiveBufferSize: DefaultReceiveBufferSize
+ sendBufSize: DefaultSendBufferSize
- receiveBufferSize: 8000
- sendBufSize: 8000
semaIndex: semaIndex
readSemaIndex: readSemaIndex
writeSemaIndex: writeSemaIndex ]!
Item was changed:
----- Method: Socket>>initialize:family: (in category 'initialize-destroy') -----
initialize: socketType family: family
"Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil."
NetNameResolver useOldNetwork ifTrue: [ ^self initialize: socketType ].
self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex |
self primSocketCreateNetwork: family
type: socketType
+ receiveBufferSize: DefaultReceiveBufferSize
+ sendBufSize: DefaultSendBufferSize
- receiveBufferSize: 8000
- sendBufSize: 8000
semaIndex: semaIndex
readSemaIndex: readSemaIndex
writeSemaIndex: writeSemaIndex ]!
Item was added:
+ ----- Method: Socket>>isOtherEndConnected (in category 'queries') -----
+ isOtherEndConnected
+ "Return true if this socket is connected, or this end has closed the connection but not the other end, so we can still send data."
+
+ | state |
+ socketHandle ifNil: [ ^false ].
+ (state := self primSocketConnectionStatus: socketHandle) == Connected ifTrue: [ ^true ].
+ ^state == ThisEndClosed
+ !
Item was added:
+ ----- Method: Socket>>isThisEndConnected (in category 'queries') -----
+ isThisEndConnected
+ "Return true if this socket is connected, other the other end has closed the connection but not this end, so we can still receive data."
+
+ | state |
+ socketHandle ifNil: [ ^false ].
+ (state := self primSocketConnectionStatus: socketHandle) == Connected ifTrue: [ ^true ].
+ ^state == OtherEndClosed
+ !
Item was changed:
----- Method: Socket>>peerName (in category 'accessing') -----
peerName
"Return the name of the host I'm connected to, or nil if its name isn't known to the domain name server or the request times out."
"Note: Slow. Calls the domain name server, taking up to 20 seconds to time out. Even when sucessful, delays of up to 13 seconds have been observed during periods of high network load."
+ | remoteAddress |
+ NetNameResolver useOldNetwork ifFalse: [ ^self remoteAddress hostName ].
+ (remoteAddress := self remoteAddress) = #[0 0 0 0] ifTrue: [
+ "Don't wait for the lookup"
+ ^nil ].
+ ^NetNameResolver
+ nameForAddress: remoteAddress
+ timeout: 20!
- ^NetNameResolver useOldNetwork
- ifFalse: [ self remoteAddress hostName ]
- ifTrue: [ NetNameResolver
- nameForAddress: self remoteAddress
- timeout: 20 ]!
Item was changed:
----- Method: Socket>>sendData: (in category 'sending') -----
sendData: aStringOrByteArray
"Send all of the data in the given array, even if it requires multiple calls to send it all. Return the number of bytes sent."
"An experimental version use on slow lines: Longer timeout and smaller writes to try to avoid spurious timeouts."
| bytesSent bytesToSend count |
bytesToSend := aStringOrByteArray size.
bytesSent := 0.
[bytesSent < bytesToSend] whileTrue: [
(self waitForSendDoneFor: 60)
ifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].
count := self primSocket: socketHandle
sendData: aStringOrByteArray
startIndex: bytesSent + 1
+ count: (bytesToSend - bytesSent min: DefaultSendBufferSize).
- count: (bytesToSend - bytesSent min: 5000).
bytesSent := bytesSent + count].
^ bytesSent
!
Item was changed:
----- Method: Socket>>sendSomeData:startIndex:count:for: (in category 'sending') -----
sendSomeData: aStringOrByteArray startIndex: startIndex count: count for: aTimeoutInSeconds
"Send up to count bytes of the given data starting at the given index. Answer the number of bytes actually sent."
"Note: This operation may have to be repeated multiple times to send a large amount of data."
+ (self waitForSendDoneFor: aTimeoutInSeconds) ifFalse: [
+ ConnectionTimedOut signal: 'send data timeout; data not sent'.
+ ^0 ].
+ ^self primSocket: socketHandle
+ sendData: aStringOrByteArray
+ startIndex: startIndex
+ count: count!
- | bytesSent |
- (self waitForSendDoneFor: aTimeoutInSeconds)
- ifTrue: [
- bytesSent := self primSocket: socketHandle
- sendData: aStringOrByteArray
- startIndex: startIndex
- count: count]
- ifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].
- ^ bytesSent
- !
Item was changed:
----- Method: Socket>>waitForConnectionUntil: (in category 'waiting') -----
waitForConnectionUntil: deadline
"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
+ | status waitTime |
+ [
+ (status := self primSocketConnectionStatus: socketHandle) == Connected ifTrue: [ ^true ].
+ status == WaitingForConnection ifFalse: [ ^false ].
+ (waitTime := deadline - Time millisecondClockValue) > 0 ifFalse: [ ^false ].
+ semaphore waitTimeoutMSecs: waitTime ] repeat!
- | status |
- status := self primSocketConnectionStatus: socketHandle.
- self isConnected ifTrue: [^status].
- [(status = WaitingForConnection) and: [Time millisecondClockValue < deadline]]
- whileTrue: [
- semaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).
- status := self primSocketConnectionStatus: socketHandle].
-
- ^ status = Connected
- !
Item was changed:
----- Method: Socket>>waitForDataFor:ifClosed:ifTimedOut: (in category 'waiting') -----
waitForDataFor: timeout ifClosed: closedBlock ifTimedOut: timedOutBlock
"Wait for the given nr of seconds for data to arrive."
| startTime msecsDelta |
+ socketHandle ifNil: [ ^closedBlock value ].
startTime := Time millisecondClockValue.
msecsDelta := (timeout * 1000) truncated.
+ [
+ (self primSocketReceiveDataAvailable: socketHandle) ifTrue: [ ^self ].
+ self isConnected ifFalse: [ ^closedBlock value ].
+ (Time millisecondsSince: startTime) < msecsDelta ifFalse: [ ^timedOutBlock value ].
- [(Time millisecondsSince: startTime) < msecsDelta] whileTrue: [
- (self primSocketReceiveDataAvailable: socketHandle)
- ifTrue: [^self].
- self isConnected
- ifFalse: [^closedBlock value].
"Providing a maximum for the time for waiting is a workaround for a VM bug which causes sockets waiting for data forever in some rare cases, because the semaphore doesn't get signaled. Remove the ""min: self class maximumReadSemaphoreWaitTimeout"" part when the bug is fixed."
readSemaphore waitTimeoutMSecs:
+ (msecsDelta - (Time millisecondsSince: startTime) min: self class maximumReadSemaphoreWaitTimeout) ] repeat!
- (msecsDelta - (Time millisecondsSince: startTime) min: self class maximumReadSemaphoreWaitTimeout).
- ].
-
- (self primSocketReceiveDataAvailable: socketHandle)
- ifFalse: [
- self isConnected
- ifTrue: [^timedOutBlock value]
- ifFalse: [^closedBlock value]].!
Item was changed:
----- Method: Socket>>waitForDataIfClosed: (in category 'waiting') -----
waitForDataIfClosed: closedBlock
"Wait indefinitely for data to arrive. This method will block until
data is available or the socket is closed."
+ socketHandle ifNil: [ ^closedBlock value ].
+ [
+ (self primSocketReceiveDataAvailable: socketHandle) ifTrue: [ ^self ].
+ self isConnected ifFalse: [ ^closedBlock value ].
+ "ul 8/13/2014 21:16
+ Providing a maximum for the time for waiting is a workaround for a VM bug which
+ causes sockets waiting for data forever in some rare cases, because the semaphore
+ doesn't get signaled. Replace the ""waitTimeoutMSecs: self class maximumReadSemaphoreWaitTimeout""
+ part with ""wait"" when the bug is fixed."
+ readSemaphore waitTimeoutMSecs: self class maximumReadSemaphoreWaitTimeout ] repeat!
- [(socketHandle ~~ nil
- and: [self primSocketReceiveDataAvailable: socketHandle]) ifTrue:
- [^self].
- self isConnected ifFalse:
- [^closedBlock value].
- "ul 8/13/2014 21:16
- Providing a maximum for the time for waiting is a workaround for a VM bug which
- causes sockets waiting for data forever in some rare cases, because the semaphore
- doesn't get signaled. Replace the ""waitTimeoutMSecs: self class maximumReadSemaphoreWaitTimeout""
- part with ""wait"" when the bug is fixed."
- readSemaphore waitTimeoutMSecs: self class maximumReadSemaphoreWaitTimeout] repeat!
Item was changed:
----- Method: Socket>>waitForSendDoneFor: (in category 'waiting') -----
waitForSendDoneFor: timeout
"Wait up until the given deadline for the current send operation to complete. Return true if it completes by the deadline, false if not."
+ | startTime msecsDelta msecsEllapsed |
- | startTime msecsDelta msecsEllapsed sendDone |
startTime := Time millisecondClockValue.
msecsDelta := (timeout * 1000) truncated.
+ [
+ (self primSocketSendDone: socketHandle) ifTrue: [ ^true ].
+ self isConnected ifFalse: [ ^false ].
+ (msecsEllapsed := Time millisecondsSince: startTime) < msecsDelta ifFalse: [ ^false ].
+ writeSemaphore waitTimeoutMSecs: msecsDelta - msecsEllapsed ] repeat!
- [(sendDone := self primSocketSendDone: socketHandle) not and: [ self isConnected
- "Connection end and final data can happen fast, so test in this order"
- and: [(msecsEllapsed := Time millisecondsSince: startTime) < msecsDelta]]] whileTrue: [
- writeSemaphore waitTimeoutMSecs: msecsDelta - msecsEllapsed].
-
- ^ sendDone!
Levente Uzonyi uploaded a new version of Regex-Core to project The Trunk:
http://source.squeak.org/trunk/Regex-Core-ul.48.mcz
==================== Summary ====================
Name: Regex-Core-ul.48
Author: ul
Time: 27 March 2016, 12:29:39.025303 am
UUID: 911704bb-a07f-4ac8-bed3-de8f349ac9e5
Ancestors: Regex-Core-ul.47
- use double dispatch in #matchAgainst: of the subclasses of RxmLink. This allowed us to get rid of #currentState, #markerPositionAt:add: and #restoreState: from RxMatcher
- do not add both lowercase and uppercase characters to the set in RxsCharSet >> #enumerableSetIgnoringCase:, because that stops a few possible optimizations to work. The missing characters are added in #enumerablePartPredicateIgnoringCase: and RxMatchOptimizer's corresponding method. This change also let us have simpler #enumerateTo: methods
=============== Diff against Regex-Core-ul.47 ===============
Item was removed:
- ----- Method: RxMatcher>>currentState (in category 'privileged') -----
- currentState
- "Answer an opaque object that can later be used to restore the matcher's state (for backtracking)."
-
- ^stream position!
Item was removed:
- ----- Method: RxMatcher>>markerPositionAt:add: (in category 'privileged') -----
- markerPositionAt: index add: position
- "Remember position of another instance of the given marker."
-
- index <= 2 ifTrue: [
- markerPositions at: index put: position.
- ^self ].
- (markerPositions at: index) addLast: position!
Item was added:
+ ----- Method: RxMatcher>>matchAgainstLookahead:nextLink: (in category 'matching') -----
+ matchAgainstLookahead: lookahead nextLink: anRmxLink
+
+ | position result |
+ position := stream position.
+ result := lookahead matchAgainst: self.
+ stream position: position.
+ result ifTrue: [ ^false ].
+ ^anRmxLink matchAgainst: self!
Item was added:
+ ----- Method: RxMatcher>>matchAgainstMarkerAt:nextLink: (in category 'matching') -----
+ matchAgainstMarkerAt: index nextLink: anRmxLink
+
+ | position |
+ position := stream position.
+ (anRmxLink matchAgainst: self) ifFalse: [ ^false ].
+ index <= 2
+ ifTrue: [ markerPositions at: index put: position ]
+ ifFalse: [ (markerPositions at: index) addLast: position ].
+ ^true!
Item was added:
+ ----- Method: RxMatcher>>matchAgainstPredicate:nextLink: (in category 'matching') -----
+ matchAgainstPredicate: aBlock nextLink: anRmxLink
+
+ | next position |
+ next := stream next ifNil: [ ^false ].
+ position := stream position - 1.
+ (aBlock value: next) ifTrue: [
+ (anRmxLink matchAgainst: self) ifTrue: [ ^true ] ].
+ stream position: position.
+ ^false!
Item was added:
+ ----- Method: RxMatcher>>matchCaseInsensitiveAgainstStream:nextLink: (in category 'matching') -----
+ matchCaseInsensitiveAgainstStream: aStream nextLink: anRmxLink
+
+ | next nextSample position |
+ position := stream position.
+ "The order of the stream reads is important. When aStream runs out of characters, we must not consume any character from stream, or else the next position will be skipped in stream."
+ [ (nextSample := aStream next) == nil or: [ (next := stream next) == nil ] ] whileFalse: [
+ (nextSample sameAs: next) ifFalse: [
+ stream position: position.
+ ^false ] ].
+ (nextSample == nil and: [ anRmxLink matchAgainst: self ]) ifTrue: [ ^true ].
+ stream position: position.
+ ^false!
Item was added:
+ ----- Method: RxMatcher>>matchCaseSensitiveAgainstStream:nextLink: (in category 'matching') -----
+ matchCaseSensitiveAgainstStream: aStream nextLink: anRmxLink
+
+ | next nextSample position |
+ position := stream position.
+ "The order of the stream reads is important. When aStream runs out of characters, we must not consume any character from stream, or else the next position will be skipped in stream."
+ [ (nextSample := aStream next) == nil or: [ (next := stream next) == nil ] ] whileFalse: [
+ nextSample == next ifFalse: [
+ stream position: position.
+ ^false ] ].
+ (nextSample == nil and: [ anRmxLink matchAgainst: self ]) ifTrue: [ ^true ].
+ stream position: position.
+ ^false!
Item was removed:
- ----- Method: RxMatcher>>restoreState: (in category 'privileged') -----
- restoreState: streamPosition
-
- stream position: streamPosition!
Item was changed:
----- Method: RxmLookahead>>matchAgainst: (in category 'matching') -----
matchAgainst: aMatcher
"Match if the predicate block evaluates to true when given the
current stream character as the argument."
+ ^aMatcher matchAgainstLookahead: lookahead nextLink: next!
- | original result |
- original := aMatcher currentState.
- result := lookahead matchAgainst: aMatcher.
- aMatcher restoreState: original.
- ^ result not
- and: [ next matchAgainst: aMatcher ]!
Item was changed:
----- Method: RxmMarker>>matchAgainst: (in category 'matching') -----
matchAgainst: aMatcher
"If the rest of the link chain matches successfully, report the
position of the stream *before* the match started to the matcher."
+ ^aMatcher matchAgainstMarkerAt: index nextLink: next!
- | startPosition |
- startPosition := aMatcher position.
- (next matchAgainst: aMatcher) ifFalse: [ ^false ].
- aMatcher markerPositionAt: index add: startPosition.
- ^true!
Item was changed:
----- Method: RxmPredicate>>matchAgainst: (in category 'matching') -----
matchAgainst: aMatcher
"Match if the predicate block evaluates to true when given the
current stream character as the argument."
+ ^aMatcher matchAgainstPredicate: predicate nextLink: next!
- | nextCharacter originalState |
- originalState := aMatcher currentState.
- nextCharacter := aMatcher next ifNil: [
- aMatcher restoreState: originalState.
- ^false ].
- (predicate value: nextCharacter) ifTrue: [
- (next matchAgainst: aMatcher) ifTrue: [ ^true ] ].
- aMatcher restoreState: originalState.
- ^false
- !
Item was changed:
----- Method: RxmSpecial>>matchAgainst: (in category 'matching') -----
matchAgainst: aMatcher
"Match without consuming any input, if the matcher is
in appropriate state."
+ (aMatcher perform: matchSelector) ifFalse: [ ^false ].
+ ^next matchAgainst: aMatcher!
- ^(aMatcher perform: matchSelector)
- and: [next matchAgainst: aMatcher]!
Item was changed:
----- Method: RxmSubstring>>matchAgainst: (in category 'matching') -----
matchAgainst: aMatcher
"Match if my sample stream is exactly the current prefix
of the matcher stream's contents."
- | nextSample nextFromMatcher originalState |
- originalState := aMatcher currentState.
sampleStream reset.
+ ignoreCase ifFalse: [ ^aMatcher matchCaseSensitiveAgainstStream: sampleStream nextLink: next ].
+ ^aMatcher matchCaseInsensitiveAgainstStream: sampleStream nextLink: next!
- ignoreCase
- ifFalse: [
- [ (nextSample := sampleStream next) == nil or: [ (nextFromMatcher := aMatcher next) == nil ] ] whileFalse: [
- nextSample == nextFromMatcher ifFalse: [
- aMatcher restoreState: originalState.
- ^false ] ] ]
- ifTrue: [
- [ (nextSample := sampleStream next) == nil or: [ (nextFromMatcher := aMatcher next) == nil ] ] whileFalse: [
- (nextSample sameAs: nextFromMatcher) ifFalse: [
- aMatcher restoreState: originalState.
- ^false ] ] ].
- (nextSample == nil and: [ next matchAgainst: aMatcher ]) ifTrue: [ ^true ].
- aMatcher restoreState: originalState.
- ^false!
Item was changed:
----- Method: RxsCharSet>>enumerablePartPredicateIgnoringCase: (in category 'privileged') -----
+ enumerablePartPredicateIgnoringCase: ignoreCase
- enumerablePartPredicateIgnoringCase: aBoolean
+ | set p |
+ set := (self enumerableSetIgnoringCase: ignoreCase) ifNil: [ ^nil ].
- | set |
- set := (self enumerableSetIgnoringCase: aBoolean) ifNil: [ ^nil ].
set size = 1 ifTrue: [
+ | char |
+ char := set anyOne.
+ ignoreCase ifTrue: [
+ | lowercaseChar |
+ lowercaseChar := char asLowercase.
+ char := char asUppercase.
+ char == lowercaseChar ifFalse: [
+ negated ifTrue: [
+ ^[ :character | (character == char or: [ character == lowercaseChar ]) not ] ].
+ ^[ :character | character == char or: [ character == lowercaseChar ] ] ] ].
+ negated ifTrue: [ ^[ :character | character ~~ char ] ].
+ ^[ :character | character == char ] ].
+ ignoreCase ifTrue: [
+ set copy do: [ :each |
+ | char |
+ (char := each asUppercase) == each
+ ifFalse: [ set add: char ]
+ ifTrue: [
+ (char := each asLowercase) == each ifFalse: [
+ set add: char ] ] ] ].
+ set size < 10 ifTrue: [ "10 is an empirical value"
+ p := set asArray.
+ negated ifTrue: [ ^[ :character | (p instVarsInclude: character) not ] ].
+ ^[ :character | p instVarsInclude: character ] ].
+ negated ifTrue: [ ^[ :character | (set includes: character) not ] ].
+ ^[ :character | set includes: character ]!
- | p |
- p := set anyOne.
- negated ifTrue: [ ^[ :character | character ~~ p ] ].
- ^[ :character | character == p ] ].
- negated ifTrue: [ ^[ :char | (set includes: char) not ] ].
- ^[ :char | set includes: char ]!
Item was changed:
----- Method: RxsCharSet>>enumerableSetIgnoringCase: (in category 'privileged') -----
enumerableSetIgnoringCase: aBoolean
+ "Answer a collection of characters that make up the portion of me that can be enumerated, or nil if there are no such characters. The case check is only used to determine the type of set to be used. The returned set won't contain characters of both cases, because this way the senders of this method can create more efficient checks."
- "Answer a collection of characters that make up the portion of me that can be enumerated, or nil if there are no such characters."
| highestCharacterCode set |
highestCharacterCode := elements inject: -1 into: [ :max :each |
max := (each maximumCharacterCodeIgnoringCase: aBoolean) max: max ].
highestCharacterCode = -1 ifTrue: [ ^nil ].
set := highestCharacterCode <= 255
ifTrue: [ CharacterSet new ]
ifFalse: [ WideCharacterSet new ].
+ elements do: [ :each | each enumerateTo: set ].
- elements do: [ :each |
- each enumerateTo: set ignoringCase: aBoolean ].
^set!
Item was added:
+ ----- Method: RxsCharacter>>enumerateTo: (in category 'accessing') -----
+ enumerateTo: aSet
+
+ ^aSet add: character!
Item was removed:
- ----- Method: RxsCharacter>>enumerateTo:ignoringCase: (in category 'accessing') -----
- enumerateTo: aSet ignoringCase: aBoolean
-
- aBoolean ifFalse: [ ^aSet add: character ].
- aSet
- add: character asUppercase;
- add: character asLowercase!
Item was added:
+ ----- Method: RxsPredicate>>enumerateTo: (in category 'accessing') -----
+ enumerateTo: aSet
+
+ ^self "Not enumerable"!
Item was removed:
- ----- Method: RxsPredicate>>enumerateTo:ignoringCase: (in category 'accessing') -----
- enumerateTo: aSet ignoringCase: aBoolean
-
- ^self "Not enumerable"!
Item was added:
+ ----- Method: RxsRange>>enumerateTo: (in category 'accessing') -----
+ enumerateTo: aSet
+ "Add all of the elements I represent to the collection."
+
+ first asInteger to: last asInteger do: [ :charCode |
+ aSet add: charCode asCharacter ].
+ ^self!
Item was removed:
- ----- Method: RxsRange>>enumerateTo:ignoringCase: (in category 'accessing') -----
- enumerateTo: aSet ignoringCase: aBoolean
- "Add all of the elements I represent to the collection."
-
- aBoolean ifFalse: [
- first asInteger to: last asInteger do: [ :charCode |
- aSet add: charCode asCharacter ].
- ^self ].
- first asInteger to: last asInteger do: [ :charCode |
- | character |
- character := charCode asCharacter.
- aSet
- add: character asLowercase;
- add: character asUppercase ]!