class: CharacterArray
authorClaus Gittinger <cg@exept.de>
Mon, 19 Jun 2017 16:54:35 +0200
changeset 4418 05f82ac9d198
parent 4417 01b4de1f0b01
child 4419 ee66504fb36a
class: CharacterArray code duplication removed changed: #printf:on: #printf_printArgFrom:to:withData:
extensions.st
--- a/extensions.st	Mon Jun 19 16:52:27 2017 +0200
+++ b/extensions.st	Mon Jun 19 16:54:35 2017 +0200
@@ -248,27 +248,23 @@
 
      For copyright information, see goodies/String-printf_scanf.chg"
 
-    |argStream inStream char escChar|
+    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
 
-    argStream := ReadStream on:args.
-    inStream := ReadStream on:self.
-    [ inStream atEnd ] whileFalse:[
-        (char := inStream next) == $% ifFalse:[
-            char == $\ ifTrue:[
-                escChar := inStream next.
-                escChar == $n ifTrue:[ char := Character nl ]
-                ifFalse:[ escChar == $t ifTrue:[ char := Character tab ]
-                ifFalse:[ escChar == $r ifTrue:[ char := Character return ]
-                ifFalse:[ char := escChar ]]]
-            ].        
-            outStream nextPut:char
-        ] ifTrue:[
-            self
-                printf_printArgFrom:inStream
-                to:outStream
-                withData:argStream
-        ]
-    ]
+     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): / 19-06-2017 / 15:51:57 / cg"
 ! !
 
 !CharacterArray methodsFor:'printing & storing'!
@@ -335,41 +331,27 @@
      as a printf/scanf format control string.
      For copyright information, see goodies/String-printf_scanf.chg"
 
-    |nonConsecutive count|
+    ^ PrintfScanf formatArgCountFor:self.
 
-    nonConsecutive := true.
-    count := 0.
-    self do:[:c |
-	c == $% ifTrue:[
-	    nonConsecutive ifTrue:[
-		count := count + 1.
-		nonConsecutive := false
-	    ] ifFalse:[
-		count := count - 1.
-		nonConsecutive := true
-	    ]
-	] ifFalse:[
-	    nonConsecutive := true
-	]
-    ].
-    ^ count
+    "Modified: / 19-06-2017 / 16:54:10 / cg"
 ! !
 
 !CharacterArray methodsFor:'private'!
 
-printf_printArgFrom:inStream to:outStream withData:argStream
+printf_printArgFrom:formatStream to:outStream withData:argStream
+    <resource: #obsolete>
     "Interpret the required number of arguments from <argStream>
-     according to the formatting information in <inStream>.
+     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).
-     <inStream> is assumed to be positioned just past
+     <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 <inStream> pointing past the last character in the conversion control string.
+     Leave <formatStream> pointing past the last character in the conversion control string.
 
-     This code assumes that <inStream> is formatted according to
+     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
@@ -377,172 +359,9 @@
 
      For copyright information, see goodies/String-printf_scanf.chg"
 
-    |nextArg ljust plus pound width precision pad char arg argString|
-
-    nextArg := [
-                    argStream atEnd ifTrue:[
-                        self error:'not enough arguments for format string'
-                    ].
-                    argStream next
-               ].
+    PrintfScanf printArgFrom:formatStream to:outStream arguments:argStream
 
-    ljust := plus := pound := false.
-    width := 0.
-    precision := SmallInteger maxVal.
-    pad := $ .
-    char := inStream peek.
-    char == $% ifTrue:[
-        ^ outStream nextPut:inStream next
-    ].
-    char == $- ifTrue:[
-        ljust := true.
-        inStream next.
-        char := inStream peek
-    ].
-    char == $  ifTrue:[
-        outStream space.
-        inStream next.
-        char := inStream peek
-    ].
-    char == $+ ifTrue:[
-        plus := true.
-        inStream next.
-        char := inStream peek
-    ].
-    char == $# ifTrue:[
-        pound := true.
-        inStream next.
-        char := inStream peek
-    ].
-    char == $* ifTrue:[
-        width := nextArg value.
-        inStream next.
-        char := inStream peek
-    ].
-    char isDigit ifTrue:[
-        char == $0 ifTrue:[
-            pad := $0
-        ].
-        width := Integer readFrom:inStream.
-        char := inStream peek
-    ].
-    char == $. ifTrue:[
-        inStream next.
-        char := inStream peek.
-        char == $* ifTrue:[
-            precision := nextArg value.
-            inStream next.
-        ] ifFalse:[
-            precision := Integer readFrom:inStream.
-        ].
-        char := inStream peek
-    ].
-    char == $l "Ignore long specifier." ifTrue:[
-        inStream next.
-        char := inStream peek
-    ].
-    ('feg' includes:char) ifTrue:[
-        arg := nextArg value asFloat.
-        precision := precision min:6.
-        argString := WriteStream on:''.
-        char == $g ifTrue:[
-            arg absPrintOn:argString digits:precision + 1
-        ].
-        char == $f ifTrue:[
-            arg absDecimalPrintOn:argString digits:precision + arg abs log + 1
-        ].
-        char == $e ifTrue:[
-            arg absScientificPrintOn:argString digits:precision + 1
-        ].
-        argString := argString contents.
-        arg < 0 ifTrue:[
-            argString := '-' , argString
-        ] ifFalse:[
-            plus ifTrue:[
-                argString := '+' , argString
-            ]
-        ].
-        (precision = 0 and:[ pound not ]) ifTrue:[
-            (argString includes:$e) ifTrue:[
-                "self halt"
-            ] ifFalse:[
-                argString := arg truncated printString
-            ]
-        ].
-        pound ifTrue:[
-            (argString includes:$e) ifTrue:[
-                "self halt"
-            ] ifFalse:[
-                precision - (argString size - (argString indexOf:$.)) timesRepeat:[
-                    argString := argString , '0'
-                ]
-            ]
-        ].
-        ljust ifTrue:[
-            outStream nextPutAll:argString
-        ].
-        width - argString size timesRepeat:[
-            outStream space
-        ].
-        ljust ifFalse:[
-            outStream nextPutAll:argString
-        ].
-        ^ inStream next
-    ].
-    char == $c ifTrue:[
-        arg := String with:nextArg value asCharacter
-    ].
-    char == $s ifTrue:[
-        "Assume the arg is a String or Symbol. (if not, its printString is used)" 
-        arg := nextArg value asString
-    ].
-    char == $d ifTrue:[
-        arg := nextArg value asInteger printString.
-        plus ifTrue:[
-            arg := '+' , arg
-        ]
-    ].
-    char == $u ifTrue:[
-        arg := nextArg value asInteger abs printString
-    ].
-    char == $o ifTrue:[
-        arg := nextArg value asInteger abs printStringRadix:8.
-        pound ifTrue:[
-            arg := '0' , arg
-        ]
-    ].
-    char == $b ifTrue:[
-        arg := nextArg value asInteger abs printStringRadix:2.
-        pound ifTrue:[
-            arg := '0' , arg
-        ]
-    ].
-    ('xX' includes:char) ifTrue:[
-        arg := nextArg value asInteger abs printStringRadix:16.
-        pound ifTrue:[
-            arg := '0x' , arg
-        ]
-    ].
-    char == $x ifTrue:[
-        1 to:arg size do:[:i |
-            ('ABCDEF' includes:(arg at:i)) ifTrue:[
-                arg at:i put:(arg at:i) asLowercase
-            ]
-        ]
-    ].
-    precision := precision min:arg size.
-    ljust ifTrue:[
-        outStream nextPutAll:(arg copyFrom:1 to:precision)
-    ].
-    width - precision timesRepeat:[
-        outStream nextPut:pad
-    ].
-    ljust ifFalse:[
-        outStream nextPutAll:(arg copyFrom:1 to:precision)
-    ].
-    ^ inStream next
-
-    "Modified: / 24-07-2011 / 07:16:42 / cg"
+    "Modified: / 19-06-2017 / 15:44:28 / cg"
 ! !
 
 !CharacterArray methodsFor:'printing & storing'!
@@ -597,6 +416,7 @@
 !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>.
@@ -837,38 +657,40 @@
 
     "x is myself normalized to (1.0, 10.0), exp is my exponent"
     exp := self abs < 1.0
-		ifTrue:[ (10.0 / self abs) log floor negated ]
-		ifFalse:[ self abs log floor ].
+                ifTrue:[ (10.0 / self abs) log10 floor negated ]
+                ifFalse:[ self abs log10 floor ].
     x := self abs / (10.0 raisedTo:exp).
     fuzz := 10.0 raisedTo:1 - digits.
      "round the last digit to be printed"
     x := 0.5 * fuzz + x.
     x >= 10.0 "check if rounding has unnormalized x" ifTrue:[
-	x := x / 10.0.
-	exp := exp + 1
+        x := x / 10.0.
+        exp := exp + 1
     ].
     exp < 0 ifTrue:[
-	1 to:1 - exp do:[:j |
-	    aStream nextPut:('0.000000000000' at:j)
-	]
+        1 to:1 - exp do:[:j |
+            aStream nextPut:('0.000000000000' at:j)
+        ]
     ].
     [ x >= fuzz ] "use fuzz to track significance" whileTrue:[
-	i := x truncated.
-	aStream nextPut:(48 + i) asCharacter.
-	x := (x - i) * 10.0.
-	fuzz := fuzz * 10.0.
-	exp := exp - 1.
-	exp = -1 ifTrue:[
-	    aStream nextPut:$.
-	]
+        i := x truncated.
+        aStream nextPut:(48 + i) asCharacter.
+        x := (x - i) * 10.0.
+        fuzz := fuzz * 10.0.
+        exp := exp - 1.
+        exp = -1 ifTrue:[
+            aStream nextPut:$.
+        ]
     ].
     [ exp >= -1 ] whileTrue:[
-	aStream nextPut:$0.
-	exp := exp - 1.
-	exp = -1 ifTrue:[
-	    aStream nextPut:$.
-	]
+        aStream nextPut:$0.
+        exp := exp - 1.
+        exp = -1 ifTrue:[
+            aStream nextPut:$.
+        ]
     ]
+
+    "Modified: / 19-06-2017 / 14:53:47 / cg"
 ! !
 
 !Float methodsFor:'private'!
@@ -878,11 +700,9 @@
      <digits> significant digits.
      This is a helper for printf."
 
-    (self < 1.0e6 and:[ self > 1.0e-4 ]) ifTrue:[
-	self absDecimalPrintOn:aStream digits:digits
-    ] ifFalse:[
-	self absScientificPrintOn:aStream digits:digits
-    ]
+    PrintfScanf absPrintFloat:self on:aStream digits:digits
+
+    "Modified: / 19-06-2017 / 15:04:24 / cg"
 ! !
 
 !Float methodsFor:'private'!
@@ -892,41 +712,9 @@
      digits, using scientific notation.
      This is a helper for printf."
 
-    |exp fuzz x q i|
+    PrintfScanf absScientificPrintFloat:self on:aStream digits:digits.
 
-    "x is myself normalized to [1.0, 10.0), exp is my exponent"
-    exp := self abs < 1.0
-	    ifTrue:[ (10.0 / self abs) log floor negated ]
-	    ifFalse:[ self abs log floor ].
-    x := self abs / (10.0 raisedTo:exp).
-    fuzz := 10.0 raisedTo:1 - digits.
-     "round the last digit to be printed"
-    x := 0.5 * fuzz + x.
-    x >= 10.0 "check if rounding has unnormalized x" ifTrue:[
-	x := x / 10.0.
-	exp := exp + 1
-    ].
-    q := exp.
-    exp := 0.
-    [ x >= fuzz ] "use fuzz to track significance" whileTrue:[
-	i := x truncated.
-	aStream nextPut:(48 + i) asCharacter.
-	x := (x - i) * 10.0.
-	fuzz := fuzz * 10.0.
-	exp := exp - 1.
-	exp = -1 ifTrue:[
-	    aStream nextPut:$.
-	]
-    ].
-    [ exp >= -1 ] whileTrue:[
-	aStream nextPut:$0.
-	exp := exp - 1.
-	exp = -1 ifTrue:[
-	    aStream nextPut:$.
-	]
-    ].
-    aStream nextPut:$e.
-    q printOn:aStream
+    "Modified: / 19-06-2017 / 14:59:56 / cg"
 ! !
 
 !Float methodsFor:'coercing & converting'!