<div dir="ltr"><div><div>Just a side note: nextFloat is broken in the sense that it will fail to answer the nearest floating point value to the specified decimal value.<br><br></div>OK, it&#39;s reasonably fast, but the comments should mention the trade offs.<br><br></div><div>Also in 32 bits VM, nextFloat might be slower than NumberParser when numbers are specified with many decimal digits.<br></div><div><br></div>Nicolas<br></div><div class="gmail_extra"><br><div class="gmail_quote">2015-04-02 0:08 GMT+02:00  <span dir="ltr">&lt;<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Levente Uzonyi uploaded a new version of Collections to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Collections-ul.607.mcz" target="_blank">http://source.squeak.org/trunk/Collections-ul.607.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Collections-ul.607<br>
Author: ul<br>
Time: 2 April 2015, 12:07:14.622 am<br>
UUID: 607c7a3f-c462-454c-8e18-02c49e4ae91a<br>
Ancestors: Collections-ul.606<br>
<br>
Simplified CharacterSet class&gt;&gt;separators.<br>
Fixed ReadStream &gt;&gt; #nextFloat, when collection is not a ByteString.<br>
<br>
=============== Diff against Collections-ul.606 ===============<br>
<br>
Item was changed:<br>
  ----- Method: CharacterSet class&gt;&gt;separators (in category &#39;accessing&#39;) -----<br>
  separators<br>
        &quot;return a set containing just the whitespace characters&quot;<br>
<br>
+       ^Separators ifNil: [ Separators := self newFrom: Character separators ]!<br>
-       ^Separators ifNil: [<br>
-               Separators := self new<br>
-                       addAll: Character separators;<br>
-                       yourself ]!<br>
<br>
Item was changed:<br>
  ----- Method: ReadStream&gt;&gt;nextFloat (in category &#39;accessing&#39;) -----<br>
  nextFloat<br>
        &quot;Read a floating point value from the receiver. This method is highly optimized for cases<br>
        where many floating point values need to be read subsequently. And if this needs to go<br>
        even faster, look at the inner loops fetching the characters - moving those into a plugin<br>
        would speed things up even more.&quot;<br>
        | buffer count sign index cc value digit fraction exp startIndex anyDigit digitNeeded |<br>
        buffer := collection.<br>
        count := readLimit.<br>
        index := position+1.<br>
<br>
        &quot;Skip separators&quot;<br>
+       index := ByteString findFirstInString: buffer inSet: CharacterSet nonSeparators byteArrayMap startingAt: index.<br>
-       index := buffer indexOfAnyOf: CharacterSet nonSeparators startingAt: index.<br>
        index = 0 ifTrue:[self setToEnd. ^nil].<br>
<br>
        &quot;check for sign&quot;<br>
        digitNeeded := false.<br>
        sign := 1. cc := buffer byteAt: index.<br>
        cc = 45 &quot;$- asciiValue&quot;<br>
                ifTrue:[sign := -1. index := index+1. digitNeeded := true]<br>
                ifFalse:[cc =  43 &quot;$+ asciiValue&quot; ifTrue:[index := index+1. digitNeeded := true]].<br>
<br>
        &quot;Read integer part&quot;<br>
        startIndex := index.<br>
        value := 0.<br>
        [index &lt;= count and:[<br>
                digit := (buffer byteAt: index) - 48. &quot;$0 asciiValue&quot;<br>
                digit &gt;= 0 and:[digit &lt;= 9]]] whileTrue:[<br>
                        value := value * 10 + digit.<br>
                        index := index + 1.<br>
        ].<br>
        anyDigit := index &gt; startIndex.<br>
        index &gt; count ifTrue:[<br>
                (digitNeeded and:[anyDigit not]) ifTrue:[^self error: &#39;At least one digit expected&#39;].<br>
                self setToEnd. ^value asFloat * sign].<br>
<br>
        (buffer byteAt: index) = 46 &quot;$. asciiValue&quot; ifTrue:[&quot;&lt;integer&gt;.&lt;fraction&gt;&quot;<br>
                index := index+1.<br>
                startIndex := index.<br>
                &quot;NOTE: fraction and exp below can overflow into LargeInteger range. If they do, then things slow down horribly due to the relatively slow LargeInt -&gt; Float conversion. This can be avoided by changing fraction and exp to use floats to begin with (0.0 and 1.0 respectively), however, this will give different results to Float&gt;&gt;readFrom: and it is not clear if that is acceptable here.&quot;<br>
                fraction := 0. exp := 1.<br>
                [index &lt;= count and:[<br>
                        digit := (buffer byteAt: index) - 48. &quot;$0 asciiValue&quot;<br>
                        digit &gt;= 0 and:[digit &lt;= 9]]] whileTrue:[<br>
                                fraction := fraction * 10 + digit.<br>
                                exp := exp * 10.<br>
                                index := index + 1.<br>
                ].<br>
                value := value + (fraction asFloat / exp asFloat).<br>
                anyDigit := anyDigit or:[index &gt; startIndex].<br>
        ].<br>
        value := value asFloat * sign.<br>
<br>
        &quot;At this point we require at least one digit to avoid allowing:<br>
                - . (&#39;0.0&#39; without leading digits)<br>
                - e32 (&#39;0e32&#39; without leading digits)<br>
                - .e32 (&#39;0.0e32&#39; without leading digits)<br>
        but these are currently allowed:<br>
                - .5 (0.5)<br>
                - 1. (&#39;1.0&#39;)<br>
                - 1e32 (&#39;1.0e32&#39;)<br>
                - 1.e32 (&#39;1.0e32&#39;)<br>
                - .5e32 (&#39;0.5e32&#39;)<br>
        &quot;<br>
        anyDigit ifFalse:[&quot;Check for NaN/Infinity first&quot;<br>
                (count - index &gt;= 2 and:[(buffer copyFrom: index to: index+2) = &#39;NaN&#39;])<br>
                        ifTrue:[position := index+2. ^Float nan * sign].<br>
                (count - index &gt;= 7 and:[(buffer copyFrom: index to: index+7) = &#39;Infinity&#39;])<br>
                        ifTrue:[position := index+7. ^Float infinity * sign].<br>
                ^self error: &#39;At least one digit expected&#39;<br>
        ].<br>
<br>
        index &gt; count ifTrue:[self setToEnd. ^value asFloat].<br>
<br>
        (buffer byteAt: index) = 101 &quot;$e asciiValue&quot; ifTrue:[&quot;&lt;number&gt;e[+|-]&lt;exponent&gt;&quot;<br>
                index := index+1. &quot;skip e&quot;<br>
                sign := 1. cc := buffer byteAt: index.<br>
                cc = 45 &quot;$- asciiValue&quot;<br>
                        ifTrue:[sign := -1. index := index+1]<br>
                        ifFalse:[cc = 43 &quot;$+ asciiValue&quot; ifTrue:[index := index+1]].<br>
                startIndex := index.<br>
                exp := 0. anyDigit := false.<br>
                [index &lt;= count and:[<br>
                        digit := (buffer byteAt: index) - 48. &quot;$0 asciiValue&quot;<br>
                        digit &gt;= 0 and:[digit &lt;= 9]]] whileTrue:[<br>
                                exp := exp * 10 + digit.<br>
                                index := index + 1.<br>
                ].<br>
                index&gt; startIndex ifFalse:[^self error: &#39;Exponent expected&#39;].<br>
                value := value * (10.0 raisedToInteger: exp * sign).<br>
        ].<br>
<br>
        position := index-1.<br>
        ^value!<br>
<br>
<br>
</blockquote></div><br></div>