#FEATURE by exept
authorClaus Gittinger <cg@exept.de>
Sat, 31 Aug 2019 10:30:08 +0200
changeset 5192 674ac6172b1f
parent 5191 16a20c9f63dd
child 5193 b0a97940f538
#FEATURE by exept class: PrintfScanf class comment/format in: #format_printf changed: #printArgFrom:to:arguments: handle + and space flag for infinity.
PrintfScanf.st
--- a/PrintfScanf.st	Fri Aug 30 02:23:07 2019 +0200
+++ b/PrintfScanf.st	Sat Aug 31 10:30:08 2019 +0200
@@ -131,50 +131,46 @@
 "
     Printf Format specifier:
     
-        required: leading '%'
+    required: leading '%'
         optional: '-' (POSIX refers to this as the <<flags>>)
-        optional: positive number or '*' (POSIX <<width>>)
-        optional: period followed by positive number or * (POSIX <<precision>>)
-        optional: an h or l to indicate size of data (POSIX <<length>>)
-        required: character describing output behavior (POSIX <<conversion specifier>>)
+        optional: positive number or '*' (POSIX: <<width>>)
+        optional: period followed by positive number or * (POSIX: <<precision>>)
+        optional: an h or l to indicate size of data (POSIX: <<length>>)
+        required: character describing output behavior (POSIX: <<conversion specifier>>)
 
     Various implementations of printf have added different functionality.
 
     ANSI standards up through C99:
-
         more flags '+' ' ' '0' '#'
         more lengths 'L' 'hh' 'll' 'j' 'z' 't'
         more conversions 'F' 'a' 'A' 'n'
 
     The POSIX specification of printf added:
-
         positional parameters to identify argument indices
         more flags ''' (single quote)
         more conversions 'C' 'S'
         clarifications regarding corner cases and 'undefined behavior'
 
     BSD implementations added:
-
         more lengths 'q'
         more conversions 'D' 'U' 'O'
 
     glibc (GNU) added:
-
         more lengths 'Z'
         more conversions 'm'
 
     Windows C Runtime (CRT) added:
-
         more lengths 'I' 'I32' 'I64' 'w'
 
-    glibc and CRT both added 'Z'. 
-    glibc uses 'Z' for the length size_t. 
-    CRT uses Z as a conversion for length-prefixed strings. 
+    glibc and CRT both added length 'Z'. 
+        glibc uses 'Z' for the length size_t. 
+        CRT uses Z as a conversion for length-prefixed strings. 
     This implementation takes the former approach, handling 'Z' in the same way as 'z'.
 
     BSD and IBM C library both added 'D'. 
-    BSD uses D as a conversion, namely as an alias of 'ld'. 
-    IBM uses 'D' for the length for _Decimal64, a decimal floating point type, in accordance with ISO/IEC TR 24732. 
+        BSD uses D as a conversion, namely as an alias of 'ld'. 
+        IBM uses 'D' for the length for _Decimal64, a decimal floating point type, 
+        in accordance with ISO/IEC TR 24732. 
     This implementation takes the former approach.
 
     ================================================================
@@ -198,7 +194,7 @@
         'g'     'e' or 'f', whichever looks more appropriate (based on value)
         'i'     integer (alias for 'd')
         'j'     (not implemented) JSON format
-        'n'     (not implemented) stores number of characters written into arg 
+        'n'     (not implemented) stores number of characters written so far into arg 
         'o'     base-8 octal
         'p'     (not implemented) pointer 
         's'     string
@@ -209,13 +205,12 @@
         'X'     base-16 hex upper case
 
     Parameter selection (not implemented):
-
         <n>$    take n'th parameter
 
     Dynamic width/precision (consumed in order as presented):
-
         *       take width/parameter from next argument
 
+    Examples:
         PrintfScanf printf:'|%d|'  arguments:{ 123 }         -> '|123|'
         PrintfScanf printf:'|%5d|' arguments:{ 123 }         -> '|  123|'
         PrintfScanf printf:'|%-5d|' arguments:{ 123 }        -> '|123  |'
@@ -229,7 +224,6 @@
 
 
     Negative width will fill at the right:
-
         PrintfScanf printf:'|%5s|'  arguments:{ 'abc' }      -> '|  abc|'
         PrintfScanf printf:'|%-5s|' arguments:{ 'abc' }      -> '|abc  |'
         PrintfScanf printf:'|%-*s|' arguments:{ 5 . 'abc' }  -> '|abc  |'
@@ -241,7 +235,6 @@
         PrintfScanf printf:'|%-*f|'  arguments:{ -8 . 1.234 } -> '|1.234   |'
 
     A Zero as fill character:
-
         PrintfScanf printf:'|%05s|'  arguments:{ 'abc' }     -> '|00abc|'
         PrintfScanf printf:'|%-05s|' arguments:{ 'abc' }     -> '|abc00|'
 
@@ -251,7 +244,6 @@
         PrintfScanf printf:'|%-*f|'  arguments:{ -8 . 1.234 } -> '|1.234   |'
 
     Case of float-format character only affects printing of Nan and infinity:
-    
         PrintfScanf printf:'%f' argument:1.234    
         PrintfScanf printf:'%F' argument:1.234    
         PrintfScanf printf:'%f' argument:(Float NaN)    
@@ -458,6 +450,10 @@
             "Ignore ptrdiff-length specifier."
             more := true.
         ].
+        char == $z ifTrue:[
+            "Ignore size_t-length specifier."
+            more := true.
+        ].
         more ifTrue:[
             formatStream next.  
             char := formatStream peek.
@@ -477,6 +473,15 @@
             (char isUppercase) 
                 ifTrue:[ argString := argString asUppercase ] 
                 ifFalse:[ argString := argString asLowercase ].
+            arg positive ifTrue:[
+                plus ifTrue: [
+                    argString := '+', argString
+                ] ifFalse:[
+                    spaceIfPositive ifTrue: [
+                        argString := ' ', argString
+                    ].
+                ].
+            ].
         ] ifFalse:[
             argString := WriteStream on:''.
             (char == $g or:[char == $G]) ifTrue: [ 
@@ -525,7 +530,7 @@
     char == $c ifTrue:[
         arg := nextArg value.
         arg isString ifTrue:[
-            arg := arg first
+            arg := arg first asString
         ] ifFalse:[    
             arg := arg asCharacter asString
         ].