Commit 6756a37a authored by Dave Hylands's avatar Dave Hylands
Browse files

Implements most of str.modulo

The alternate form for floating point doesn't work yet.
The %(name)s form doesn't work yet.
parent 5bf565e3
...@@ -894,32 +894,162 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t ...@@ -894,32 +894,162 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t
assert(MP_OBJ_IS_STR(pattern)); assert(MP_OBJ_IS_STR(pattern));
GET_STR_DATA_LEN(pattern, str, len); GET_STR_DATA_LEN(pattern, str, len);
const byte *start_str = str;
int arg_i = 0; int arg_i = 0;
vstr_t *vstr = vstr_new(); vstr_t *vstr = vstr_new();
pfenv_t pfenv_vstr;
pfenv_vstr.data = vstr;
pfenv_vstr.print_strn = pfenv_vstr_add_strn;
for (const byte *top = str + len; str < top; str++) { for (const byte *top = str + len; str < top; str++) {
if (*str != '%') {
vstr_add_char(vstr, *str);
continue;
}
if (++str >= top) {
break;
}
if (*str == '%') { if (*str == '%') {
if (++str >= top) { vstr_add_char(vstr, '%');
break; continue;
} }
if (*str == '%') { if (arg_i >= n_args) {
vstr_add_char(vstr, '%'); nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "not enough arguments for format string"));
}
int flags = 0;
char fill = ' ';
bool alt = false;
while (str < top) {
if (*str == '-') flags |= PF_FLAG_LEFT_ADJUST;
else if (*str == '+') flags |= PF_FLAG_SHOW_SIGN;
else if (*str == ' ') flags |= PF_FLAG_SPACE_SIGN;
else if (*str == '#') alt = true;
else if (*str == '0') {
flags |= PF_FLAG_PAD_AFTER_SIGN;
fill = '0';
} else break;
str++;
}
// parse width, if it exists
int width = 0;
if (str < top) {
if (*str == '*') {
width = mp_obj_get_int(args[arg_i++]);
str++;
} else { } else {
if (arg_i >= n_args) { for (; str < top && '0' <= *str && *str <= '9'; str++) {
nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "not enough arguments for format string")); width = width * 10 + *str - '0';
} }
switch (*str) { }
case 's': }
mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[arg_i], PRINT_STR); int prec = -1;
break; if (str < top && *str == '.') {
case 'r': if (++str < top) {
mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[arg_i], PRINT_REPR); if (*str == '*') {
prec = mp_obj_get_int(args[arg_i++]);
str++;
} else {
prec = 0;
for (; str < top && '0' <= *str && *str <= '9'; str++) {
prec = prec * 10 + *str - '0';
}
}
}
}
if (str >= top) {
nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "incomplete format"));
}
mp_obj_t arg = args[arg_i];
switch (*str) {
case 'c':
if (MP_OBJ_IS_STR(arg)) {
uint len;
const char *s = mp_obj_str_get_data(arg, &len);
if (len != 1) {
nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "%c requires int or char"));
break; break;
}
pfenv_print_strn(&pfenv_vstr, s, 1, flags, ' ', width);
break;
}
if (arg_looks_integer(arg)) {
char ch = mp_obj_get_int(arg);
pfenv_print_strn(&pfenv_vstr, &ch, 1, flags, ' ', width);
break;
}
#if MICROPY_ENABLE_FLOAT
// This is what CPython reports, so we report the same.
if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) {
nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "integer argument expected, got float"));
}
#endif
nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "an integer is required"));
break;
case 'd':
case 'i':
case 'u':
pfenv_print_int(&pfenv_vstr, mp_obj_get_int(arg), 1, 10, 'a', flags, fill, width);
break;
#if MICROPY_ENABLE_FLOAT
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
pfenv_print_float(&pfenv_vstr, mp_obj_get_float(arg), *str, flags, fill, width, prec);
break;
#endif
case 'o':
if (alt) {
flags |= PF_FLAG_SHOW_PREFIX;
}
pfenv_print_int(&pfenv_vstr, mp_obj_get_int(arg), 1, 8, 'a', flags, fill, width);
break;
case 'r':
case 's':
{
vstr_t *arg_vstr = vstr_new();
mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf,
arg_vstr, arg, *str == 'r' ? PRINT_REPR : PRINT_STR);
uint len = vstr_len(arg_vstr);
if (prec < 0) {
prec = len;
}
if (len > prec) {
len = prec;
} }
arg_i++; pfenv_print_strn(&pfenv_vstr, vstr_str(arg_vstr), len, flags, ' ', width);
vstr_free(arg_vstr);
break;
} }
} else {
vstr_add_char(vstr, *str); case 'x':
if (alt) {
flags |= PF_FLAG_SHOW_PREFIX;
}
pfenv_print_int(&pfenv_vstr, mp_obj_get_int(arg), 1, 16, 'a', flags, fill, width);
break;
case 'X':
if (alt) {
flags |= PF_FLAG_SHOW_PREFIX;
}
pfenv_print_int(&pfenv_vstr, mp_obj_get_int(arg), 1, 16, 'A', flags, fill, width);
break;
default:
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"unsupported format character '%c' (0x%x) at index %d",
*str, *str, str - start_str));
} }
arg_i++;
} }
if (arg_i != n_args) { if (arg_i != n_args) {
......
...@@ -20,3 +20,25 @@ try: ...@@ -20,3 +20,25 @@ try:
print("=%s=" % (1, 2)) print("=%s=" % (1, 2))
except TypeError: except TypeError:
print("TypeError") print("TypeError")
print("%c" % 48)
print("%c" % 'a')
print("%10s" % 'abc')
print("%-10s" % 'abc')
print("%d" % 10)
print("%+d" % 10)
print("% d" % 10)
print("%d" % -10)
print("%x" % 18)
print("%o" % 18)
print("%X" % 18)
print("%#x" % 18)
print("%#X" % 18)
print("%#6x" % 18)
print("%#06x" % 18)
print("%e" % 1.23456)
print("%E" % 1.23456)
print("%f" % 1.23456)
print("%F" % 1.23456)
print("%g" % 1.23456)
print("%G" % 1.23456)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment