8000 Improve mp_printf with support for compressed strings · domdfcoding/circuitpython@bfea694 · GitHub
[go: up one dir, main page]

Skip to content

Commit bfea694

Browse files
committed
Improve mp_printf with support for compressed strings
* The new nonstandard '%S' format takes a pointer to compressed_string_t and prints it * The new mp_cprintf and mp_vcprintf take a format string that is a compressed_string_t
1 parent f6d7b87 commit bfea694

File tree

9 files changed

+67
-60
lines changed

9 files changed

+67
-60
lines changed

locale/circuitpython.pot

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ msgid ""
3535
"https://github.com/adafruit/circuitpython/issues\n"
3636
msgstr ""
3737

38-
#: py/obj.c shared-bindings/traceback/__init__.c
38+
#: py/obj.c
3939
msgid " File \"%q\""
4040
msgstr ""
4141

42-
#: py/obj.c shared-bindings/traceback/__init__.c
42+
#: py/obj.c
4343
msgid " File \"%q\", line %d"
4444
msgstr ""
4545

@@ -322,7 +322,7 @@ msgstr ""
322322
msgid "*x must be assignment target"
323323
msgstr ""
324324

325-
#: py/obj.c shared-bindings/traceback/__init__.c
325+
#: py/obj.c
326326
msgid ", in %q\n"
327327
msgstr ""
328328

@@ -2211,7 +2211,7 @@ msgstr ""
22112211
msgid "Touch alarms not available"
22122212
msgstr ""
22132213

2214-
#: py/obj.c shared-bindings/traceback/__init__.c
2214+
#: py/obj.c
22152215
msgid "Traceback (most recent call last):\n"
22162216
msgstr ""
22172217

@@ -3903,6 +3903,10 @@ msgstr ""
39033903
#: ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.h
39043904
#: ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.h
39053905
#: ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.h
3906+
#: ports/esp32s2/boards/gravitech_cucumber_m/mpconfigboard.h
3907+
#: ports/esp32s2/boards/gravitech_cucumber_ms/mpconfigboard.h
3908+
#: ports/esp32s2/boards/gravitech_cucumber_r/mpconfigboard.h
3909+
#: ports/esp32s2/boards/gravitech_cucumber_rs/mpconfigboard.h
39063910
#: ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
39073911
#: ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h
39083912
#: ports/esp32s2/boards/muselab_nanoesp32_s2_wroom/mpconfigboard.h

py/builtinhelp.c

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,7 @@ STATIC void mp_help_print_modules(void) {
131131

132132
#if MICROPY_ENABLE_EXTERNAL_IMPORT
133133
// let the user know there may be other modules available from the filesystem
134-
const compressed_string_t *compressed = translate("Plus any modules on the filesystem\n");
135-
char decompressed[decompress_length(compressed)];
136-
decompress(compressed, decompressed);
137-
mp_print_str(MP_PYTHON_PRINTER, decompressed);
134+
mp_printf(MP_PYTHON_PRINTER, "%S", translate("Plus any modules on the filesystem\n"));
138135
#endif
139136
}
140137
#endif
@@ -150,18 +147,10 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) {
150147
const mp_obj_type_t *type = mp_obj_get_type(obj);
151148

152149
// try to print something sensible about the given object
153-
const compressed_string_t *compressed = translate("object ");
154-
char decompressed_object[decompress_length(compressed)];
155-
decompress(compressed, decompressed_object);
156-
157-
mp_print_str(MP_PYTHON_PRINTER, decompressed_object);
150+
mp_cprintf(MP_PYTHON_PRINTER, translate("object "));
158151
mp_obj_print(obj, PRINT_STR);
159152

160-
compressed = translate(" is of type %q\n");
161-
char decompressed_typestring[decompress_length(compressed)];
162-
decompress(compressed, decompressed_typestring);
163-
164-
mp_printf(MP_PYTHON_PRINTER, decompressed_typestring, type->name);
153+
mp_cprintf(MP_PYTHON_PRINTER, translate(" is of type %q\n"), type->name);
165154

166155
mp_map_t *map = NULL;
167156
if (type == &mp_type_module) {
@@ -186,11 +175,9 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) {
186175
STATIC mp_obj_t mp_builtin_help(size_t n_args, const mp_obj_t *args) {
187176
if (n_args == 0) {
188177
// print a general help message. Translate only works on single strings on one line.
189-
const compressed_string_t *compressed =
190-
translate("Welcome to Adafruit CircuitPython %s!\n\nPlease visit learn.adafruit.com/category/circuitpython for project guides.\n\nTo list built-in modules please do `help(\"modules\")`.\n");
191-
char decompressed[decompress_length(compressed)];
192-
decompress(compressed, decompressed);
193-
mp_printf(MP_PYTHON_PRINTER, decompressed, MICROPY_GIT_TAG);
178+
mp_cprintf(MP_PYTHON_PRINTER,
179+
translate("Welcome to Adafruit CircuitPython %s!\n\nPlease visit learn.adafruit.com/category/circuitpython for project guides.\n\nTo list built-in modules please do `help(\"modules\")`.\n"),
180+
MICROPY_GIT_TAG);
194181
} else {
195182
// try to print something sensible about the given object
196183
mp_help_print_obj(args[0]);

py/mpprint.c

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,13 @@ int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, c
376376
}
377377
#endif
378378

379+
static int print_str_common(const mp_print_t *print, const char *str, int prec, size_t len, int flags, int fill, int width) {
380+
if (prec >= 0 && (size_t)prec < len) {
381+
len = prec;
382+
}
383+
return mp_print_strn(print, str, len, flags, fill, width);
384+
}
385+
379386
int mp_printf(const mp_print_t *print, const char *fmt, ...) {
380387
va_list ap;
381388
va_start(ap, fmt);
@@ -484,19 +491,24 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
484491
qstr qst = va_arg(args, qstr);
485492
size_t len;
486493
const char *str = (const char *)qstr_data(qst, &len);
487-
if (prec >= 0 && (size_t)prec < len) {
488-
len = prec;
489-
}
490-
chrs += mp_print_strn(print, str, len, flags, fill, width);
494+
chrs += print_str_common(print, str, prec, len, flags, fill, width);
495+
break;
496+
}
497+
case 'S': {
498+
compressed_string_t *arg = va_arg(args, compressed_string_t *);
499+
size_t len_with_nul = decompress_length(arg);
500+
size_t len = len_with_nul - 1;
501+
char str[len_with_nul];
502+
decompress(arg, str);
503+
chrs += print_str_common(print, str, prec, len, flags, fill, width);
491504
break;
492505
}
493506
case 's': {
494507
const char *str = va_arg(args, const char *);
495508
#ifndef NDEBUG
496509
// With debugging enabled, catch printing of null string pointers
497-
if (prec != 0 && str == NULL) {
498-
chrs += mp_print_strn(print, "(null)", 6, flags, fill, width);
499-
break;
510+
if (str == NULL) {
511+
str = "(null)";
500512
}
501513
#endif
502514
size_t len = strlen(str);
@@ -574,3 +586,19 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
574586
}
575587
return chrs;
576588
}
589+
590+
int mp_cprintf(const mp_print_t *print, const compressed_string_t *compressed_fmt, ...) {
591+
va_list ap;
592+
va_start(ap, compressed_fmt);
593+
int ret = mp_vcprintf(print, compressed_fmt, ap);
594+
va_end(ap);
595+
return ret;
596+
}
597+
598+
int mp_vcprintf(const mp_print_t *print, const compressed_string_t *compressed_fmt, va_list args) {
599+
char fmt[decompress_length(compressed_fmt)];
600+
// TODO: Optimise this to format-while-decompressing (and not require the temp stack space).
601+
decompress(compressed_fmt, fmt);
602+
603+
return mp_vprintf(print, fmt, args);
604+
}

py/mpprint.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,10 @@ int mp_printf(const mp_print_t *print, const char *fmt, ...);
7171
int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args);
7272
#endif
7373

74+
struct compressed_string;
75+
int mp_cprintf(const mp_print_t *print, const struct compressed_string *compressed_fmt, ...);
76+
#ifdef va_start
77+
int mp_vcprintf(const mp_print_t *print, const struct compressed_string *compressed_fmt, va_list args);
78+
#endif
79+
7480
#endif // MICROPY_INCLUDED_PY_MPPRINT_H

py/obj.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -149,35 +149,27 @@ void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc) {
149149
mp_obj_exception_get_traceback(exc, &n, &values);
150150
if (n > 0) {
151151
assert(n % 3 == 0);
152-
// Decompress the format strings
153-
const compressed_string_t *traceback = MP_ERROR_TEXT("Traceback (most recent call last):\n");
154-
char decompressed[decompress_length(traceback)];
155-
decompress(traceback, decompressed);
156152
#if MICROPY_ENABLE_SOURCE_LINE
157153
const compressed_string_t *frame = MP_ERROR_TEXT(" File \"%q\", line %d");
158154
#else
159155
const compressed_string_t *frame = MP_ERROR_TEXT(" File \"%q\"");
160156
#endif
161-
char decompressed_frame[decompress_length(frame)];
162-
decompress(frame, decompressed_frame);
163157
const compressed_string_t *block_fmt = MP_ERROR_TEXT(", in %q\n");
164-
char decompressed_block[decompress_length(block_fmt)];
165-
decompress(block_fmt, decompressed_block);
166158

167159
// Print the traceback
168-
mp_print_str(print, decompressed);
160+
mp_cprintf(print, MP_ERROR_TEXT("Traceback (most recent call last):\n"));
169161
for (int i = n - 3; i >= 0; i -= 3) {
170162
#if MICROPY_ENABLE_SOURCE_LINE
171-
mp_printf(print, decompressed_frame, values[i], (int)values[i + 1]);
163+
mp_cprintf(print, frame, values[i], (int)values[i + 1]);
172164
#else
173-
mp_printf(print, decompressed_frame, values[i]);
165+
mp_printf(print, frame, values[i]);
174166
#endif
175167
// the block name can be NULL if it's unknown
176168
qstr block = values[i + 2];
177169
if (block == MP_QSTRnull) {
178170
mp_print_str(print, "\n");
179171
} else {
180-
mp_printf(print, decompressed_block, block);
172+
mp_cprintf(print, block_fmt, block);
181173
}
182174
}
183175
}

py/objexcept.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -465,12 +465,9 @@ mp_obj_t mp_obj_new_exception_msg_vlist(const mp_obj_type_t *exc_type, const com
465465
o_str->data = NULL;
466466
} else {
467467
// We have some memory to format the string.
468-
// TODO: Optimise this to format-while-decompressing (and not require the temp stack space).
469468
struct _exc_printer_t exc_pr = {!used_emg_buf, o_str_alloc, 0, o_str_buf};
470469
mp_print_t print = {&exc_pr, exc_add_strn};
471-
char fmt_decompressed[decompress_length(fmt)];
472-
decompress(fmt, fmt_decompressed);
473-
mp_vprintf(&print, fmt_decompressed, ap);
470+
mp_vcprintf(&print, fmt, ap);
474471
exc_pr.buf[exc_pr.len] = '\0';
475472
o_str->len = exc_pr.len;
476473
o_str->data = exc_pr.buf;

shared-module/traceback/__init__.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,12 @@ void shared_module_traceback_print_exception(mp_obj_exception_t *exc, mp_print_t
3535
assert(n % 3 == 0);
3636
// Decompress the format strings
3737
const compressed_string_t *traceback = MP_ERROR_TEXT("Traceback (most recent call last):\n");
38-
char decompressed[decompress_length(traceback)];
39-
decompress(traceback, decompressed);
4038
#if MICROPY_ENABLE_SOURCE_LINE
4139
const compressed_string_t *frame = MP_ERROR_TEXT(" File \"%q\", line %d");
4240
#else
4341
const compressed_string_t *frame = MP_ERROR_TEXT(" File \"%q\"");
4442
#endif
45-
char decompressed_frame[decompress_length(frame)];
46-
decompress(frame, decompressed_frame);
4743
const compressed_string_t *block_fmt = MP_ERROR_TEXT(", in %q\n");
48-
char decompressed_block[decompress_length(block_fmt)];
49-
decompress(block_fmt, decompressed_block);
5044

5145
// Set traceback formatting
5246
// Default: Print full traceback
@@ -69,20 +63,20 @@ void shared_module_traceback_print_exception(mp_obj_exception_t *exc, mp_print_t
6963
}
7064

7165
// Print the traceback
72-
mp_print_str(print, decompressed);
66+
mp_cprintf(print, traceback);
7367
for (; i >= limit; i -= 3) {
7468
j = (i < 0) ? -i : i;
7569
#if MICROPY_ENABLE_SOURCE_LINE
76-
mp_printf(print, decompressed_frame, values[j], (int)values[j + 1]);
70+
mp_cprintf(print, frame, values[j], (int)values[j + 1]);
7771
#else
78-
mp_printf(print, decompressed_frame, values[j]);
72+
mp_printf(print, frame, values[j]);
7973
#endif
8074
// The block name can be NULL if it's unknown
8175
qstr block = values[j + 2];
8276
if (block == MP_QSTRnull) {
8377
mp_print_str(print, "\n");
8478
} else {
85-
mp_printf(print, decompressed_block, block);
79+
mp_printf(print, block_fmt, block);
8680
}
8781
}
8882
}

supervisor/shared/translate.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,11 @@
3535
#endif
3636

3737
#include "py/misc.h"
38+
#include "py/mpprint.h"
3839
#include "supervisor/serial.h"
3940

4041
void serial_write_compressed(const compressed_string_t *compressed) {
41-
char decompressed[decompress_length(compressed)];
42-
decompress(compressed, decompressed);
43-
serial_write(decompressed);
42+
mp_printf(MP_PYTHON_PRINTER, "%S", compressed);
4443
}
4544

4645
STATIC void get_word(int n, const mchar_t **pos, const mchar_t **end) {

supervisor/shared/translate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
// flexible array}, but is also future-proofed against strings with
7070
// UTF-8 length above 256, with a savings of about 1.375 bytes per
7171
// string.
72-
typedef struct {
72+
typedef struct compressed_string {
7373
uint8_t data;
7474
const uint8_t tail[];
7575
} compressed_string_t;

0 commit comments

Comments
 (0)
0