summaryrefslogtreecommitdiffstatshomepage
path: root/py/pfenv.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/pfenv.c')
-rw-r--r--py/pfenv.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/py/pfenv.c b/py/pfenv.c
new file mode 100644
index 0000000000..07f35c335c
--- /dev/null
+++ b/py/pfenv.c
@@ -0,0 +1,208 @@
+#include <stdint.h>
+#include <string.h>
+
+///#include "std.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "pfenv.h"
+
+#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
+#include <stdio.h>
+#endif
+
+#if MICROPY_ENABLE_FLOAT
+#include "formatfloat.h"
+#endif
+
+#define PF_PAD_SIZE 16
+static const char *pad_spaces = " ";
+static const char *pad_zeroes = "0000000000000000";
+
+void pfenv_vstr_add_strn(void *data, const char *str, unsigned int len){
+ vstr_add_strn(data, str, len);
+}
+
+int pfenv_print_strn(const pfenv_t *pfenv, const char *str, unsigned int len, int flags, char fill, int width) {
+ int left_pad = 0;
+ int right_pad = 0;
+ int pad = width - len;
+ char pad_fill[PF_PAD_SIZE];
+ const char *pad_chars;
+
+ if (!fill || fill == ' ' ) {
+ pad_chars = pad_spaces;
+ } else if (fill == '0') {
+ pad_chars = pad_zeroes;
+ } else {
+ memset(pad_fill, fill, PF_PAD_SIZE);
+ pad_chars = pad_fill;
+ }
+
+ if (flags & PF_FLAG_CENTER_ADJUST) {
+ left_pad = pad / 2;
+ right_pad = pad - left_pad;
+ } else if (flags & PF_FLAG_LEFT_ADJUST) {
+ right_pad = pad;
+ } else {
+ left_pad = pad;
+ }
+
+ if (left_pad) {
+ while (left_pad > 0) {
+ int p = left_pad;
+ if (p > PF_PAD_SIZE)
+ p = PF_PAD_SIZE;
+ pfenv->print_strn(pfenv->data, pad_chars, p);
+ left_pad -= p;
+ }
+ }
+ pfenv->print_strn(pfenv->data, str, len);
+ if (right_pad) {
+ while (right_pad > 0) {
+ int p = right_pad;
+ if (p > PF_PAD_SIZE)
+ p = PF_PAD_SIZE;
+ pfenv->print_strn(pfenv->data, pad_chars, p);
+ right_pad -= p;
+ }
+ }
+ return len;
+}
+
+// enough room for 32 signed number
+#define INT_BUF_SIZE (16)
+
+int pfenv_print_int(const pfenv_t *pfenv, unsigned int x, int sgn, int base, int base_char, int flags, char fill, int width) {
+ char sign = 0;
+ if (sgn) {
+ if ((int)x < 0) {
+ sign = '-';
+ x = -x;
+ } else if (flags & PF_FLAG_SHOW_SIGN) {
+ sign = '+';
+ } else if (flags & PF_FLAG_SPACE_SIGN) {
+ sign = ' ';
+ }
+ }
+
+ char buf[INT_BUF_SIZE];
+ char *b = buf + INT_BUF_SIZE;
+
+ if (x == 0) {
+ *(--b) = '0';
+ } else {
+ do {
+ int c = x % base;
+ x /= base;
+ if (c >= 10) {
+ c += base_char - 10;
+ } else {
+ c += '0';
+ }
+ *(--b) = c;
+ } while (b > buf && x != 0);
+ }
+
+ char prefix_char = '\0';
+
+ if (flags & PF_FLAG_SHOW_PREFIX) {
+ if (base == 2) {
+ prefix_char = base_char + 'b' - 'a';
+ } else if (base == 8) {
+ prefix_char = base_char + 'o' - 'a';
+ } else if (base == 16) {
+ prefix_char = base_char + 'x' - 'a';
+ }
+ }
+
+ int len = 0;
+ if (flags & PF_FLAG_PAD_AFTER_SIGN) {
+ if (sign) {
+ len += pfenv_print_strn(pfenv, &sign, 1, flags, fill, 1);
+ width--;
+ }
+ if (prefix_char) {
+ len += pfenv_print_strn(pfenv, "0", 1, flags, fill, 1);
+ len += pfenv_print_strn(pfenv, &prefix_char, 1, flags, fill, 1);
+ width -= 2;
+ }
+ } else {
+ if (prefix_char && b > &buf[1]) {
+ *(--b) = prefix_char;
+ *(--b) = '0';
+ }
+ if (sign && b > buf) {
+ *(--b) = sign;
+ }
+ }
+
+ len += pfenv_print_strn(pfenv, b, buf + INT_BUF_SIZE - b, flags, fill, width);
+ return len;
+}
+
+#if MICROPY_ENABLE_FLOAT
+int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec) {
+ char buf[32];
+ char sign = '\0';
+ int chrs = 0;
+
+ if (flags & PF_FLAG_SHOW_SIGN) {
+ sign = '+';
+ }
+ else
+ if (flags & PF_FLAG_SPACE_SIGN) {
+ sign = ' ';
+ }
+ int len;
+#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
+ len = format_float(f, buf, sizeof(buf), fmt, prec, sign);
+#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
+ char fmt_buf[6];
+ char *fmt_s = fmt_buf;
+
+ *fmt_s++ = '%';
+ if (sign) {
+ *fmt_s++ = sign;
+ }
+ *fmt_s++ = '.';
+ *fmt_s++ = '*';
+ *fmt_s++ = fmt;
+ *fmt_s = '\0';
+
+ len = snprintf(buf, sizeof(buf), fmt_buf, prec, f);
+#else
+#error Unknown MICROPY FLOAT IMPL
+#endif
+ char *s = buf;
+
+ if ((flags & PF_FLAG_ADD_PERCENT) && (len + 1) < sizeof(buf)) {
+ buf[len++] = '%';
+ buf[len] = '\0';
+ }
+
+ // buf[0] < '0' returns true if the first character is space, + or -
+ if ((flags & PF_FLAG_PAD_AFTER_SIGN) && buf[0] < '0') {
+ // We have a sign character
+ s++;
+ if (*s <= '9' || (flags & PF_FLAG_PAD_NAN_INF)) {
+ // We have a number, or we have a inf/nan and PAD_NAN_INF is set
+ // With '{:06e}'.format(float('-inf')) you get '-00inf'
+ chrs += pfenv_print_strn(pfenv, &buf[0], 1, 0, 0, 1);
+ width--;
+ len--;
+ }
+ }
+
+ if (*s > 'A' && (flags & PF_FLAG_PAD_NAN_INF) == 0) {
+ // We have one of the inf or nan variants, suppress zero fill.
+ // With printf, if you use: printf("%06e", -inf) then you get " -inf"
+ // so suppress the zero fill.
+ fill = ' ';
+ }
+ chrs += pfenv_print_strn(pfenv, s, len, flags, fill, width);
+
+ return chrs;
+}
+#endif