84 ! ! |
84 ! ! |
85 |
85 |
86 !PrintfScanf class methodsFor:'others'! |
86 !PrintfScanf class methodsFor:'others'! |
87 |
87 |
88 version_CVS |
88 version_CVS |
89 ^ '$Header: /cvs/stx/stx/libbasic2/PrintfScanf.st,v 1.5 2011-11-29 10:56:05 cg Exp $' |
89 ^ '$Header: /cvs/stx/stx/libbasic2/PrintfScanf.st,v 1.6 2013-01-23 10:01:22 cg Exp $' |
|
90 ! ! |
|
91 |
|
92 !PrintfScanf class methodsFor:'printing'! |
|
93 |
|
94 printf:formatString arguments:args |
|
95 "Format and print the receiver with <args> formatted in C style, |
|
96 as described in the UTek manual page for printf(3)." |
|
97 |
|
98 ^ self new printf:formatString arguments:args |
|
99 ! |
|
100 |
|
101 printf:formatString on:outStream arguments: args |
|
102 "Format and print formatString on <outStream> with <args> |
|
103 formatted in C style, as described in the UTek manual page for |
|
104 printf(3). This method is designed for producing output |
|
105 suitable for a machine." |
|
106 |
|
107 ^ self new printf:formatString on:outStream arguments: args |
|
108 ! ! |
|
109 |
|
110 !PrintfScanf class methodsFor:'scanning'! |
|
111 |
|
112 scanf:formatString fromStream:dataStream |
|
113 "Return a Collection of objects found in the Character Stream |
|
114 <dataStream> as interpreted according to the receiver. The |
|
115 receiver is assumed to be a conversion control string as |
|
116 specified in the UTek manual page for scanf(3)." |
|
117 |
|
118 ^ self new scanf:formatString fromStream:dataStream |
|
119 ! |
|
120 |
|
121 sscanf:formatString fromString:aString |
|
122 "Return a Collection of objects found in <string> as |
|
123 interpreted according to the receiver. The receiver is |
|
124 assumed to be a conversion control string as specified in the |
|
125 UTek manual page for scanf(3)." |
|
126 |
|
127 ^ self new sscanf:formatString fromString:aString |
|
128 ! ! |
|
129 |
|
130 !PrintfScanf methodsFor:'helpers'! |
|
131 |
|
132 absDecimalPrintFloat:aFloat on:aStream digits:digits |
|
133 "Place a string representation of the receiver on <aStream> using <digits> significant digits, using decimal notation." |
|
134 |
|
135 |exp x fuzz i| |
|
136 |
|
137 "x is myself normalized to (1.0, 10.0), exp is my exponent" |
|
138 exp := aFloat abs < 1.0 ifTrue:[ |
|
139 (10.0 / aFloat abs) log floor negated |
|
140 ] ifFalse:[ |
|
141 aFloat abs log floor |
|
142 ]. |
|
143 x := aFloat abs / (10.0 raisedTo:exp). |
|
144 fuzz := 10.0 raisedTo:1 - digits. |
|
145 x := 0.5 * fuzz + x. |
|
146 x >= 10.0 ifTrue:[ |
|
147 "check if rounding has unnormalized x" |
|
148 x := x / 10.0. |
|
149 exp := exp + 1 |
|
150 ]. |
|
151 exp < 0 ifTrue:[ |
|
152 1 to:1 - exp do:[:j | |
|
153 aStream nextPut:('0.000000000000' at:j) |
|
154 ] |
|
155 ]. |
|
156 [ x >= fuzz ] whileTrue:[ |
|
157 "use fuzz to track significance" |
|
158 i := x truncated. |
|
159 aStream nextPut:(48 + i) asCharacter. |
|
160 x := (x - i) * 10.0. |
|
161 fuzz := fuzz * 10.0. |
|
162 exp := exp - 1. |
|
163 exp = -1 ifTrue:[ |
|
164 aStream nextPut:$. |
|
165 ] |
|
166 ]. |
|
167 [ exp >= -1 ] whileTrue:[ |
|
168 aStream nextPut:$0. |
|
169 exp := exp - 1. |
|
170 exp = -1 ifTrue:[ |
|
171 aStream nextPut:$. |
|
172 ] |
|
173 ] |
|
174 ! |
|
175 |
|
176 absPrintFloat:aFloat on:aStream digits:digits |
|
177 "Place a string representation of the receiver on <aStream> using <digits> significant digits." |
|
178 |
|
179 (aFloat < 1.0e6 and:[ aFloat > 1.0e-4 ]) ifTrue:[ |
|
180 self |
|
181 absDecimalPrintFloat:aFloat |
|
182 on:aStream |
|
183 digits:digits |
|
184 ] ifFalse:[ |
|
185 aFloat |
|
186 absScientificPrintFloat:aFloat |
|
187 on:aStream |
|
188 digits:digits |
|
189 ] |
|
190 ! |
|
191 |
|
192 absScientificPrintFloat:aFloat on:aStream digits:digits |
|
193 "Place a string representation of the receiver on <aStream> using <digits> significant digits, using scientific notation." |
|
194 |
|
195 |exp fuzz x q i| |
|
196 |
|
197 "x is myself normalized to [1.0, 10.0), exp is my exponent" |
|
198 exp := aFloat abs < 1.0 ifTrue:[ |
|
199 (10.0 / aFloat abs) log floor negated |
|
200 ] ifFalse:[ |
|
201 aFloat abs log floor |
|
202 ]. |
|
203 x := aFloat abs / (10.0 raisedTo:exp). |
|
204 fuzz := 10.0 raisedTo:1 - digits. |
|
205 x := 0.5 * fuzz + x. |
|
206 x >= 10.0 ifTrue:[ "check if rounding has unnormalized x" |
|
207 x := x / 10.0. |
|
208 exp := exp + 1 |
|
209 ]. |
|
210 q := exp. |
|
211 exp := 0. |
|
212 [ x >= fuzz ] whileTrue:[ |
|
213 "use fuzz to track significance" |
|
214 i := x truncated. |
|
215 aStream nextPut:(48 + i) asCharacter. |
|
216 x := (x - i) * 10.0. |
|
217 fuzz := fuzz * 10.0. |
|
218 exp := exp - 1. |
|
219 exp = -1 ifTrue:[ |
|
220 aStream nextPut:$. |
|
221 ] |
|
222 ]. |
|
223 [ exp >= -1 ] whileTrue:[ |
|
224 aStream nextPut:$0. |
|
225 exp := exp - 1. |
|
226 exp = -1 ifTrue:[ |
|
227 aStream nextPut:$. |
|
228 ] |
|
229 ]. |
|
230 aStream nextPut:$e. |
|
231 q printOn:aStream |
|
232 ! |
|
233 |
|
234 formatArgCountFor:aFormatString |
|
235 "Return the number of arguments required/produced, |
|
236 if the argument is interpreted as a printf/scanf format control string." |
|
237 |
|
238 |nonConsecutive count| |
|
239 |
|
240 nonConsecutive := true. |
|
241 count := 0. |
|
242 aFormatString do:[:c | |
|
243 c == $% ifTrue:[ |
|
244 nonConsecutive ifTrue:[ |
|
245 count := count + 1. |
|
246 nonConsecutive := false |
|
247 ] ifFalse:[ |
|
248 count := count - 1. |
|
249 nonConsecutive := true |
|
250 ] |
|
251 ] ifFalse:[ |
|
252 nonConsecutive := true |
|
253 ] |
|
254 ]. |
|
255 ^ count |
90 ! ! |
256 ! ! |
91 |
257 |
92 !PrintfScanf methodsFor:'printing'! |
258 !PrintfScanf methodsFor:'printing'! |
93 |
259 |
94 printArgFrom:inStream to:outStream arguments:argStream |
260 printArgFrom:inStream to:outStream arguments:argStream |
276 outStream nextPut: char |
442 outStream nextPut: char |
277 ] ifTrue: [ |
443 ] ifTrue: [ |
278 self printArgFrom:inStream to:outStream arguments:argStream |
444 self printArgFrom:inStream to:outStream arguments:argStream |
279 ] |
445 ] |
280 ] |
446 ] |
281 ! ! |
|
282 |
|
283 !PrintfScanf methodsFor:'queries'! |
|
284 |
|
285 absDecimalPrintFloat:aFloat on:aStream digits:digits |
|
286 "Place a string representation of the receiver on <aStream> using <digits> significant digits, using decimal notation." |
|
287 |
|
288 |exp x fuzz i| |
|
289 |
|
290 "x is myself normalized to (1.0, 10.0), exp is my exponent" |
|
291 exp := aFloat abs < 1.0 ifTrue:[ |
|
292 (10.0 / aFloat abs) log floor negated |
|
293 ] ifFalse:[ |
|
294 aFloat abs log floor |
|
295 ]. |
|
296 x := aFloat abs / (10.0 raisedTo:exp). |
|
297 fuzz := 10.0 raisedTo:1 - digits. |
|
298 x := 0.5 * fuzz + x. |
|
299 x >= 10.0 ifTrue:[ |
|
300 "check if rounding has unnormalized x" |
|
301 x := x / 10.0. |
|
302 exp := exp + 1 |
|
303 ]. |
|
304 exp < 0 ifTrue:[ |
|
305 1 to:1 - exp do:[:j | |
|
306 aStream nextPut:('0.000000000000' at:j) |
|
307 ] |
|
308 ]. |
|
309 [ x >= fuzz ] whileTrue:[ |
|
310 "use fuzz to track significance" |
|
311 i := x truncated. |
|
312 aStream nextPut:(48 + i) asCharacter. |
|
313 x := (x - i) * 10.0. |
|
314 fuzz := fuzz * 10.0. |
|
315 exp := exp - 1. |
|
316 exp = -1 ifTrue:[ |
|
317 aStream nextPut:$. |
|
318 ] |
|
319 ]. |
|
320 [ exp >= -1 ] whileTrue:[ |
|
321 aStream nextPut:$0. |
|
322 exp := exp - 1. |
|
323 exp = -1 ifTrue:[ |
|
324 aStream nextPut:$. |
|
325 ] |
|
326 ] |
|
327 ! |
|
328 |
|
329 absPrintFloat:aFloat on:aStream digits:digits |
|
330 "Place a string representation of the receiver on <aStream> using <digits> significant digits." |
|
331 |
|
332 (aFloat < 1.0e6 and:[ aFloat > 1.0e-4 ]) ifTrue:[ |
|
333 self |
|
334 absDecimalPrintFloat:aFloat |
|
335 on:aStream |
|
336 digits:digits |
|
337 ] ifFalse:[ |
|
338 aFloat |
|
339 absScientificPrintFloat:aFloat |
|
340 on:aStream |
|
341 digits:digits |
|
342 ] |
|
343 ! |
|
344 |
|
345 absScientificPrintFloat:aFloat on:aStream digits:digits |
|
346 "Place a string representation of the receiver on <aStream> using <digits> significant digits, using scientific notation." |
|
347 |
|
348 |exp fuzz x q i| |
|
349 |
|
350 "x is myself normalized to [1.0, 10.0), exp is my exponent" |
|
351 exp := aFloat abs < 1.0 ifTrue:[ |
|
352 (10.0 / aFloat abs) log floor negated |
|
353 ] ifFalse:[ |
|
354 aFloat abs log floor |
|
355 ]. |
|
356 x := aFloat abs / (10.0 raisedTo:exp). |
|
357 fuzz := 10.0 raisedTo:1 - digits. |
|
358 x := 0.5 * fuzz + x. |
|
359 x >= 10.0 ifTrue:[ "check if rounding has unnormalized x" |
|
360 x := x / 10.0. |
|
361 exp := exp + 1 |
|
362 ]. |
|
363 q := exp. |
|
364 exp := 0. |
|
365 [ x >= fuzz ] whileTrue:[ |
|
366 "use fuzz to track significance" |
|
367 i := x truncated. |
|
368 aStream nextPut:(48 + i) asCharacter. |
|
369 x := (x - i) * 10.0. |
|
370 fuzz := fuzz * 10.0. |
|
371 exp := exp - 1. |
|
372 exp = -1 ifTrue:[ |
|
373 aStream nextPut:$. |
|
374 ] |
|
375 ]. |
|
376 [ exp >= -1 ] whileTrue:[ |
|
377 aStream nextPut:$0. |
|
378 exp := exp - 1. |
|
379 exp = -1 ifTrue:[ |
|
380 aStream nextPut:$. |
|
381 ] |
|
382 ]. |
|
383 aStream nextPut:$e. |
|
384 q printOn:aStream |
|
385 ! |
|
386 |
|
387 formatArgCountFor:aFormatString |
|
388 "Return the number of arguments required/produced, |
|
389 if the argument is interpreted as a printf/scanf format control string." |
|
390 |
|
391 |nonConsecutive count| |
|
392 |
|
393 nonConsecutive := true. |
|
394 count := 0. |
|
395 aFormatString do:[:c | |
|
396 c == $% ifTrue:[ |
|
397 nonConsecutive ifTrue:[ |
|
398 count := count + 1. |
|
399 nonConsecutive := false |
|
400 ] ifFalse:[ |
|
401 count := count - 1. |
|
402 nonConsecutive := true |
|
403 ] |
|
404 ] ifFalse:[ |
|
405 nonConsecutive := true |
|
406 ] |
|
407 ]. |
|
408 ^ count |
|
409 ! ! |
447 ! ! |
410 |
448 |
411 !PrintfScanf methodsFor:'scanning'! |
449 !PrintfScanf methodsFor:'scanning'! |
412 |
450 |
413 scanArgFrom:dataStream to:collection format:format |
451 scanArgFrom:dataStream to:collection format:format |