extensions.st
author Claus Gittinger <cg@exept.de>
Sat, 02 May 2020 21:40:13 +0200
changeset 5476 7355a4b11cb6
parent 5455 20dbad6d9935
permissions -rw-r--r--
#FEATURE by cg class: Socket class added: #newTCPclientToHost:port:domain:domainOrder:withTimeout: changed: #newTCPclientToHost:port:domain:withTimeout:

"{ Package: 'stx:libbasic2' }"!

!ArithmeticValue methodsFor:'converting'!

asQDouble
    "return a QDouble with same value"

    ^ QDouble fromFloat:self asFloat

    "
     123 asQDouble
     (Fraction basicNew setNumerator:246 denominator:2) asQDouble
     123 asLongFloat asQDouble
     123 asLargeFloat asQDouble
    "

    "Created: / 13-06-2017 / 16:48:24 / cg"
    "Modified (comment): / 25-07-2017 / 16:06:19 / cg"
! !

!ArithmeticValue methodsFor:'converting'!

asQuadFloat
    "return a quadFloat with same value"

    "WARNING: could loose precision here, if not redefined in concrete classes which
     have more than float precision (i.e. LargeIntegers and Fractions)"

    ^ self asFloat asQuadFloat "/ subclassResponsibility

    "Created: / 07-06-2019 / 02:28:54 / Claus Gittinger"
! !

!ArithmeticValue methodsFor:'double dispatching'!

differenceFromIEEEFloat:anIEEEFloat
    "anIEEEFloat does not know how to subtract the receiver -
     retry the operation by coercing to higher generality"

    ^ anIEEEFloat retry:#- coercing:self


! !

!ArithmeticValue methodsFor:'double dispatching'!

differenceFromQDouble:aQDouble
    "aQDouble does not know how to subtract the receiver -
     retry the operation by coercing to higher generality"

    ^ aQDouble retry:#- coercing:self

    "Created: / 13-06-2017 / 08:55:38 / cg"
! !

!ArithmeticValue methodsFor:'double dispatching'!

equalFromIEEEFloat:anIEEEFloat
    "anIEEEFloat does not know how to compare against by the receiver -
     retry the operation by coercing to higher generality"

    ^ anIEEEFloat retry:#= coercing:self
! !

!ArithmeticValue methodsFor:'double dispatching'!

equalFromQDouble:aQDouble
    "aQDouble does not know how to compare to the receiver -
     retry the operation by coercing to higher generality"

    ^ aQDouble retry:#= coercing:self

    "Created: / 13-06-2017 / 08:55:30 / cg"
! !

!ArithmeticValue methodsFor:'double dispatching'!

lessFromIEEEFloat:anIEEEFloat
    "anIEEEFloat does not know how to compare against by the receiver -
     retry the operation by coercing to higher generality"

    ^ anIEEEFloat retry:#< coercing:self
! !

!ArithmeticValue methodsFor:'double dispatching'!

lessFromQDouble:aQDouble
    "aQDouble does not know how to compare to the receiver -
     Return true if aQDouble < self.
     retry the operation by coercing to higher generality"

    ^ aQDouble retry:#< coercing:self

    "Created: / 13-06-2017 / 08:55:20 / cg"
! !

!ArithmeticValue methodsFor:'double dispatching'!

productFromIEEEFloat:anIEEEFloat
    "anIEEEFloat does not know how to multiply the receiver -
     retry the operation by coercing to higher generality"

    ^ anIEEEFloat retry:#* coercing:self
! !

!ArithmeticValue methodsFor:'double dispatching'!

productFromQDouble:aQDouble
    "aQDouble does not know how to multiply the receiver -
     retry the operation by coercing to higher generality"

    ^ aQDouble retry:#* coercing:self

    "Created: / 13-06-2017 / 08:55:07 / cg"
! !

!ArithmeticValue methodsFor:'double dispatching'!

quotientFromIEEEFloat:anIEEEFloat
    "anIEEEFloat does not know how to divide by the receiver -
     retry the operation by coercing to higher generality"

    ^ anIEEEFloat retry:#/ coercing:self
! !

!ArithmeticValue methodsFor:'double dispatching'!

quotientFromQDouble:aQDouble
    "aQDouble does not know how to divide by the receiver -
     retry the operation by coercing to higher generality"

    ^ aQDouble retry:#/ coercing:self

    "Created: / 13-06-2017 / 08:54:55 / cg"
! !

!ArithmeticValue methodsFor:'double dispatching'!

remainderFromQDouble:aQDouble
    "aQDouble does not know how to compute the remainder with the receiver -
     retry the operation by coercing to higher generality"

    ^ aQDouble retry:#rem: coercing:self

    "Created: / 13-06-2017 / 08:54:47 / cg"
! !

!ArithmeticValue methodsFor:'double dispatching'!

sumFromIEEEFloat:anIEEEFloat
    "anIEEEFloat does not know how to add the receiver -
     retry the operation by coercing to higher generality"

    ^ anIEEEFloat retry:#+ coercing:self
! !

!ArithmeticValue methodsFor:'double dispatching'!

sumFromQDouble:aQDouble
    "aQDouble does not know how to add the receiver -
     retry the operation by coercing to higher generality"

    ^ aQDouble retry:#+ coercing:self

    "Created: / 13-06-2017 / 08:54:27 / cg"
! !

!Block methodsFor:'Compatibility-Dolphin'!

deferredValue
    "Dolphin compatibility method - do not use in new code.
     Dolphin's alias for futureValue"

    ^ Future new block:self

    "Modified: / 04-10-2011 / 14:56:27 / cg"
! !

!Block methodsFor:'Compatibility-Dolphin'!

deferredValueAt:priority
    "Dolphin compatibility method - do not use in new code.
     Dolphin's alias for futureValue"

    ^ Future new
	priority:priority block:self

    "Created: / 04-10-2011 / 14:55:56 / cg"
! !

!Block methodsFor:'parallel evaluation'!

futureValue
    "Fork a synchronised evaluation of myself.
     Starts the evaluation in parallel now, but synchronizes
     any access to wait until the result is computed."

    ^ Future new block:self
! !

!Block methodsFor:'parallel evaluation'!

futureValue:aValue
    "Fork a synchronised evaluation of myself.
     Starts the evaluation in parallel now, but synchronizes
     any access to wait until the result is computed."

    ^ Future new block:self value:aValue
! !

!Block methodsFor:'parallel evaluation'!

futureValue:aValue value:anotherValue
    "Fork a synchronised evaluation of myself.
     Starts the evaluation in parallel now, but synchronizes
     any access to wait until the result is computed."

    ^ Future new
	block:self
	value:aValue
	value:anotherValue
! !

!Block methodsFor:'parallel evaluation'!

futureValue:aValue value:anotherValue value:bValue
    "Fork a synchronised evaluation of myself.
     Starts the evaluation in parallel now, but synchronizes
     any access to wait until the result is computed."

    ^ Future new
	block:self
	value:aValue
	value:anotherValue
	value:bValue
! !

!Block methodsFor:'parallel evaluation'!

futureValueWithArguments:anArray
    "Fork a synchronised evaluation of myself.
     Starts the evaluation in parallel now, but synchronizes
     any access to wait until the result is computed."

    ^ Future new
	block:self
	valueWithArguments:anArray

    "Modified (format): / 04-10-2011 / 14:55:40 / cg"
! !

!Block methodsFor:'parallel evaluation'!

lazyValue
    "Return a lazy value object, evaluating myself. 
     Only computes when the result is requested."

    ^ Lazy new block:self

    "Modified (comment): / 09-02-2019 / 15:59:29 / Claus Gittinger"
! !

!Block methodsFor:'parallel evaluation'!

lazyValue:aValue
    "Return a lazy value object, evaluating myself. 
     Only computes when the result is requested."

    ^ Lazy new block:self value:aValue

    "Modified (comment): / 09-02-2019 / 16:00:02 / Claus Gittinger"
! !

!Block methodsFor:'parallel evaluation'!

lazyValue:aValue value:anotherValue
    "Return a lazy value object, evaluating myself. 
     Only computes when the result is requested."

    ^ Lazy new
        block:self
        value:aValue
        value:anotherValue

    "Modified (comment): / 09-02-2019 / 16:00:05 / Claus Gittinger"
! !

!Block methodsFor:'parallel evaluation'!

lazyValue:aValue value:anotherValue value:bValue
    "Return a lazy value object, evaluating myself. 
     Only computes when the result is requested."

    ^ Lazy new
        block:self
        value:aValue
        value:anotherValue
        value:bValue

    "Modified (comment): / 09-02-2019 / 16:00:08 / Claus Gittinger"
! !

!Block methodsFor:'parallel evaluation'!

lazyValueWithArguments:anArray
    "Return a lazy value object, evaluating myself. 
     Only computes when the result is requested."

    ^ Lazy new block:self valueWithArguments:anArray

    "Modified (comment): / 09-02-2019 / 16:00:12 / Claus Gittinger"
! !

!Block methodsFor:'process creation'!

promise
    "create a promise on the receiver. The promise will evaluate the
     receiver and promise to return the value with the #value message.
     The evaluation will be performed as a separate process.
     Asking the promise for its value will either block the asking process
     (if the evaluation has not yet been finished) or return the value
     immediately."

    ^ Promise value:self

    "
     |p|

     p := [1000 factorial] promise.
     'do something else ...'.
     p value
    "
! !

!Block methodsFor:'process creation'!

promiseAt:prio
    "create a promise on the receiver. The promise will evaluate the
     receiver and promise to return the value with the #value message.
     The evaluation will be performed as a separate process running at prio.
     Asking the promise for its value will either block the asking process
     (if the evaluation has not yet been finished) or return the value
     immediately."

    ^ Promise value:self priority:prio
! !

!CharacterArray methodsFor:'matching - phonetic'!

asKoelnerPhoneticCode
    "return a koelner phonetic code.
     The koelnerPhonetic code is for the german language what the soundex code is for english;
     it returns simular strings for similar sounding words.
     There are some differences to soundex, though:
	its length is not limited to 4, but depends on the length of the original string;
	it does not start with the first character of the input.

     Caveat: this phonetic code is especially suited for german words.
	     Please have a look at the other phonetic comparison operators found
	     in PhoneticStringUtilities."

    ^ PhoneticStringUtilities koelnerPhoneticCodeOf:self

    "
     #(
	'Müller'
	'Miller'
	'Mueller'
	'Mühler'
	'Mühlherr'
	'Mülherr'
	'Myler'
	'Millar'
	'Myller'
	'Müllar'
	'Müler'
	'Muehler'
	'Mülller'
	'Müllerr'
	'Muehlherr'
	'Muellar'
	'Mueler'
	'Mülleer'
	'Mueller'
	'Nüller'
	'Nyller'
	'Niler'
	'Czerny'
	'Tscherny'
	'Czernie'
	'Tschernie'
	'Schernie'
	'Scherny'
	'Scherno'
	'Czerne'
	'Zerny'
	'Tzernie'
	'Breschnew'
     ) do:[:w |
	 Transcript show:w; show:'->'; showCR:(w asKoelnerPhoneticCode)
     ].
    "

    "
     'Breschnew' asKoelnerPhoneticCode -> '17863'
     'Breschnew' asKoelnerPhoneticCode -> '17863'
     'Breschneff' asKoelnerPhoneticCode -> '17863'
     'Braeschneff' asKoelnerPhoneticCode -> '17863'
     'Braessneff' asKoelnerPhoneticCode -> '17863'
     'Pressneff' asKoelnerPhoneticCode -> '17863'
     'Presznäph' asKoelnerPhoneticCode -> '17863'
    "
! !

!CharacterArray methodsFor:'matching - phonetic'!

asSoundexCode
    "return a soundex phonetic code or nil.
     Soundex returns similar codes for similar sounding words, making it a useful
     tool when searching for words where the correct spelling is unknown.
     (read Knuth or search the web if you don't know what a soundex code is).

     Caveat: 'similar sounding words' means: 'similar sounding in ENGLISH'
             Please have a look at the other phonetic comparison operators found
             in PhoneticStringUtilities."

    ^ PhoneticStringUtilities soundexCodeOf:self

    "
     'claus' asSoundexCode
     'clause' asSoundexCode
     'close' asSoundexCode
     'smalltalk' asSoundexCode
     'smaltalk' asSoundexCode
     'smaltak' asSoundexCode
     'smaltok' asSoundexCode
     'smoltok' asSoundexCode
     'aa' asSoundexCode
     'by' asSoundexCode
     'bab' asSoundexCode
     'bob' asSoundexCode
     'bop' asSoundexCode
    "
! !

!CharacterArray methodsFor:'printing & storing'!

printf:args
    "Format and print the receiver with <args> formatted in C style,
     as specified in the Unix C-language manual page for printf(3).
     Return the resulting string (i.e actually, this is more like an sprintf).
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf.
     For copyright information, see goodies/String-printf_scanf.chg"

    |aStream|

    aStream := CharacterWriteStream on:(self species uninitializedNew:self size).
    self printf:args on:aStream.
    ^ aStream contents

    "
     ('%05x %d %f %o' printf:{ 123. 234*5. 1.234. 8r377 } )    
     Transcript showCR:('%05x %d %f %o' printf:{ 123. 234*5. 1.234. 8r377 } )
    "

    "
     Transcript showCR: 'Some examples:'!!

     Transcript show:'''%#x %#X %03o%*.*s'' printf: #(16rABCD 16rEF 5 9 5 ''ghijklmn'') = .'.
     Transcript show: ('%#x %#X %03o%*.*s' printf: #(16rABCD 16rEF 5 9 5 'ghijklmn')).
     Transcript showCR: '.'

     Transcript show: '''%- 10.4s%.2e'' printf: (Array with: ''abcdefghijkl'' with: Float pi) = .'.
     Transcript show: ('%- 10.4s%.2e' printf: (Array with: 'abcdefghijkl' with: Float pi)).
     Transcript showCR: '.'

     Transcript show: '''%8.3f'' printf: (Array with: 200 sqrt negated) = .'.
     Transcript show: ('%8.3f' printf: (Array with: 200 sqrt negated)).
     Transcript showCR: '.'

     Transcript show: '''%c'' printf: #(16r41) = .'.
     Transcript show: ('%c' printf: #(16r41)).
     Transcript showCR: '.'

     Transcript show: '''%f%2s%s%s%s'' sscanf: ''237.0 this is a test'' = '.
     Transcript showCR: ('%f%2s%s%s%s'  sscanf: '237.0 this is a test') printString.

     Transcript show: '''%d%f%s'' sscanf: ''25 54.32e-01 monday'' = '.
     Transcript showCR: ('%d%f%s' sscanf: '25 54.32e-01 monday') printString.

     Transcript show: '''%f%*f %8[A-F0-9]%c%d 0x%x%f'' sscanf: ''12.45 1048.73 AE40Z527 0x75BCD15 34'' = '.
     Transcript showCR: ('%f%*f %8[A-F0-9]%c%d 0x%x%f' sscanf: '12.45 1048.73 AE40Z527 0x75BCD15 34') printString.
    "

    "Modified (comment): / 14-11-2017 / 22:58:01 / cg"
! !

!CharacterArray methodsFor:'printing & storing'!

printf:args on:outStream
    "Format and print the receiver on <outStream> with <args>
     formatted in C style, as specified in the Unix C-language manual page for printf(3).
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf.
     For copyright information, see goodies/String-printf_scanf.chg"

    PrintfScanf printf:self on:outStream arguments: args

    "
     '%e' printf:{ 1234.567 ] on:Transcript

     '%10s%3d\n' printf:{ 'hello' . 12 } on:Transcript
     '%10s%3d\n' printf:{ '1234567890' . 12 } on:Transcript

     like C's printf, a longer datum may be formatted wider than the formatspec says:
     
     '%10s%3d\n' printf:{ '12345678901234' . 12 } on:Transcript
     
     '%10s%3d\n' printf:{ 'hello' . 12 } on:Transcript
     '%10s%03d\n' printf:{ 'hello' . 12 } on:Transcript
    "

    "Modified (comment): / 14-11-2017 / 22:57:58 / cg"
! !

!CharacterArray methodsFor:'printing & storing'!

printfWith:arg1
    "Format and print the receiver with <arg1> formatted in C style,
     as specified in the Unix C-language manual page for printf(3).
     Return the resulting string (i.e actually, this is more like an sprintf).
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf"

    ^ self printf:(Array with:arg1)

    "
     ('%05x' printfWith:123)
     Transcript showCR:('%05x' printfWith:123)
    "

    "Modified (comment): / 14-11-2017 / 22:58:10 / cg"
! !

!CharacterArray methodsFor:'printing & storing'!

printfWith:arg1 with:arg2
    "Format and print the receiver with <argI> formatted in C style,
     as specified in the Unix C-language manual page for printf(3).
     Return the resulting string (i.e actually, this is more like an sprintf).
     For smalltalk specific formats, see documentation in PrintfScanf >> format_printf."

    ^ self printf:(Array with:arg1 with:arg2)

    "
     Transcript showCR:('%d %05x' printfWith:123 with:234)
     ('%d %05x' printfWith:123 with:234)
     ('%d%02d' printfWith:2004 with:9)  
    "

    "Modified (comment): / 14-11-2017 / 22:58:16 / cg"
! !

!CharacterArray methodsFor:'printing & storing'!

printfWith:arg1 with:arg2 with:arg3
    "Format and print the receiver with <argI> formatted in C style,
     as specified in the Unix C-language manual page for printf(3).
     Return the resulting string (i.e actually, this is more like an sprintf).
     For smalltalk specific formats, see documentation in PrintfScanf >> format_printf."

    ^ self printf:(Array with:arg1 with:arg2 with:arg3)

    "
     Transcript showCR:('%d %05x %08o' printfWith:123 with:234 with:345)
    "

    "Modified (comment): / 14-11-2017 / 22:58:20 / cg"
! !

!CharacterArray methodsFor:'printing & storing'!

printfWith:arg1 with:arg2 with:arg3 with:arg4
    "Format and print the receiver with <argI> formatted in C style,
     as specified in the Unix C-language manual page for printf(3).
     Return the resulting string (i.e actually, this is more like an sprintf).
     For smalltalk specific formats, see documentation in PrintfScanf >> format_printf."

    ^ self printf:(Array with:arg1 with:arg2 with:arg3 with:arg4)

    "
     Transcript showCR:('%d %05x %08o %b' printfWith:123 with:234 with:345 with:123)
    "

    "Modified (comment): / 14-11-2017 / 22:58:23 / cg"
! !

!CharacterArray methodsFor:'printing & storing'!

printfWith:arg1 with:arg2 with:arg3 with:arg4 with:arg5
    "Format and print the receiver with <argI> formatted in C style,
     as specified in the Unix C-language manual page for printf(3).
     Return the resulting string (i.e actually, this is more like an sprintf).
     For smalltalk specific formats, see documentation in PrintfScanf >> format_printf."

    ^ self printf:(Array with:arg1 with:arg2 with:arg3 with:arg4 with:arg5)

    "
     Transcript showCR:('%d %05x %08o %b' printfWith:123 with:234 with:345 with:123)
    "

    "Modified (comment): / 14-11-2017 / 22:58:28 / cg"
! !

!CharacterArray methodsFor:'printing & storing'!

printf_formatArgCount
    "Return the number of arguments required/produced if the receiver is interpreted
     as a printf/scanf format control string.
     For smalltalk specific formats, see documentation in PrintfScanf.
     For copyright information, see goodies/String-printf_scanf.chg"

    ^ PrintfScanf formatArgCountFor:self.

    "Modified: / 19-06-2017 / 16:54:10 / cg"
    "Modified (comment): / 14-11-2017 / 22:58:34 / cg"
! !

!CharacterArray methodsFor:'private'!

printf_printArgFrom:formatStream to:outStream withData:argStream
    <resource: #obsolete>
    "Interpret the required number of arguments from <argStream>
     according to the formatting information in <formatStream>.
     Place the interpretation on <outStream>.
     The interpretation is C printf(3) style, as
     specified in the Unix C-language manual page for printf(3).
     <formatStream> is assumed to be positioned just past
     $%, and a complete control string is assumed available.

     Return when the conversion control string is consumed.
     Leave <formatStream> pointing past the last character in the conversion control string.

     This code assumes that <formatStream> is formatted according to
     specification, and error checking is minimal.  Unexpected
     results will be obtained by illegal control strings, or when
     argument types do not match conversion codes, but it probably
     won't dump core, like C does in such cases!!

     For copyright information, see goodies/String-printf_scanf.chg"

    PrintfScanf printArgFrom:formatStream to:outStream arguments:argStream

    "Modified: / 19-06-2017 / 15:44:28 / cg"
! !

!CharacterArray methodsFor:'printing & storing'!

printf_printOn:outStream withData:args
    <resource: #obsolete>

    "Format and print the receiver on <outStream> with <args>
     formatted in C style, as specified in the Unix C-language manual page for printf(3).

     For copyright information, see goodies/String-printf_scanf.chg"

    self obsoleteMethodWarning:'use printf:on:'.
    self printf:args on:outStream
! !

!CharacterArray methodsFor:'converting'!

scanf:dataStreamOrString
    "Return a Collection of objects found in the Character Stream
     <dataStream> as interpreted according to the receiver.
     The receiver is assumed to be a conversion control string as
     specified in the Unix C-language manual page for scanf(3).
     For copyright information, see goodies/String-printf_scanf.chg"

    |dataStream|

    dataStream := dataStreamOrString readStream.
    ^ PrintfScanf scanf:self fromStream:dataStream
    
"/    |results format char|
"/
"/    results := OrderedCollection new.
"/    format := ReadStream on:self.
"/    [ format atEnd ] whileFalse:[
"/        char := format next.
"/        (char == Character space or:[ char == Character tab ]) ifTrue:[
"/            dataStream skipSeparators.
"/            format skipSeparators
"/        ].
"/        char == $% ifTrue:[
"/            PrintfScanf scanArgFrom:dataStream to:results format:format.
"/        ] ifFalse:[
"/            dataStream peekFor:char
"/        ]
"/    ].
"/    ^ results

    "
     '%d %x' scanf:(ReadStream on:'1234 ff00')
     '%d %s' scanf:(ReadStream on:'1234 ff00')
     '%d %b' scanf:(ReadStream on:'1234 1111')
     '%d %f' scanf:(ReadStream on:'1234 1111')
     '%d %f' scanf:(ReadStream on:'1234 1111.2345')
     '%d %q' scanf:(ReadStream on:'1234 1111.2345')
    "

    "Modified: / 14-07-2017 / 11:11:49 / cg"
! !

!CharacterArray methodsFor:'private'!

scanf_scanArgFrom:dataStream to:collection format:format
    <resource: #obsolete>
    "Add to <collection> an object who's representation is found
     in <dataStream> interpreted according to the conversion
     control string in the Stream <format>.
     <format> is assumed to be positioned just past a $%, and a complete control
     string is assumed available.

     Return when the conversion control string is consumed.  Leave
     <format> pointing past the last character in the conversion
     control string, leave <dataStream> pointing past any width
     specified in <format>, or at the first character that doesn't
     make sense for the <format>.

     For copyright information, see goodies/String-printf_scanf.chg"

    PrintfScanf scanArgFrom:dataStream to:collection format:format.

    "
     '%d %x' sscanf:'1234 ff00'
     '%d %x %b' sscanf:'1234 ff00 1001'
    "

    "Modified: / 14-07-2017 / 11:09:35 / cg"
! !

!CharacterArray methodsFor:'converting'!

sscanf:string
    "Return a Collection of objects found in <string> as
     interpreted according to the receiver.
     The receiver is assumed to be a conversion control string as
     specified in the Unix C-language manual page for scanf(3).
     For copyright information, see goodies/String-printf_scanf.chg"

    ^ self scanf:(ReadStream on:string)

    "
     '%d %x' sscanf:'1234 ff00'
     '%d %x %b' sscanf:'1234 ff00 1001'
    "
! !

!CharacterArray methodsFor:'Compatibility-Squeak'!

urlDecoded
    "decode %xx form.  This is the opposite of #urlEncoded"

    ^ HTMLUtilities urlDecoded:self

    "
     'abc%61def' unescapePercents
     'abc%61def' urlDecoded
     
      (HTMLUtilities urlEncoded:'_-.*Frankfurt(Main) Hbf') unescapePercents
      (HTMLUtilities urlEncoded:'_-.*Frankfurt(Main) Hbf') urlDecoded

      (HTMLUtilities urlEncoded:'-_.*%exept ex+pecco;') unescapePercents
      (HTMLUtilities urlEncoded:'-_.*%exept+ex+pecco;') urlDecoded
    "

    "Created: / 26-08-2018 / 12:41:49 / Claus Gittinger"
! !

!CharacterArray methodsFor:'Compatibility-Squeak'!

urlEncoded
    "encode into %xx form.  This is the opposite of #urlDecoded"

    ^ HTMLUtilities urlEncoded:self

    "
     'abcäöüdef' urlEncoded urlDecoded
     'abc%def' urlEncoded urlDecoded
     
      ('_-.*Frankfurt(Main) Hbf' urlEncoded) unescapePercents
      ('_-.*Frankfurt(Main) Hbf' urlEncoded) urlDecoded

      ('-_.*%exept ex+pecco;' urlEncoded) unescapePercents
      ('-_.*%exept+ex+pecco;' urlEncoded) urlDecoded
    "

    "Created: / 26-08-2018 / 13:03:03 / Claus Gittinger"
! !

!Collection methodsFor:'converting'!

asHalfFloatArray
    "return a new HalfFloatArray with the collection's elements
     (which must convert to 16bit half-floats)."

    ^ self asArrayOfType:HalfFloatArray
! !

!Collection methodsFor:'converting'!

asIdentitySkipList
	"Answer a IdentitySkipList whose elements are the elements of the 
	receiver. The sort order is the default less than or equal."

	^ self as: IdentitySkipList
! !

!Collection methodsFor:'converting'!

asList
    "return a new List with the receiver collection's elements"

    ^ self addAllTo:(List new:self size)

    "Created: 14.2.1997 / 16:25:23 / cg"
! !

!Collection methodsFor:'converting'!

asRunArray
    "return a new RunArray with the collection's elements"

    ^ RunArray from:self.

"/    |runs lastElement occurrences|
"/
"/    runs := RunArray new.
"/    occurrences := 0.
"/    self do:[:each |
"/        each == lastElement ifTrue:[
"/            occurrences := occurrences + 1
"/        ] ifFalse:[
"/            runs add:lastElement withOccurrences:occurrences.
"/            occurrences := 1.
"/            lastElement := each
"/        ].
"/    ].
"/    occurrences ~~ 0 ifTrue:[
"/        runs add:lastElement withOccurrences:occurrences
"/    ].
"/    ^ runs

    "
     #(1 2 3 3 3 4 4 4 4 5 6 7) asRunArray 
    "

    "Modified: / 7.4.1998 / 09:50:54 / cg"
! !

!Collection methodsFor:'converting'!

asSharedCollection
    "return a shared collection on the receiver.
     This implements synchronized (i.e. mutually excluded) access to me.
     Use this for safe access when multiple processes access me concurrently.
     Notice that this is a general (possibly suboptimal) mechanism, which should
     work with all collections. Look for specialized collections (SharedQueue), which are
     tuned for this kind of operation."

    ^ SharedCollection for:self.
! !

!Collection methodsFor:'converting'!

asSkipList
	"Answer a SkipList whose elements are the elements of the 
	receiver. The sort order is the default less than or equal."

	^ self as: SkipList
! !

!Collection methodsFor:'converting'!

asSkipList: aSortBlock 
        "Answer a SkipList whose elements are the elements of the 
        receiver. The sort order is defined by the argument, aSortBlock."

        | skipList |
        skipList := SkipList new: self size sortBlock: aSortBlock.
        skipList addAll: self.
        ^ skipList

    "Modified (comment): / 18-06-2017 / 22:40:10 / cg"
! !

!Float methodsFor:'private'!

absDecimalPrintOn:aStream digits:digits
    "Place a string representation of the receiver's abs value
     on <aStream> using <digits> significant digits, using decimal notation.
     This is a helper for printf."

    <resource: #obsolete>
    PrintfScanf absDecimalPrintFloat:self on:aStream digits:digits.

    "Modified: / 20-06-2017 / 11:49:15 / cg"
! !

!Float methodsFor:'private'!

absPrintOn:aStream digits:digits
    "Place a string representation of the receiver's abs value on <aStream> using
     <digits> significant digits.
     This is a helper for printf."

    <resource: #obsolete>
    PrintfScanf absPrintFloat:self on:aStream digits:digits

    "Modified: / 20-06-2017 / 11:49:11 / cg"
! !

!Float methodsFor:'private'!

absScientificPrintOn:aStream digits:digits
    "Place a string representation of the receiver's abs value on <aStream> using <digits> significant
     digits, using scientific notation.
     This is a helper for printf."

    <resource: #obsolete>
    PrintfScanf absScientificPrintFloat:self on:aStream digits:digits.

    "Modified: / 19-06-2017 / 14:59:56 / cg"
    "Modified (format): / 20-06-2017 / 11:49:07 / cg"
! !

!Float methodsFor:'coercing & converting'!

asIEEEFloat
    "return an IEEE soft float with same value as receiver"

    ^ IEEEFloat fromFloat:self

    "
     123 asFloat asIEEEFloat
     0 asShortFloat asIEEEFloat
     0.0 asIEEEFloat
    "

! !

!Float methodsFor:'coercing & converting'!

asOctaFloat
    "return an octaFloat with same value as receiver"

    ^ OctaFloat fromFloat:self

    "
     123 asFloat asOctaFloat
     0 asFloat asOctaFloat
     0.0 asOctaFloat
    "
! !

!Float methodsFor:'coercing & converting'!

asQDouble
    "return a QDouble with my value"

    ^ QDouble fromFloat:self

    "
     1.0 asQDouble
    "

    "Created: / 13-06-2017 / 16:48:57 / cg"
! !

!Float methodsFor:'coercing & converting'!

asQuadFloat
    "return a quadFloat with same value as receiver"

    ^ QuadFloat fromFloat:self

    "
     123 asFloat asQuadFloat
     0 asFloat asQuadFloat
     0.0 asQuadFloat
    "

    "Created: / 07-06-2019 / 02:28:26 / Claus Gittinger"
    "Modified (comment): / 10-06-2019 / 21:51:04 / Claus Gittinger"
! !

!Fraction methodsFor:'coercing & converting'!

asQuadFloat
    "return a QuadFloat with (approximately) my value.
     Since floats have a limited precision, you usually loose bits when doing this."

    |num den numShift denShift numBits rslt|

    (numerator class == SmallInteger and:[denominator class == SmallInteger]) ifTrue:[
        ^ (numerator asQuadFloat) / (denominator asQuadFloat)
    ].

    "Do it the hard way: reduce magnitude and undo reduction on the quotient"

    numBits := QuadFloat precision * 2.    "number of bits to preserve (conservative)"
    num := numerator abs.
    numShift := numBits - num highBit. "(num highBit - bits) negated"
    numShift < 0 ifTrue:[num := num bitShift:numShift] ifFalse:[ numShift := 0].

    den :=  denominator.
    denShift := numBits - den highBit. "(den highBit - bits) negated"
    denShift < 0 ifTrue:[den := den bitShift:denShift] ifFalse:[denShift := 0].

    rslt := (num asQuadFloat / den asQuadFloat) * (2 raisedToInteger:denShift-numShift).
    numerator negative ifTrue:[ ^ rslt negated ].
    ^ rslt.

    "
      (5/9) asQuadFloat
      (-5/9) asQuadFloat
      (Fraction basicNew setNumerator:500000000000 denominator:900000000000) asQuadFloat = (5/9) asQuadFloat
      (Fraction basicNew setNumerator:500000000001 denominator:900000000000) asQuadFloat = (5/9) asQuadFloat
      (500000000001/900000000000) asQuadFloat
      (-500000000001/900000000000) asQuadFloat
      (500000000001/900000000000) asQuadFloat = (5/9) asQuadFloat

      (500000000000/9) asQuadFloat
      (5/900000000000) asQuadFloat
      89012345678901234567 asFloat / 123456789123456789 asQuadFloat
      (89012345678901234567 / 123456789123456789) asQuadFloat
      (-89012345678901234567 / 123456789123456789) asQuadFloat

      (
       180338700661043257034670206806167960222709397862806840937993331366591676308781197477183367018067356365812757479444845320188679437752013593674158587947149815441890236037219685250845721864713487208757788709113534916165172927384095182655935222723385253851776639985379367854545495930551624041981995105743408203125
        /
       180331613628627651967947866455016278082980736719853750685591387625058011528928110602436691256100991596843001549483950600930062886280582766771424470965440873615557144641435276844465734361353086032476712374317224249252177316815544331763696909434844464464323192083930469387098582956241443753242492675781250
      ) asQuadFloat

      180338700661043257034670206806167960222709397862806840937993331366591676308781197477183367018067356365812757479444845320188679437752013593674158587947149815441890236037219685250845721864713487208757788709113534916165172927384095182655935222723385253851776639985379367854545495930551624041981995105743408203125
         asQuadFloat /
      180331613628627651967947866455016278082980736719853750685591387625058011528928110602436691256100991596843001549483950600930062886280582766771424470965440873615557144641435276844465734361353086032476712374317224249252177316815544331763696909434844464464323192083930469387098582956241443753242492675781250
         asQuadFloat
    "

    "Created: / 07-06-2019 / 02:32:19 / Claus Gittinger"
! !

!Integer methodsFor:'coercing & converting'!

asIEEEFloat
    "return an IEEEFloat with same value as the receiver"

    ^ IEEEFloat fromInteger:self

    "
     1234567890 asIEEEFloat
     1234567890 asIEEEFloat asInteger
     12345678901234567890 asIEEEFloat
     12345678901234567890 asIEEEFloat asInteger
    "


! !

!Integer methodsFor:'coercing & converting'!

asOctaFloat
    "return a OctaFloat with same value as myself.
     Since octaFloats have a limited precision, you may loose bits when
     doing this."

    ^ OctaFloat fromInteger:self

    "
     1234567890 asOctaFloat
     1234567890 asOctaFloat asInteger
     12345678901234567890 asOctaFloat
     12345678901234567890 asOctaFloat asInteger
    "

    "Created: / 07-06-2019 / 02:30:38 / Claus Gittinger"
! !

!Integer methodsFor:'coercing & converting'!

asQDouble
    "return a QDouble with same value as myself."

    ^ QDouble fromInteger:self

    "
     1234567890 asQDouble
     1234567890 asQDouble asInteger
     12345678901234567890 asQDouble
     12345678901234567890 asQDouble asInteger
    "

    "Created: / 12-06-2017 / 18:41:07 / cg"
    "Modified (comment): / 12-06-2017 / 20:55:24 / cg"
! !

!Integer methodsFor:'coercing & converting'!

asQuadFloat
    "return a QuadFloat with same value as myself.
     Since quadFloats have a limited precision, you may loose bits when
     doing this."

    ^ QuadFloat fromInteger:self

    "
     1234567890 asQuadFloat
     1234567890 asQuadFloat asInteger
     12345678901234567890 asQuadFloat
     12345678901234567890 asQuadFloat asInteger
    "

    "Created: / 07-06-2019 / 02:30:38 / Claus Gittinger"
! !

!Integer methodsFor:'Compatibility-Squeak'!

atRandom
    "return a random number between 1 and myself"

    ^ self atRandom:Random.

    "
     100 atRandom
     1000 atRandom
    "
! !

!LimitedPrecisionReal methodsFor:'coercing & converting'!

asOctaFloat
    ^ OctaFloat fromLimitedPrecisionReal:self

    "Created: / 07-06-2019 / 02:30:07 / Claus Gittinger"
! !

!LimitedPrecisionReal methodsFor:'coercing & converting'!

asQuadFloat
    ^ QuadFloat fromLimitedPrecisionReal:self

    "Created: / 07-06-2019 / 02:30:07 / Claus Gittinger"
! !

!LongFloat methodsFor:'coercing & converting'!

asIEEEFloat
    "return an IEEE soft float with same value as receiver"

    ^ IEEEFloat fromFloat:self

    "
     123 asFloat asIEEEFloat
     0 asShortFloat asIEEEFloat
     0 asLongFloat asIEEEFloat
     0.0 asIEEEFloat
    "
! !

!LongFloat methodsFor:'coercing & converting'!

asQDouble
    "return a QDouble with my value"

    ^ QDouble fromLongFloat:self

    "
     1.0 asLongFloat asQDouble
    "
! !

!LongFloat methodsFor:'coercing & converting'!

asQuadFloat
    "return a QuadFloat with same value as the receiver"

    ^ QuadFloat fromLongFloat:self

    "Created: / 07-06-2019 / 02:46:30 / Claus Gittinger"
! !

!MetaNumber methodsFor:'coercing & converting'!

asOctaFloat
    "return an OctaFloat with same value as the receiver.
     For anything but NaN, +Inf or -Inf, an error is raised here."

    ^ self asInstanceOf:OctaFloat fromSelector:#asOctaFloat

    "
     Infinity NaN asFloat
     Infinity NaN asOctaFloat
     
     Infinity positive asFloat
     Infinity positive asOctaFloat

     Infinity negative asFloat
     Infinity negative asOctaFloat
    "

    "Created: / 21-06-2017 / 20:42:09 / cg"
! !

!MetaNumber methodsFor:'coercing & converting'!

asQDouble
    "return a QDouble with same value as the receiver.
     For anything but NaN, +Inf or -Inf, an error is raised here."

    ^ self asInstanceOf:QDouble fromSelector:#asQDouble

    "
     Infinity NaN asFloat
     Infinity NaN asQDouble
     
     Infinity positive asFloat
     Infinity positive asQDouble

     Infinity negative asFloat
     Infinity negative asQDouble
    "

    "Created: / 21-06-2017 / 20:42:09 / cg"
! !

!MetaNumber methodsFor:'coercing & converting'!

asQuadFloat
    "return a QuadFloat with same value as the receiver.
     For anything but NaN, +Inf or -Inf, an error is raised here."

    ^ self asInstanceOf:QuadFloat fromSelector:#asQuadFloat

    "
     Infinity NaN asFloat
     Infinity NaN asQuadFloat
     
     Infinity positive asFloat
     Infinity positive asQuadFloat

     Infinity negative asFloat
     Infinity negative asQuadFloat
    "

    "Created: / 21-06-2017 / 20:42:09 / cg"
! !

!Object methodsFor:'dependents-interests'!

addInterest:anInterest
    "install an interest forwarder.
     Here, we use the nonWeakDependencies."

    self addNonWeakDependent:anInterest

    "Created: 14.10.1996 / 22:27:34 / stefan"
! !

!Object methodsFor:'converting'!

asDoubleLink
    "return a valueDoubleLink for the receiver.
     Used to make sure the receiver can be added to a double linked list"

    ^ ValueDoubleLink value:self
! !

!Object methodsFor:'dependents-interests'!

expressInterestIn:aspect for:anObject sendBack:aSelector
    "arrange for aSelector to be sent to anObject whenever the receiver
     changes aspect."

    "/ for now, use an interestConverter, which is somewhat less efficient.
    "/ In the future, a more intelligent DependencyCollection class is planned for

    self addInterest:(InterestConverter
			    destination:anObject
			    selector:aSelector
			    aspect:aspect)

    "
     |p b|

     b := [Transcript showCR:' -> the point changed'].

     p := Point new.
     Transcript showCR:'interest in #foo:'.
     p expressInterestIn:#foo for:b sendBack:#value.
     p x:1.
     Transcript showCR:'now changing #bar ... (expect no notification)'.
     p changed:#bar.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'now changing #foo ... (expect notification)'.
     p changed:#foo.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'no more interest in #foo:'.
     p retractInterestIn:#foo for:b.
     Transcript showCR:'now changing #foo ... (expect no notification)'.
     p changed:#foo.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'interest in #bar now:'.
     p expressInterestIn:#bar for:b sendBack:#value.
     Transcript showCR:'now changing #foo ... (expect no notification)'.
     p changed:#foo.
     Transcript showCR:'now changing #bar ... (expect notification)'.
     p changed:#bar.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'interest in #foo now:'.
     p expressInterestIn:#foo for:b sendBack:#value.
     Transcript showCR:'now changing #foo ... (expect notification)'.
     p changed:#foo.
     Transcript showCR:'now changing #bar ... (expect notification)'.
     p changed:#bar.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'no more interests:'.
     p retractInterestsFor:b.
     Transcript showCR:'now changing #foo ... (expect no notification)'.
     p changed:#foo.
     Transcript showCR:'now changing #bar...  (expect no notification)'.
     p changed:#bar.
     Transcript cr.

     p release.
    "

    "Created: 19.4.1996 / 10:26:22 / cg"
    "Modified: 19.4.1996 / 12:34:08 / cg"
    "Modified: 14.10.1996 / 22:28:20 / stefan"
! !

!Object methodsFor:'dependents-interests'!

interests
    "return a Collection of interests - empty if there is none.
     Here, we use the nonWeakDependents for interests."

    ^ self nonWeakDependents

    "Created: / 14.10.1996 / 22:20:51 / stefan"
    "Modified: / 30.1.1998 / 14:07:35 / cg"
! !

!Object methodsFor:'dependents-interests'!

interestsFor:someOne
    "return a collection of interests of someOne - empty if there is none."

    |coll deps|

    deps := self interests.
    deps size == 0 ifTrue:[^ #()].

    coll := IdentitySet new.

    deps do:[:dep |
	(dep isInterestConverter) ifTrue:[
	    dep destination == someOne ifTrue:[
		coll add:dep.
	    ]
	]
    ].
    ^ coll

    "Created: / 30.1.1998 / 14:02:26 / cg"
    "Modified: / 30.1.1998 / 14:08:24 / cg"
! !

!Object methodsFor:'dependents-interests'!

onChange:aspect evaluate:aBlock
    "arrange for aBlock to be evaluated whenever the receiver changes the given aspect."

    |na selector|

    na := aBlock argumentCount.
    na == 0 ifTrue:[
        selector := #value
    ] ifFalse:[
        selector := #( #'value:' #'value:value:' #'value:value:value:') at:na
    ].
    ^ self onChange:aspect send:selector to:aBlock

    "
     |p b|

     b := [Transcript showCR:' -> the point changed X'].

     p := Point new.
     Transcript showCR:'interest in #x, #y'.
     p onChange:#x evaluate:b.
     p onChange:#y evaluate:[Transcript showCR:' -> the point changed Y'].
     Transcript showCR:'now changing ...'.
     p changed.
     Transcript showCR:'now changing #bar ...'.
     p changed:#bar.
     Transcript showCR:'now changing #x ...'.
     p x:1.
     p changed:#x.
     Transcript showCR:'now changing #y ...'.
     p y:1.
     p changed:#y.

     Transcript showCR:'no more interests'.
     p retractInterests.
     p changed:#bar.
     p changed:#y.
     p changed:#x.
    "
! !

!Object methodsFor:'dependents-interests'!

onChange:aspect send:aSelector to:anObject
    "arrange for aSelector to be sent to anObject whenever the receiver
     changed the given aspect.
     Use retractInterestsFor: in case you are no longer interested"

    "/ for now, use an interestConverter, which is somewhat less efficient.
    "/ In the future, a more intelligent DependencyCollection class is planned for

    (self interests contains:[:anInterest |
            anInterest isInterestConverter
                and:[anInterest destination == anObject
                and:[anInterest selector == aSelector
                and:[anInterest aspect == aspect]]]
            ]
    ) ifFalse:[
        self addInterest:(InterestConverter
                              destination:anObject
                              selector:aSelector
                              aspect:aspect)
    ].


    "
     |p b|

     b := [Transcript showCR:'the point changed X'].

     p := Point new.
     p onChange:#x send:#value to:b.
     p onChange:#y send:#value to:[Transcript showCR:'the point changed Y'].
     Transcript showCR:'now changing x'.
     p x:1.
     p changed:#x.
     Transcript cr.

     Transcript showCR:'now changing y'.
     p y:2.
     p changed:#y.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'now changing (any)'.
     p changed.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'no more interest in x'.
     p retractInterestsFor:b.
     Transcript showCR:'now changing again'.
     p changed:#y.
     p changed:#x.
     p changed.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'interest in x again'.
     p onChange:#x send:#value to:b.
     Transcript showCR:'now changing again'.
     p changed:#y.
     p changed:#x.
     p changed.
     Transcript cr.

     Transcript showCR:'no more interest at all'.
     p retractInterests.
     p changed:#y.
     p changed:#x.
     p changed.
     Transcript cr.
    "

    "Created: / 19-04-1996 / 10:26:38 / cg"
    "Modified: / 19-04-1996 / 12:34:26 / cg"
    "Modified: / 14-10-1996 / 22:28:27 / stefan"
    "Modified: / 30-11-2018 / 18:01:47 / Stefan Vogel"
! !

!Object methodsFor:'dependents-interests'!

onChangeEvaluate:aBlock
    "arrange for aBlock to be evaluated whenever the receiver changes."

    |na selector|

    na := aBlock argumentCount.
    na == 0 ifTrue:[
        selector := #value
    ] ifFalse:[
        selector := #( #'value:' #'value:value:' #'value:value:value:') at:na
    ].
    ^ self onChangeSend:selector to:aBlock

    "
     |p b|

     b := [Transcript showCR:' -> the point changed'].

     p := Point new.
     Transcript showCR:'interest in #foo:'.
     p onChangeEvaluate:b.
     p x:1.
     Transcript showCR:'now changing #bar ... (expect no notification)'.
     p changed:#bar.

     p retractInterests.
     p changed:#bar.
    "
! !

!Object methodsFor:'dependents-interests'!

onChangeSend:aSelector to:anObject
    "arrange for aSelector to be sent to anObject whenever the receiver
     changes.
     Use retractInterestsFor: in case you are no longer interested"

    "/ for now, use an interestConverter, which is somewhat less efficient.
    "/ In the future, a more intelligent DependencyCollection class is planned for

    (self interests contains:[:anInterest |
            anInterest isInterestConverter
                and:[anInterest destination == anObject
                and:[anInterest selector == aSelector]]
            ]
    ) ifFalse:[
        self addInterest:(InterestConverter
                              destination:anObject
                              selector:aSelector)
    ].


    "
     |p b|

     b := [Transcript showCR:'the point changed'].

     p := Point new.
     p onChangeSend:#value to:b.
     p x:1.
     Transcript showCR:'now changing'.
     p changed.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'now changing'.
     p changed.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'no more interest'.
     p retractInterestsFor:b.
     Transcript showCR:'now changing again'.
     p changed.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'interest again'.
     p onChangeSend:#value to:b.
     Transcript showCR:'now changing again'.
     p changed.
     Transcript cr.
    "

    "Created: / 19-04-1996 / 10:26:38 / cg"
    "Modified: / 19-04-1996 / 12:34:26 / cg"
    "Modified: / 14-10-1996 / 22:28:27 / stefan"
    "Modified: / 30-11-2018 / 18:01:47 / Stefan Vogel"
! !

!Object methodsFor:'dependents-st/v event simulation'!

removeActionsForEvent:eventSymbol
    "remove ST/V-style event triggers."

    self retractInterestsIn:eventSymbol
! !

!Object methodsFor:'dependents-st/v event simulation'!

removeActionsWithReceiver:aReceiver
    "remove ST/V-style event triggers."

    self retractInterestsFor:aReceiver
! !

!Object methodsFor:'dependents-st/v event simulation'!

removeAllActionsWithReceiver:anObject
    "remove ST/V-style event triggers."

    self retractInterestsFor:anObject
! !

!Object methodsFor:'dependents-interests'!

removeDependentAndRetractInterestsFor:someOne
    "remove any dependency and interest of someOne in the receiver.
     Answer the receiver"

    self retractInterestsFor:someOne.
    self removeDependent:someOne.

    "Created: / 30-05-2019 / 11:11:19 / Claus Gittinger"
! !

!Object methodsFor:'dependents-interests'!

removeInterest:anInterest
    "remove an interest forwarder.
     Here, we use the nonWeakDependencies."

    self removeNonWeakDependent:anInterest

    "Created: 14.10.1996 / 22:21:59 / stefan"
! !

!Object methodsFor:'dependents-interests'!

retractInterestIn:aspect for:someOne
    "remove the interest of someOne in the receiver changing aspect
     (as installed with #expressInterestIn:for:sendBack:).
     Answer the retracted interests."

    "/ for now, remove the interestConverter.
    "/ In the future, a more intelligent DependencyCollection class is planned for

    ^ self retractInterestsForWhich:[:i | 
            (i aspect == aspect) and:[i destination == someOne]
        ]

    "
     |p b|

     b := [Transcript showCR:'the point changed'].

     p := Point new.
     Transcript showCR:'interest in #foo'.
     p expressInterestIn:#foo for:b sendBack:#value.
     p x:1.
     Transcript showCR:'now changing #bar'.
     p changed:#bar.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'now changing #foo'.
     p changed:#foo.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'no more interest in #foo'.
     p retractInterestIn:#foo for:b.
     Transcript showCR:'now changing #foo'.
     p changed:#foo.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'interest in #bar now'.
     p expressInterestIn:#bar for:b sendBack:#value.
     Transcript showCR:'now changing #foo'.
     p changed:#foo.
     Transcript showCR:'now changing #bar'.
     p changed:#bar.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'interest in #foo now'.
     p expressInterestIn:#foo for:b sendBack:#value.
     Transcript showCR:'now changing #foo'.
     p changed:#foo.
     Transcript showCR:'now changing #bar'.
     p changed:#bar.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'no more interests'.
     p retractInterestsFor:b.
     Transcript showCR:'now changing #foo'.
     p changed:#foo.
     Transcript showCR:'now changing #bar'.
     p changed:#bar.
     Transcript cr.
    "

    "Created: / 19.4.1996 / 10:27:11 / cg"
    "Modified: / 14.10.1996 / 22:21:19 / stefan"
    "Modified: / 30.1.1998 / 14:05:34 / cg"
! !

!Object methodsFor:'dependents-interests'!

retractInterests
    "remove all interests in the receiver changing aspect
     (as installed with #expressInterestIn:for:sendBack:).
     Answer the retraced interests."

    "/ for now, remove the interestConverter.
    "/ In the future, a more intelligent DependencyCollection class is planned for

    ^ self retractInterestsForWhich:[:i | true ]
! !

!Object methodsFor:'dependents-interests'!

retractInterestsFor:someOne
    "remove the interest of someOne in the receiver
     (as installed with #onChangeSend:to:).
     Answer the retracted interests."

    "/ for now, remove the interestConverter.
    "/ In the future, a more intelligent DependencyCollection class is planned for

    ^ self retractInterestsForWhich:[:i | i destination == someOne ]

    "
     |p b|

     b := [Transcript showCR:'the point changed'].

     p := Point new.
     p onChangeSend:#value to:b.
     p x:1.
     Transcript showCR:'now changing'.
     p changed.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'now changing'.
     p changed.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'no more interest'.
     p retractInterestsFor:b.
     Transcript showCR:'now changing again'.
     p changed.
     Transcript cr.

     Delay waitForSeconds:1.
     Transcript showCR:'interest again'.
     p onChangeSend:#value to:b.
     Transcript showCR:'now changing again'.
     p changed.
     Transcript cr.
    "

    "Created: / 19.4.1996 / 10:23:46 / cg"
    "Modified: / 14.10.1996 / 22:21:25 / stefan"
    "Modified: / 30.1.1998 / 14:04:52 / cg"
! !

!Object methodsFor:'dependents-interests'!

retractInterestsForWhich:aBlock
    "remove all interests in the receiver changing aspect
     (as installed with #expressInterestIn:for:sendBack:).
     Answer the retracted interests."

    "/ for now, remove the interestConverter.
    "/ In the future, a more intelligent DependencyCollection class is planned for

    |deps toRemove|

    deps := self interests.
    deps size ~~ 0 ifTrue:[
        "/ cannot removeDependent within the loop - the interests collection rehashes
        toRemove := IdentitySet new.
        deps do:[:dep |
            dep isInterestConverter ifTrue:[
                (aBlock value:dep) ifTrue:[toRemove add:dep].
            ]
        ].
        toRemove do:[:dep |
            self removeInterest:dep.
        ].
        ^ toRemove.
    ].
    ^ #()
! !

!Object methodsFor:'dependents-interests'!

retractInterestsIn:aspect
    "remove all interests in the receiver changing aspect
     (as installed with #expressInterestIn:for:sendBack:).
     Answer the retracted interests."

    "/ for now, remove the interestConverter.
    "/ In the future, a more intelligent DependencyCollection class is planned for

    ^ self retractInterestsForWhich:[:i | i aspect == aspect ]
! !

!Object methodsFor:'Compatibility-Dolphin'!

trigger:anAspect
    self changed:anAspect
! !

!Object methodsFor:'Compatibility-Dolphin'!

trigger:anAspect with:anArgument
    self changed:anAspect with:anArgument
! !

!Object methodsFor:'dependents-st/v event simulation'!

triggerEvent:aSymbol
    self changed:aSymbol
! !

!Object methodsFor:'dependents-st/v event simulation'!

triggerEvent:eventSymbol with:aParameter
    "perform ST/V-style event triggering."

    self changed:eventSymbol with:(Array with:aParameter).
! !

!Object methodsFor:'dependents-st/v event simulation'!

triggerEvent:eventSymbol withArguments:parameters
    "perform ST/V-style event triggering."

    self changed:eventSymbol with:parameters.
! !

!Object methodsFor:'dependents-st/v event simulation'!

when:eventSymbol send:selector to:anObject
    "install an ST/V-style interest forwarder.
     Here, we use the nonWeakDependencies."

    self addInterest:(InterestConverterWithParameters
                            destination:anObject
                            selector:selector
                            aspect:eventSymbol).

    "
     |p b|

     b := [Transcript showCR:'the point changed'].

     p := Point new.
     p when:#foo:bar: send:#value:value: to:[:a :b | Transcript show:'foo: '; show:a; show:' bar: '; showCR:b].
     Transcript showCR:'now changing'.
     p triggerEvent:#foo:bar: withArguments:#('fooArg' 'barArg').
     p removeActionsForEvent:#foo:bar:.
    "
! !

!Object methodsFor:'dependents-st/v event simulation'!

when:eventSymbol send:selector to:anObject with:aParameter
    "install an ST/V-style interest forwarder.
     Here, we use the nonWeakDependencies."

    self addInterest:((InterestConverterWithParameters
                            destination:anObject
                            selector:selector
                            aspect:eventSymbol) 
                        defaultParameters:(Array with:aParameter)).

    "
     |p b|

     b := [Transcript showCR:'the point changed'].

     p := Point new.
     p 
        when:#foo: 
        send:#value: 
        to:[:a | Transcript show:'foo: '; showCR:a]
        with:123.
     Transcript showCR:'now changing'.
     p triggerEvent:#foo:.
     p triggerEvent:#foo: with:987.
     p removeActionsForEvent:#foo:.
    "
! !

!Object methodsFor:'Compatibility-Dolphin'!

when:anAspect sendTo:anObject
    self expressInterestIn:anAspect for:anObject sendBack:anAspect
! !

!ShortFloat methodsFor:'coercing & converting'!

asIEEEFloat
    "return an IEEE soft float with same value as receiver"

    ^ IEEEFloat fromFloat:self

    "
     123 asFloat asIEEEFloat
     0 asShortFloat asIEEEFloat
     0 asLongFloat asIEEEFloat
     0.0 asIEEEFloat
    "
! !

!ShortFloat methodsFor:'coercing & converting'!

asQuadFloat
    "return a QuadFloat with same value as the receiver"

    ^ QuadFloat fromShortFloat:self

    "Created: / 07-06-2019 / 02:29:14 / Claus Gittinger"
! !

!Stream methodsFor:'stacked computing streams'!

collecting:aBlock
    "return a stacked computing stream, which reads elements from the receiver,
     applies aBlock to each read element, and provides the results as elements to its reader."

    ^ CollectingReadStream on:self collecting:aBlock

    "
     |s s2|

     s := 'hello world' readStream.
     s2 := s collecting:[:ch | ch asUppercase].
     s2 upToEnd.   
    "
! !

!Stream methodsFor:'writing'!

printf:formatString
    "C-style printing into a stream.
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf"

    formatString printf:#() on:self.

    "
     Transcript printf:'Hello World\n'
     Transcript printf:'Hello World %d\n' with:123
    "

    "Modified (comment): / 17-03-2019 / 15:05:29 / Claus Gittinger"
! !

!Stream methodsFor:'writing'!

printf:formatString arguments:arguments
    "C-style printing into a stream.
     Same as printf:withAll:, for protocol completeness.
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf"

    formatString printf:arguments on:self.

    "
     Transcript printf:'%05x %d %f %o\n' withAll:{ 123. 234*5. 1.234. 8r377 }
     Transcript printf:'%03d %03d %03d\n' withAll:{ 1. 2. 3 }
    "

    "Created: / 23-02-2017 / 16:43:39 / cg"
! !

!Stream methodsFor:'writing'!

printf:formatString with:argument
    "C-style printing into a stream.
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf"

    formatString printf:{argument} on:self.

    "
     Transcript printf:'%05x\n' with:12345
    "
! !

!Stream methodsFor:'writing'!

printf:formatString with:argument1 with:argument2
    "C-style printing into a stream.
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf"

    formatString printf:{argument1 . argument2} on:self.

    "
     Transcript printf:'%05x %3s\n' with:12345 with:'abc'
    "
! !

!Stream methodsFor:'writing'!

printf:formatString with:argument1 with:argument2 with:argument3
    "C-style printing into a stream.
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf"

    formatString printf:{argument1 . argument2 . argument3} on:self.

    "
     Transcript printf:'%05x %3s %09s\n' with:12345 with:'abc' with:'abc'
     Transcript printf:'%05x %3s %9s\n' with:12345 with:'abc' with:'abc'
    "
! !

!Stream methodsFor:'writing'!

printf:formatString with:argument1 with:argument2 with:argument3 with:argument4
    "C-style printing into a stream.
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf"

    formatString printf:{argument1 . argument2 . argument3 . argument4} on:self.

    "
     Transcript printf:'%02x %02x %02x %02x\n' with:1 with:2 with:3 with:4
     Transcript printf:'%2x %2x %2x %2x\n' with:1 with:2 with:3 with:4
     Transcript printf:'%-2x %-2x %-2x %-2x\n' with:1 with:2 with:3 with:4
    "
! !

!Stream methodsFor:'writing'!

printf:formatString with:argument1 with:argument2 with:argument3 with:argument4 with:argument5
    "C-style printing into a stream.
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf"

    formatString printf:{argument1 . argument2 . argument3 . argument4 . argument5} on:self.

    "
     Transcript printf:'%02x %02x %02x %02x\n' with:1 with:2 with:3 with:4
     Transcript printf:'%2x %2x %2x %2x\n' with:1 with:2 with:3 with:4
     Transcript printf:'%-2x %-2x %-2x %-2x\n' with:1 with:2 with:3 with:4
    "
! !

!Stream methodsFor:'writing'!

printf:formatString withAll:arguments
    "C-style printing into a stream.
     For smalltalk specific formats, 
     see documentation in PrintfScanf >> format_printf"

    formatString printf:arguments on:self.

    "
     Transcript printf:'%05x %d %f %o\n' withAll:{ 123. 234*5. 1.234. 8r377 }
     Transcript printf:'%03d %03d %03d\n' withAll:{ 1. 2. 3 }
    "
! !

!Stream methodsFor:'stacked computing streams'!

selecting:aBlock
    "return a stacked computing stream, which reads elements from the receiver,
     but only provides elements for which aBlock returns true to its reader."

    ^ SelectingReadStream on:self selecting:aBlock

    "
     |s s2|

     s := 'hello world' readStream.
     s2 := s selecting:[:ch | ch isVowel].
     s2 upToEnd.
    "
! !

!stx_libbasic2 class methodsFor:'documentation'!

extensionsVersion_CVS
    ^ '$Header$'
! !