@@ -30,7 +30,7 @@ static void s_mp_str_reverse(char *s, int len)
3030 }
3131}
3232static 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) */
3434static int s_mp_print_mp_digit_binary (mp_digit number , mp_digit base , bool prefix , char * buffer )
3535{
3636 mp_digit cp , digit ;
@@ -63,14 +63,19 @@ static int s_mp_print_mp_digit_binary(mp_digit number, mp_digit base, bool prefi
6363 return i ;
6464}
6565
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+
6671#include <printf.h>
6772static int s_mp_print_mp_int (FILE * stream , const struct printf_info * info , const void * const * args )
6873{
6974 mp_err err = MP_OKAY ;
7075 const mp_int * a ;
7176 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 ;
7479 size_t size , written , extra_len = 0u ;
7580
7681 /* 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
8893 base = 10 ;
8994 }
9095
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-
11296 /* Get some estimate of the size of "a" in the given base */
11397 if ((err = mp_radix_size_overestimate (a , base , & size )) != MP_OKAY ) {
11498 return -1 ;
@@ -123,6 +107,14 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
123107 extra_len ++ ;
124108 }
125109
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+
126118 buf = MP_MALLOC (size + extra_len );
127119 if (buf == NULL ) {
128120 return -1 ;
@@ -138,6 +130,7 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
138130 buf -- ;
139131 }
140132
133+
141134 if ((err = mp_to_radix (a , buf , size , & written , base )) != MP_OKAY ) {
142135 MP_FREE (start_buf , size + extra_len );
143136 return -1 ;
@@ -146,34 +139,106 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
146139 if (mp_isneg (a )) {
147140 start_buf [idx ++ ] = '-' ;
148141 } else {
142+ /* For alignment of numbers with and without a sign. */
149143 if (info -> space ) {
150144 start_buf [idx ++ ] = ' ' ;
145+ /* Always print the sign (default is for negative numbers only) */
151146 } else if (info -> showsign ) {
152147 start_buf [idx ++ ] = '+' ;
153148 }
154149 }
155150
151+ /* "info->alt" holds the information if a prefix is wanted */
156152 if ((base != 10 ) && (info -> alt == 1u )) {
157153 start_buf [idx ++ ] = '0' ;
158154 switch (base ) {
159155 case 2 :
160- start_buf [idx ] = 'b' ;
156+ /* Non-standard extension */
157+ start_buf [idx ++ ] = 'b' ;
161158 break ;
162159 case 8 :
163- start_buf [idx ] = 'o' ;
160+ start_buf [idx ++ ] = 'o' ;
164161 break ;
165162 case 16 :
166- start_buf [idx ] = 'x' ;
163+ start_buf [idx ++ ] = 'x' ;
167164 break ;
168165 case 64 :
169- start_buf [idx ] = '@' ;
166+ /* Non-standard extension */
167+ start_buf [idx ++ ] = '@' ;
170168 break ;
171169 }
172170 }
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+ }
174239
175240 MP_FREE (start_buf , size + extra_len );
176- return len ;
241+ return length_printed ;
177242}
178243
179244#include <inttypes.h>
0 commit comments