@@ -30,7 +30,7 @@ static void s_mp_str_reverse(char *s, int len)
30
30
}
31
31
}
32
32
static const char s_mp_base64 [] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/" ;
33
- /* TODO: formatting. Precision and thousands separators (latter needs locale environment, so prob. not) */
33
+ /* TODO: thousands separators (needs locale environment, so prob. not) */
34
34
static int s_mp_print_mp_digit_binary (mp_digit number , mp_digit base , bool prefix , char * buffer )
35
35
{
36
36
mp_digit cp , digit ;
@@ -63,14 +63,19 @@ static int s_mp_print_mp_digit_binary(mp_digit number, mp_digit base, bool prefi
63
63
return i ;
64
64
}
65
65
66
+ /* Function for the output to a stream, adjust to your needs */
67
+ #ifndef MP_FPUTC
68
+ #define MP_FPUTC (c , stream ) fputc((c), (stream))
69
+ #endif
70
+
66
71
#include <printf.h>
67
72
static int s_mp_print_mp_int (FILE * stream , const struct printf_info * info , const void * const * args )
68
73
{
69
74
mp_err err = MP_OKAY ;
70
75
const mp_int * a ;
71
76
char * buf , * start_buf ;
72
- char * prefixed_zero = "" ;
73
- int base , len , idx = 0 ;
77
+ int base , length_number , min_width ;
78
+ int idx = 0 , fill_zeros = 0 , length_printed = 0 , i ;
74
79
size_t size , written , extra_len = 0u ;
75
80
76
81
/* Fiddle our bigint out of the argument list */
@@ -88,27 +93,6 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
88
93
base = 10 ;
89
94
}
90
95
91
- if (mp_iszero (a )) {
92
- if (info -> alt == 1u ) {
93
- switch (base ) {
94
- case 2 :
95
- prefixed_zero = "0b0" ;
96
- break ;
97
- case 8 :
98
- prefixed_zero = "0o0" ;
99
- break ;
100
- case 16 :
101
- prefixed_zero = "0x0" ;
102
- break ;
103
- case 64 :
104
- prefixed_zero = "0@0" ;
105
- break ;
106
- }
107
- return fprintf (stream , "%*s" , (info -> left ? - info -> width : info -> width ), prefixed_zero );
108
- }
109
- return fprintf (stream , "%*s" , (info -> left ? - info -> width : info -> width ), "0" );
110
- }
111
-
112
96
/* Get some estimate of the size of "a" in the given base */
113
97
if ((err = mp_radix_size_overestimate (a , base , & size )) != MP_OKAY ) {
114
98
return -1 ;
@@ -123,6 +107,14 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
123
107
extra_len ++ ;
124
108
}
125
109
110
+ /* Minimum length, fill with leading zeros if not reached */
111
+ if (info -> prec > 0 ) {
112
+ if (info -> prec > (int )size ) {
113
+ /* exact number is in written later */
114
+ size = (size_t )info -> prec ;
115
+ }
116
+ }
117
+
126
118
buf = MP_MALLOC (size + extra_len );
127
119
if (buf == NULL ) {
128
120
return -1 ;
@@ -138,6 +130,7 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
138
130
buf -- ;
139
131
}
140
132
133
+
141
134
if ((err = mp_to_radix (a , buf , size , & written , base )) != MP_OKAY ) {
142
135
MP_FREE (start_buf , size + extra_len );
143
136
return -1 ;
@@ -146,34 +139,106 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
146
139
if (mp_isneg (a )) {
147
140
start_buf [idx ++ ] = '-' ;
148
141
} else {
142
+ /* For alignment of numbers with and without a sign. */
149
143
if (info -> space ) {
150
144
start_buf [idx ++ ] = ' ' ;
145
+ /* Always print the sign (default is for negative numbers only) */
151
146
} else if (info -> showsign ) {
152
147
start_buf [idx ++ ] = '+' ;
153
148
}
154
149
}
155
150
151
+ /* "info->alt" holds the information if a prefix is wanted */
156
152
if ((base != 10 ) && (info -> alt == 1u )) {
157
153
start_buf [idx ++ ] = '0' ;
158
154
switch (base ) {
159
155
case 2 :
160
- start_buf [idx ] = 'b' ;
156
+ /* Non-standard extension */
157
+ start_buf [idx ++ ] = 'b' ;
161
158
break ;
162
159
case 8 :
163
- start_buf [idx ] = 'o' ;
160
+ start_buf [idx ++ ] = 'o' ;
164
161
break ;
165
162
case 16 :
166
- start_buf [idx ] = 'x' ;
163
+ start_buf [idx ++ ] = 'x' ;
167
164
break ;
168
165
case 64 :
169
- start_buf [idx ] = '@' ;
166
+ /* Non-standard extension */
167
+ start_buf [idx ++ ] = '@' ;
170
168
break ;
171
169
}
172
170
}
173
- len = fprintf (stream , "%*s" , (info -> left ? - info -> width : info -> width ), start_buf );
171
+
172
+ /* As mentioned above: the minus sign gets overwritten. */
173
+ if (mp_isneg (a )) {
174
+ written -- ;
175
+ }
176
+
177
+ /* Length of the number with the prefix but without the leading zeros (prec) */
178
+ length_number = idx + (int )written - 1 ;
179
+
180
+ /* Include minimum length if set*/
181
+ if (info -> prec > length_number ) {
182
+ min_width = info -> width - info -> prec ;
183
+ } else {
184
+ min_width = info -> width - length_number ;
185
+ }
186
+
187
+ /* Print padding to the left for alignment to the right */
188
+ if (!(info -> left ) && (min_width > 0 )) {
189
+ while (min_width -- ) {
190
+ if (info -> pad != 0 ) {
191
+ /* TODO: The type of info->pad is wchar_t, make a note in
192
+ the docs not to use a wchar_t pad */
193
+ MP_FPUTC ((int )(info -> pad ),stream );
194
+ length_printed ++ ;
195
+ } else {
196
+ MP_FPUTC (' ' ,stream );
197
+ length_printed ++ ;
198
+ }
199
+ }
200
+ }
201
+
202
+ /* Print the prefix */
203
+ for (i = 0 ; i < idx ; i ++ ) {
204
+ MP_FPUTC (start_buf [i ],stream );
205
+ length_printed ++ ;
206
+ }
207
+
208
+ /* Add leading zeros if set */
209
+ if (info -> prec > 0 ) {
210
+ /* Prefix length, if there is any, is in idx*/
211
+ fill_zeros = info -> prec - idx - (int )written + 1 ;
212
+ /* No truncating */
213
+ if (fill_zeros > 0 ) {
214
+ while (fill_zeros -- ) {
215
+ MP_FPUTC ('0' ,stream );
216
+ length_printed ++ ;
217
+ }
218
+ }
219
+ }
220
+
221
+ /* Print the number itself */
222
+ while (start_buf [idx ] != '\0' ) {
223
+ MP_FPUTC (start_buf [idx ++ ],stream );
224
+ length_printed ++ ;
225
+ }
226
+
227
+ /* Print padding to the right for alignment to the left */
228
+ if ((info -> left ) && (min_width > 0 )) {
229
+ while (min_width -- ) {
230
+ if (info -> pad != 0 ) {
231
+ MP_FPUTC ((int )(info -> pad ),stream );
232
+ length_printed ++ ;
233
+ } else {
234
+ MP_FPUTC (' ' ,stream );
235
+ length_printed ++ ;
236
+ }
237
+ }
238
+ }
174
239
175
240
MP_FREE (start_buf , size + extra_len );
176
- return len ;
241
+ return length_printed ;
177
242
}
178
243
179
244
#include <inttypes.h>
0 commit comments