Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions py/mpprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,20 @@
#include "py/formatfloat.h"
#endif

static const char pad_spaces[] = " ";
static const char pad_zeroes[] = "0000000000000000";
static const char pad_spaces[16] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
#define pad_spaces_size (sizeof(pad_spaces))
static const char pad_common[23] = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '_', '0', '0', '0', ',', '0', '0'};
// The contents of pad_common is arranged to provide the following padding
// strings with minimal flash size:
// 0000000000000000 <- pad_zeroes
// 0000_000 <- pad_zeroes_underscore (offset: 12, size 5)
// 000,00 <- pad_zeroes_comma (offset: 17, size 4)
#define pad_zeroes (pad_common + 0)
#define pad_zeroes_size (16)
#define pad_zeroes_underscore (pad_common + 12)
#define pad_zeroes_underscore_size (5)
#define pad_zeroes_comma (pad_common + 17)
#define pad_zeroes_comma_size (4)

static void plat_print_strn(void *env, const char *str, size_t len) {
(void)env;
Expand All @@ -65,13 +77,30 @@ int mp_print_strn(const mp_print_t *print, const char *str, size_t len, unsigned
int pad_size;
int total_chars_printed = 0;
const char *pad_chars;
char grouping = flags >> PF_FLAG_SEP_POS;

if (!fill || fill == ' ') {
pad_chars = pad_spaces;
pad_size = sizeof(pad_spaces) - 1;
} else if (fill == '0') {
pad_size = pad_spaces_size;
} else if (fill == '0' && !grouping) {
pad_chars = pad_zeroes;
pad_size = sizeof(pad_zeroes) - 1;
pad_size = pad_zeroes_size;
} else if (fill == '0') {
if (grouping == '_') {
pad_chars = pad_zeroes_underscore;
pad_size = pad_zeroes_underscore_size;
} else {
pad_chars = pad_zeroes_comma;
pad_size = pad_zeroes_comma_size;
}
// The result will never start with a grouping character. An extra leading zero is added.
// width is dead after this so we can use it in calculation
if (width % pad_size == 0) {
pad++;
width++;
}
// position the grouping character correctly within the pad repetition
pad_chars += pad_size - 1 - width % pad_size;
} else {
// Other pad characters are fairly unusual, so we'll take the hit
// and output them 1 at a time.
Expand Down
9 changes: 9 additions & 0 deletions tests/basics/string_format_sep.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
try:
"%d" % 1
except TypeError:
print("SKIP")
raise SystemExit

for v in (0, 0x10, 0x1000, -0x10, -0x1000):
for sz in range(1, 12): print(("{:0%d,d}" % sz).format(v))
for sz in range(1, 12): print(("{:0%d_x}" % sz).format(v))
11 changes: 11 additions & 0 deletions tests/cpydiff/types_str_formatsep_float.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""
categories: Types,str
description: MicroPython accepts but does not properly implement the "," or "_" grouping character for float values
cause: To reduce code size, MicroPython does not implement this combination. Grouping characters will not appear in the number's significant digits and will appear at incorrect locations in leading zeros.
workaround: Do not use a format string like ``{:,f}`` if exact CPython compatibility is required.
"""

print("{:,f}".format(3141.159))
print("{:_f}".format(3141.159))
print("{:011,.2f}".format(3141.159))
print("{:011_.2f}".format(3141.159))
Loading