Skip to content

Commit 87e07ea

Browse files
committed
py/objstr: For str.format, don't allocate on the heap for field name.
1 parent e3a29de commit 87e07ea

1 file changed

Lines changed: 23 additions & 23 deletions

File tree

py/objstr.c

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -803,17 +803,16 @@ STATIC mp_obj_t str_rstrip(size_t n_args, const mp_obj_t *args) {
803803

804804
// Takes an int arg, but only parses unsigned numbers, and only changes
805805
// *num if at least one digit was parsed.
806-
STATIC int str_to_int(const char *str, int *num) {
807-
const char *s = str;
808-
if ('0' <= *s && *s <= '9') {
806+
STATIC const char *str_to_int(const char *str, const char *top, int *num) {
807+
if (str < top && '0' <= *str && *str <= '9') {
809808
*num = 0;
810809
do {
811-
*num = *num * 10 + (*s - '0');
812-
s++;
810+
*num = *num * 10 + (*str - '0');
811+
str++;
813812
}
814-
while ('0' <= *s && *s <= '9');
813+
while (str < top && '0' <= *str && *str <= '9');
815814
}
816-
return s - str;
815+
return str;
817816
}
818817

819818
STATIC bool isalignment(char ch) {
@@ -881,15 +880,17 @@ vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, mp
881880

882881
// replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"
883882

884-
vstr_t *field_name = NULL;
883+
const char *field_name = NULL;
884+
const char *field_name_top = NULL;
885885
char conversion = '\0';
886886
const char *format_spec = NULL;
887887

888888
if (str < top && *str != '}' && *str != '!' && *str != ':') {
889-
field_name = vstr_new();
889+
field_name = (const char *)str;
890890
while (str < top && *str != '}' && *str != '!' && *str != ':') {
891-
vstr_add_byte(field_name, *str++);
891+
++str;
892892
}
893+
field_name_top = (const char *)str;
893894
}
894895

895896
// conversion ::= "r" | "s"
@@ -958,9 +959,7 @@ vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, mp
958959

959960
if (field_name) {
960961
int index = 0;
961-
const char *field = vstr_null_terminated_str(field_name);
962-
const char *lookup = NULL;
963-
if (MP_LIKELY(unichar_isdigit(*field))) {
962+
if (MP_LIKELY(unichar_isdigit(*field_name))) {
964963
if (*arg_i > 0) {
965964
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
966965
terse_str_format_value_error();
@@ -969,26 +968,26 @@ vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, mp
969968
"can't switch from automatic field numbering to manual field specification"));
970969
}
971970
}
972-
lookup = str_to_int(field, &index) + field;
971+
field_name = str_to_int(field_name, field_name_top, &index);
973972
if ((uint)index >= n_args - 1) {
974973
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range"));
975974
}
976975
arg = args[index + 1];
977976
*arg_i = -1;
978977
} else {
979-
for (lookup = field; *lookup && *lookup != '.' && *lookup != '['; lookup++);
980-
mp_obj_t field_q = mp_obj_new_str(field, lookup - field, true/*?*/);
978+
const char *lookup;
979+
for (lookup = field_name; lookup < field_name_top && *lookup != '.' && *lookup != '['; lookup++);
980+
mp_obj_t field_q = mp_obj_new_str(field_name, lookup - field_name, true/*?*/);
981+
field_name = lookup;
981982
mp_map_elem_t *key_elem = mp_map_lookup(kwargs, field_q, MP_MAP_LOOKUP);
982983
if (key_elem == NULL) {
983984
nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, field_q));
984985
}
985986
arg = key_elem->value;
986987
}
987-
if (*lookup) {
988+
if (field_name < field_name_top) {
988989
mp_not_implemented("attributes not supported yet");
989990
}
990-
vstr_free(field_name);
991-
field_name = NULL;
992991
} else {
993992
if (*arg_i < 0) {
994993
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
@@ -1045,6 +1044,7 @@ vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, mp
10451044
MP_STACK_CHECK();
10461045
vstr_t format_spec_vstr = mp_obj_str_format_helper(format_spec, str, arg_i, n_args, args, kwargs);
10471046
const char *s = vstr_null_terminated_str(&format_spec_vstr);
1047+
const char *stop = s + format_spec_vstr.len;
10481048
if (isalignment(*s)) {
10491049
align = *s++;
10501050
} else if (*s && isalignment(s[1])) {
@@ -1071,14 +1071,14 @@ vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, mp
10711071
fill = '0';
10721072
}
10731073
}
1074-
s += str_to_int(s, &width);
1074+
s = str_to_int(s, stop, &width);
10751075
if (*s == ',') {
10761076
flags |= PF_FLAG_SHOW_COMMA;
10771077
s++;
10781078
}
10791079
if (*s == '.') {
10801080
s++;
1081-
s += str_to_int(s, &precision);
1081+
s = str_to_int(s, stop, &precision);
10821082
}
10831083
if (istype(*s)) {
10841084
type = *s++;
@@ -1374,7 +1374,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o
13741374
width = mp_obj_get_int(args[arg_i++]);
13751375
str++;
13761376
} else {
1377-
str += str_to_int((const char*)str, &width);
1377+
str = (const byte*)str_to_int((const char*)str, (const char*)top, &width);
13781378
}
13791379
}
13801380
int prec = -1;
@@ -1388,7 +1388,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o
13881388
str++;
13891389
} else {
13901390
prec = 0;
1391-
str += str_to_int((const char*)str, &prec);
1391+
str = (const byte*)str_to_int((const char*)str, (const char*)top, &prec);
13921392
}
13931393
}
13941394
}

0 commit comments

Comments
 (0)