The Trunk: WebClient-Core-nice.119.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: WebClient-Core-nice.119.mcz

commits-2
Nicolas Cellier uploaded a new version of WebClient-Core to project The Trunk:
http://source.squeak.org/trunk/WebClient-Core-nice.119.mcz

==================== Summary ====================

Name: WebClient-Core-nice.119
Author: nice
Time: 12 September 2019, 12:55:52.391336 am
UUID: 7a017a9c-1a85-4a4e-bbfb-63ed34c747e9
Ancestors: WebClient-Core-topa.118

Fix a bunch of serious bugs in json number decoding

Implementation will now answer the nearest Float, what it failed to previously.

=============== Diff against WebClient-Core-topa.118 ===============

Item was added:
+ ----- Method: WebUtils class>>jsonFloatSignificand:exp10: (in category 'json-decode') -----
+ jsonFloatSignificand: value exp10: exponent
+ "Take care to convert to nearest Float"
+ ^self jsonFloatSignificand: value exp10: exponent scale: (10 raisedTo: exponent abs)!

Item was added:
+ ----- Method: WebUtils class>>jsonFloatSignificand:exp10:scale: (in category 'json-decode') -----
+ jsonFloatSignificand: value exp10: exponent scale: scale
+ "Take care to convert to nearest Float"
+ "self assert: scale = (10 raisedTo: exponent abs)."
+ ^(value isAnExactFloat and: ["scale isAnExactFloat"
+ exponent between: -22 and: 22
+ "(1 to: 100) detect: [:i | (10 raisedTo: i) isAnExactFloat not]"])
+ ifTrue: [exponent >= 0
+ ifTrue: [value asExactFloat * scale asExactFloat]
+ ifFalse: [value asExactFloat / scale asExactFloat]]
+ ifFalse: [exponent >= 0
+ ifTrue: [(value * scale) asFloat]
+ ifFalse: [(Fraction numerator: value denominator: scale) asFloat]]!

Item was changed:
  ----- Method: WebUtils class>>jsonNumberFrom: (in category 'json-decode') -----
  jsonNumberFrom: stream
  "Decodes a JSON number from the stream"
 
+ | ascii ch integer fraction scale sign expSign exponent exp value beFloat |
+ integer := fraction := exponent := exp := 0. sign := scale := expSign := 1.
- | ascii integer fraction scale sign expSign exponent value ch |
- integer := fraction := 0. sign := scale := exponent := expSign := 1.
  ascii := stream next asciiValue.
  ascii = 45 "$- asciiValue" ifTrue:[
  sign := -1.
  ascii := stream next asciiValue.
  ].
  "JSON requires at least one digit"
  (ascii >= 48 and:[ascii <= 57]) ifFalse:[^self error: 'Digit expected'].
 
  "Read the integer part"
  integer := ascii - 48.
  [ch := stream next ifNil:[^integer * sign].
  ascii := ch asciiValue.
  ascii >= 48 and:[ascii <= 57]] whileTrue:[
  integer := (integer * 10) + (ascii - 48).
  ].
 
+ (beFloat := ascii = 46) "$. asciiValue" ifTrue:[
- ascii = 46 "$. asciiValue" ifTrue:[
  "Read the fraction part"
+ [ch := stream next ifNil:
+ [value := integer * scale + fraction * sign.
+ ^self jsonFloatSignificand: value exp10: exponent scale: scale].
- [ch := stream next ifNil:[^(integer * scale + fraction * sign) asFloat / scale].
  ascii := ch asciiValue.
  ascii >= 48 and:[ascii <= 57]] whileTrue:[
  fraction := (fraction * 10) + (ascii - 48).
+ exponent := exponent - 1.
  scale := scale * 10.
  ].
+ value := integer * scale + fraction * sign.
- value := (integer * scale + fraction * sign) asFloat / scale asFloat.
  ] ifFalse:[value := integer * sign].
-
  (ascii =  69 "$E asciiValue" or:[ascii =  101 "$e asciiValue"]) ifTrue:[
  "Read exponent"
  ascii := stream next asciiValue.
+ ascii =  45 "$- asciiValue" ifTrue:[
- ascii = $- ifTrue:[
  expSign := -1.
  ascii := stream next asciiValue.
+ ] ifFalse:[ascii =  43 "$+ asciiValue" ifTrue:[ascii := stream next asciiValue]].
+ exp := ascii - 48.
+ [ch := stream next ifNil:
+ [exponent := exp * expSign + exponent.
+ (beFloat or: [expSign = -1]) ifTrue: [^self jsonFloatSignificand: value exp10: exponent].
+ ^value * (10 raisedTo: exponent)].
- ] ifFalse:[ascii = $+ ifTrue:[ascii := stream next asciiValue]].
- exponent := ascii - 48.
- [ch := stream next ifNil:[^value * (10 raisedTo: expSign * exponent)].
  ascii := ch asciiValue.
  ascii >= 48 and:[ascii <= 57]] whileTrue:[
+ exp := (exp * 10) + (ascii - 48).
- exponent := (exponent * 10) + (ascii - 48).
  ].
+ exponent := exp * expSign + exponent
- exponent := exponent * expSign.
  ].
 
  "Skip back before last character since number might be part of a sequence
  like 1, 2, 3, 4, etc (which would eat the trailing comma)"
  ch isAlphaNumeric ifTrue:[^self error: 'Delimiter expected'].
  stream skip: -1.
 
+ (beFloat or: [expSign = -1]) ifTrue: [^self jsonFloatSignificand: value exp10: exponent].
+ ^value * (10 raisedTo: exponent)!
- exponent = 1 ifFalse:[
- exponent < 0 ifTrue:[value := value asFloat].
- value := value * (10 raisedTo: exponent).
- ].
- ^value!