class: CharacterArray
code duplication removed
changed:
#printf:on:
#printf_printArgFrom:to:withData:
--- 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'!