110 ]. |
110 ]. |
111 Time millisecondsToRun:[ |
111 Time millisecondsToRun:[ |
112 100000 timesRepeat:[ Integer fastFromString:'12345' ] |
112 100000 timesRepeat:[ Integer fastFromString:'12345' ] |
113 ]. |
113 ]. |
114 " |
114 " |
|
115 ! |
|
116 |
|
117 fastFromString:aString at:startIndex |
|
118 "return the next Float, Integer or ShortFloat from the string. |
|
119 No spaces are skipped. |
|
120 |
|
121 This is a specially tuned entry (using a low-level C-call), which |
|
122 returns garbage if the argument string is not a valid float number. |
|
123 It has been added to allow high speed string decomposition into numbers, |
|
124 especially for mass-data." |
|
125 |
|
126 self subclassResponsibility |
|
127 |
|
128 " |
|
129 Float fromString:'12345.0' |
|
130 Float fastFromString:'12345.0' |
|
131 |
|
132 Integer fromString:'12345' |
|
133 Integer fastFromString:'12345' |
|
134 |
|
135 should be roughly 10times faster than the general method: |
|
136 |
|
137 Time millisecondsToRun:[ |
|
138 100000 timesRepeat:[ Float fromString:'12345.0' ] |
|
139 ]. |
|
140 Time millisecondsToRun:[ |
|
141 100000 timesRepeat:[ Float fastFromString:'12345.0' ] |
|
142 ]. |
|
143 |
|
144 Time millisecondsToRun:[ |
|
145 100000 timesRepeat:[ Integer fromString:'12345' ] |
|
146 ]. |
|
147 Time millisecondsToRun:[ |
|
148 100000 timesRepeat:[ Integer fastFromString:'12345' ] |
|
149 ]. |
|
150 " |
|
151 |
|
152 "Created: / 21-07-2019 / 19:17:17 / Claus Gittinger" |
115 ! |
153 ! |
116 |
154 |
117 fromNumber:aNumber |
155 fromNumber:aNumber |
118 "return aNumber coerced to myself" |
156 "return aNumber coerced to myself" |
119 |
157 |
518 if sent to a concrete number-class, an instance of that class will be returned (independent of the exponent character) |
556 if sent to a concrete number-class, an instance of that class will be returned (independent of the exponent character) |
519 " |
557 " |
520 |
558 |
521 ^ [ |
559 ^ [ |
522 |value intValue mantissaAndScale scale decimalMantissa str |
560 |value intValue mantissaAndScale scale decimalMantissa str |
523 nextChar radix sign signExp exp numerator denom expChar fragment| |
561 nextChar radix sign signExp exp numerator denom expChar fragment mantissa| |
524 |
562 |
525 str := aStringOrStream readStream. |
563 str := aStringOrStream readStream. |
526 |
564 |
527 nextChar := str skipSeparators. |
565 nextChar := str skipSeparators. |
528 nextChar isNil ifTrue:[^ exceptionBlock value]. |
566 nextChar isNil ifTrue:[^ exceptionBlock value]. |
529 |
567 |
530 (nextChar == $-) ifTrue:[ |
568 (nextChar == $-) ifTrue:[ |
531 sign := -1. |
569 sign := -1. |
532 str next. |
570 nextChar := str nextPeekOrNil |
533 nextChar := str peekOrNil |
|
534 ] ifFalse:[ |
571 ] ifFalse:[ |
535 sign := 1. |
572 sign := 1. |
536 (nextChar == $+) ifTrue:[ |
573 (nextChar == $+) ifTrue:[ |
537 str next. |
574 nextChar := str nextPeekOrNil |
538 nextChar := str peekOrNil |
|
539 ] |
575 ] |
540 ]. |
576 ]. |
541 nextChar == $( ifTrue:[ |
577 nextChar == $( ifTrue:[ |
542 "maybe a Fraction e.g. (1/3)" |
578 "maybe a Fraction e.g. (1/3)" |
543 str next. |
579 str next. |
574 value := self zero. "/ 0.0. |
610 value := self zero. "/ 0.0. |
575 ]. |
611 ]. |
576 intValue := 0. |
612 intValue := 0. |
577 ] ifFalse:[ |
613 ] ifFalse:[ |
578 (allowCStyle and:[nextChar == $0]) ifTrue:[ |
614 (allowCStyle and:[nextChar == $0]) ifTrue:[ |
579 str next. |
615 nextChar := str nextPeekOrNil. |
580 nextChar := str peekOrNil. |
|
581 nextChar isNil ifTrue:[^ 0]. |
616 nextChar isNil ifTrue:[^ 0]. |
582 nextChar == $x ifTrue:[ |
617 nextChar == $x ifTrue:[ str next. radix := 16 ] |
583 str next. |
618 ifFalse:[ nextChar == $b ifTrue:[ str next. radix := 2 ] |
584 radix := 16. |
619 ifFalse:[ nextChar == $o ifTrue:[ str next. radix := 8 ] |
585 ] ifFalse:[ |
620 ifFalse:[ |
586 nextChar == $b ifTrue:[ |
621 nextChar isDigit ifFalse:[ |
587 str next. |
622 ^ 0 |
588 radix := 2. |
623 ]. |
589 ] ifFalse:[ |
624 ]]]. |
590 nextChar == $o ifTrue:[ |
|
591 str next. |
|
592 radix := 8. |
|
593 ] ifFalse:[ |
|
594 nextChar isDigit ifFalse:[ |
|
595 ^ 0 |
|
596 ]. |
|
597 ]. |
|
598 ]. |
|
599 ]. |
|
600 value := Integer readFrom:str radix:radix. |
625 value := Integer readFrom:str radix:radix. |
601 nextChar := str peekOrNil. |
626 nextChar := str peekOrNil. |
602 ] ifFalse:[ |
627 ] ifFalse:[ |
603 value := Integer readFrom:str radix:10. |
628 value := Integer readFrom:str radix:10. |
604 nextChar := str peekOrNil. |
629 nextChar := str peekOrNil. |
606 str next. |
631 str next. |
607 fragment := str next:3. |
632 fragment := str next:3. |
608 (fragment conform:#isDigit) ifFalse:[ |
633 (fragment conform:#isDigit) ifFalse:[ |
609 ^ exceptionBlock value. |
634 ^ exceptionBlock value. |
610 ]. |
635 ]. |
611 value := (value * 1000) + (Integer readFrom:fragment). |
636 value := (value * 1000) + (Integer fastFromString:fragment at:1). |
612 nextChar := str peekOrNil. |
637 nextChar := str peekOrNil. |
613 ]. |
638 ]. |
614 ((nextChar == $r) or:[ nextChar == $R]) ifTrue:[ |
639 ((nextChar == $r) or:[ nextChar == $R]) ifTrue:[ |
615 str next. |
640 str next. |
616 radix := value. |
641 radix := value. |
623 intValue := value. |
648 intValue := value. |
624 ]. |
649 ]. |
625 |
650 |
626 (self == Integer or:[self inheritsFrom:Integer]) ifFalse:[ |
651 (self == Integer or:[self inheritsFrom:Integer]) ifFalse:[ |
627 (decimalPointCharacters includes:nextChar) ifTrue:[ |
652 (decimalPointCharacters includes:nextChar) ifTrue:[ |
628 str next. |
653 nextChar := str nextPeekOrNil. |
629 nextChar := str peekOrNil. |
|
630 decimalMantissa := 0. |
654 decimalMantissa := 0. |
631 (nextChar notNil and:[nextChar isDigitRadix:radix]) ifTrue:[ |
655 (nextChar notNil and:[nextChar isDigitRadix:radix]) ifTrue:[ |
632 |mantissa| |
|
633 mantissaAndScale := self readMantissaAndScaleFrom:str radix:radix. |
656 mantissaAndScale := self readMantissaAndScaleFrom:str radix:radix. |
634 mantissa := mantissaAndScale first. |
657 mantissa := mantissaAndScale first. |
635 value := (mantissa coerce:value) + mantissa. |
658 value := (mantissa coerce:value) + mantissa. |
636 nextChar := str peekOrNil. |
659 nextChar := str peekOrNil. |
637 ] |
660 ] |
638 ]. |
661 ]. |
639 |
662 |
640 ('eEdDqQfF' includes:nextChar) ifTrue:[ |
663 ('eEdDqQfF' includes:nextChar) ifTrue:[ |
641 expChar := nextChar. |
664 expChar := nextChar. |
642 str next. |
665 nextChar := str nextPeekOrNil. |
643 |
|
644 nextChar := str peekOrNil. |
|
645 |
666 |
646 signExp := 1. |
667 signExp := 1. |
647 (nextChar == $+) ifTrue:[ |
668 (nextChar == $+) ifTrue:[ |
648 str next. |
669 nextChar := str nextPeekOrNil. |
649 nextChar := str peekOrNil. |
|
650 ] ifFalse:[ |
670 ] ifFalse:[ |
651 (nextChar == $-) ifTrue:[ |
671 (nextChar == $-) ifTrue:[ |
652 str next. |
672 nextChar := str nextPeekOrNil. |
653 nextChar := str peekOrNil. |
|
654 signExp := -1 |
673 signExp := -1 |
655 ] |
674 ] |
656 ]. |
675 ]. |
657 |
676 |
658 "/ if I am abstract (i.e. I am Number or LPReal), |
677 "/ if I am abstract (i.e. I am Number or LPReal), |
687 exp := (Integer readFrom:str radix:radix) * signExp. |
706 exp := (Integer readFrom:str radix:radix) * signExp. |
688 value := value * ((value class unity * 10.0) raisedToInteger:exp) |
707 value := value * ((value class unity * 10.0) raisedToInteger:exp) |
689 ] |
708 ] |
690 ] ifFalse:[ |
709 ] ifFalse:[ |
691 ('sS' includes:nextChar) ifTrue:[ |
710 ('sS' includes:nextChar) ifTrue:[ |
692 str next. |
711 nextChar := str nextPeekOrNil. |
693 |
|
694 nextChar := str peekOrNil. |
|
695 (nextChar notNil and:[ nextChar isDigit]) ifTrue:[ |
712 (nextChar notNil and:[ nextChar isDigit]) ifTrue:[ |
696 scale := (Integer readFrom:str). |
713 scale := (Integer readFrom:str). |
697 ]. |
714 ]. |
698 |
715 |
699 mantissaAndScale isNil ifTrue:[ |
716 mantissaAndScale isNil ifTrue:[ |
786 DecimalPointCharactersForReading := #( $. ). |
803 DecimalPointCharactersForReading := #( $. ). |
787 Number readFrom:'99,00' |
804 Number readFrom:'99,00' |
788 " |
805 " |
789 |
806 |
790 "Created: / 21-07-2019 / 13:05:04 / Claus Gittinger" |
807 "Created: / 21-07-2019 / 13:05:04 / Claus Gittinger" |
791 "Modified (format): / 21-07-2019 / 17:58:37 / Claus Gittinger" |
808 "Modified: / 21-07-2019 / 19:40:34 / Claus Gittinger" |
792 ! |
809 ! |
793 |
810 |
794 readFrom:aStringOrStream decimalPointCharacters:decimalPointCharacters thousandsSeparator:thousandsSeparator onError:exceptionBlock |
811 readFrom:aStringOrStream decimalPointCharacters:decimalPointCharacters thousandsSeparator:thousandsSeparator onError:exceptionBlock |
795 "return the next Number from the (character-)stream aStream; |
812 "return the next Number from the (character-)stream aStream; |
796 skipping all whitespace first. |
813 skipping all whitespace first. |