blob: 67835e43a34063fdfede32f7df50db94c6b229f8 [file] [log] [blame]
Dave Hylandsbaf6f142014-03-30 21:06:50 -07001#include <stdint.h>
2#include <string.h>
3
4///#include "std.h"
5#include "misc.h"
6#include "mpconfig.h"
7#include "qstr.h"
8#include "obj.h"
9#include "pfenv.h"
10
11#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
12#include <stdio.h>
13#endif
14
15#if MICROPY_ENABLE_FLOAT
16#include "formatfloat.h"
17#endif
18
Dave Hylands1c6b4b22014-04-01 11:59:31 -070019static const char pad_spaces[] = " ";
20static const char pad_zeroes[] = "0000000000000000";
Dave Hylandsbaf6f142014-03-30 21:06:50 -070021
22void pfenv_vstr_add_strn(void *data, const char *str, unsigned int len){
23 vstr_add_strn(data, str, len);
24}
25
26int pfenv_print_strn(const pfenv_t *pfenv, const char *str, unsigned int len, int flags, char fill, int width) {
27 int left_pad = 0;
28 int right_pad = 0;
29 int pad = width - len;
Dave Hylands1c6b4b22014-04-01 11:59:31 -070030 int pad_size;
Dave Hylandsbaf6f142014-03-30 21:06:50 -070031 const char *pad_chars;
32
33 if (!fill || fill == ' ' ) {
34 pad_chars = pad_spaces;
Dave Hylands1c6b4b22014-04-01 11:59:31 -070035 pad_size = sizeof(pad_spaces) - 1;
Dave Hylandsbaf6f142014-03-30 21:06:50 -070036 } else if (fill == '0') {
37 pad_chars = pad_zeroes;
Dave Hylands1c6b4b22014-04-01 11:59:31 -070038 pad_size = sizeof(pad_zeroes) - 1;
Dave Hylandsbaf6f142014-03-30 21:06:50 -070039 } else {
Dave Hylands1c6b4b22014-04-01 11:59:31 -070040 // Other pad characters are fairly unusual, so we'll take the hit
41 // and output them 1 at a time.
42 pad_chars = &fill;
43 pad_size = 1;
Dave Hylandsbaf6f142014-03-30 21:06:50 -070044 }
45
46 if (flags & PF_FLAG_CENTER_ADJUST) {
47 left_pad = pad / 2;
48 right_pad = pad - left_pad;
49 } else if (flags & PF_FLAG_LEFT_ADJUST) {
50 right_pad = pad;
51 } else {
52 left_pad = pad;
53 }
54
55 if (left_pad) {
56 while (left_pad > 0) {
57 int p = left_pad;
Dave Hylands1c6b4b22014-04-01 11:59:31 -070058 if (p > pad_size)
59 p = pad_size;
Dave Hylandsbaf6f142014-03-30 21:06:50 -070060 pfenv->print_strn(pfenv->data, pad_chars, p);
61 left_pad -= p;
62 }
63 }
64 pfenv->print_strn(pfenv->data, str, len);
65 if (right_pad) {
66 while (right_pad > 0) {
67 int p = right_pad;
Dave Hylands1c6b4b22014-04-01 11:59:31 -070068 if (p > pad_size)
69 p = pad_size;
Dave Hylandsbaf6f142014-03-30 21:06:50 -070070 pfenv->print_strn(pfenv->data, pad_chars, p);
71 right_pad -= p;
72 }
73 }
74 return len;
75}
76
Dave Hylands80359aa2014-04-01 11:01:55 -070077// 32-bits is 10 digits, add 3 for commas, 1 for sign, 1 for terminating null
78// We can use 16 characters for 32-bit and 32 characters for 64-bit
79#define INT_BUF_SIZE (sizeof(machine_int_t) * 4)
Dave Hylandsbaf6f142014-03-30 21:06:50 -070080
81int pfenv_print_int(const pfenv_t *pfenv, unsigned int x, int sgn, int base, int base_char, int flags, char fill, int width) {
82 char sign = 0;
83 if (sgn) {
84 if ((int)x < 0) {
85 sign = '-';
86 x = -x;
87 } else if (flags & PF_FLAG_SHOW_SIGN) {
88 sign = '+';
89 } else if (flags & PF_FLAG_SPACE_SIGN) {
90 sign = ' ';
91 }
92 }
93
94 char buf[INT_BUF_SIZE];
95 char *b = buf + INT_BUF_SIZE;
96
97 if (x == 0) {
98 *(--b) = '0';
99 } else {
100 do {
101 int c = x % base;
102 x /= base;
103 if (c >= 10) {
104 c += base_char - 10;
105 } else {
106 c += '0';
107 }
108 *(--b) = c;
109 } while (b > buf && x != 0);
110 }
111
112 char prefix_char = '\0';
113
114 if (flags & PF_FLAG_SHOW_PREFIX) {
115 if (base == 2) {
116 prefix_char = base_char + 'b' - 'a';
117 } else if (base == 8) {
118 prefix_char = base_char + 'o' - 'a';
119 } else if (base == 16) {
120 prefix_char = base_char + 'x' - 'a';
121 }
122 }
123
124 int len = 0;
125 if (flags & PF_FLAG_PAD_AFTER_SIGN) {
126 if (sign) {
127 len += pfenv_print_strn(pfenv, &sign, 1, flags, fill, 1);
128 width--;
129 }
130 if (prefix_char) {
131 len += pfenv_print_strn(pfenv, "0", 1, flags, fill, 1);
132 len += pfenv_print_strn(pfenv, &prefix_char, 1, flags, fill, 1);
133 width -= 2;
134 }
135 } else {
136 if (prefix_char && b > &buf[1]) {
137 *(--b) = prefix_char;
138 *(--b) = '0';
139 }
140 if (sign && b > buf) {
141 *(--b) = sign;
142 }
143 }
144
145 len += pfenv_print_strn(pfenv, b, buf + INT_BUF_SIZE - b, flags, fill, width);
146 return len;
147}
148
149#if MICROPY_ENABLE_FLOAT
150int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec) {
151 char buf[32];
152 char sign = '\0';
153 int chrs = 0;
154
155 if (flags & PF_FLAG_SHOW_SIGN) {
156 sign = '+';
157 }
158 else
159 if (flags & PF_FLAG_SPACE_SIGN) {
160 sign = ' ';
161 }
162 int len;
163#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
164 len = format_float(f, buf, sizeof(buf), fmt, prec, sign);
165#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
166 char fmt_buf[6];
167 char *fmt_s = fmt_buf;
168
169 *fmt_s++ = '%';
170 if (sign) {
171 *fmt_s++ = sign;
172 }
173 *fmt_s++ = '.';
174 *fmt_s++ = '*';
175 *fmt_s++ = fmt;
176 *fmt_s = '\0';
177
178 len = snprintf(buf, sizeof(buf), fmt_buf, prec, f);
179#else
180#error Unknown MICROPY FLOAT IMPL
181#endif
182 char *s = buf;
183
184 if ((flags & PF_FLAG_ADD_PERCENT) && (len + 1) < sizeof(buf)) {
185 buf[len++] = '%';
186 buf[len] = '\0';
187 }
188
189 // buf[0] < '0' returns true if the first character is space, + or -
190 if ((flags & PF_FLAG_PAD_AFTER_SIGN) && buf[0] < '0') {
191 // We have a sign character
192 s++;
193 if (*s <= '9' || (flags & PF_FLAG_PAD_NAN_INF)) {
194 // We have a number, or we have a inf/nan and PAD_NAN_INF is set
195 // With '{:06e}'.format(float('-inf')) you get '-00inf'
196 chrs += pfenv_print_strn(pfenv, &buf[0], 1, 0, 0, 1);
197 width--;
198 len--;
199 }
200 }
201
202 if (*s > 'A' && (flags & PF_FLAG_PAD_NAN_INF) == 0) {
203 // We have one of the inf or nan variants, suppress zero fill.
204 // With printf, if you use: printf("%06e", -inf) then you get " -inf"
205 // so suppress the zero fill.
206 fill = ' ';
207 }
208 chrs += pfenv_print_strn(pfenv, s, len, flags, fill, width);
209
210 return chrs;
211}
212#endif