Skip to content

Commit 354d15a

Browse files
committed
Implement fixed buffer vstrs; use them for import path.
1 parent 64131f3 commit 354d15a

6 files changed

Lines changed: 65 additions & 20 deletions

File tree

py/builtinimport.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
149149
const char *mod_str = (const char*)mp_obj_str_get_data(args[0], &mod_len);
150150

151151
uint last = 0;
152-
vstr_t *path = vstr_new();
152+
VSTR_FIXED(path, MICROPY_PATH_MAX)
153153
module_obj = MP_OBJ_NULL;
154154
uint i;
155155
for (i = 1; i <= mod_len; i++) {
@@ -159,14 +159,14 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
159159

160160
// find the file corresponding to the module name
161161
mp_import_stat_t stat;
162-
if (vstr_len(path) == 0) {
162+
if (vstr_len(&path) == 0) {
163163
// first module in the dotted-name; search for a directory or file
164-
stat = find_file(mod_str, i, path);
164+
stat = find_file(mod_str, i, &path);
165165
} else {
166166
// latter module in the dotted-name; append to path
167-
vstr_add_char(path, PATH_SEP_CHAR);
168-
vstr_add_strn(path, mod_str + last, i - last);
169-
stat = stat_dir_or_file(path);
167+
vstr_add_char(&path, PATH_SEP_CHAR);
168+
vstr_add_strn(&path, mod_str + last, i - last);
169+
stat = stat_dir_or_file(&path);
170170
}
171171
last = i + 1;
172172

@@ -182,14 +182,14 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
182182
module_obj = mp_obj_new_module(mod_name);
183183

184184
if (stat == MP_IMPORT_STAT_DIR) {
185-
vstr_add_char(path, PATH_SEP_CHAR);
186-
vstr_add_str(path, "__init__.py");
187-
if (mp_import_stat(vstr_str(path)) == MP_IMPORT_STAT_FILE) {
188-
do_load(module_obj, path);
185+
vstr_add_char(&path, PATH_SEP_CHAR);
186+
vstr_add_str(&path, "__init__.py");
187+
if (mp_import_stat(vstr_str(&path)) == MP_IMPORT_STAT_FILE) {
188+
do_load(module_obj, &path);
189189
}
190-
vstr_cut_tail(path, 12); // cut off /__init__.py
190+
vstr_cut_tail(&path, 12); // cut off /__init__.py
191191
} else { // MP_IMPORT_STAT_FILE
192-
do_load(module_obj, path);
192+
do_load(module_obj, &path);
193193
break;
194194
}
195195
}
@@ -202,8 +202,6 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
202202
assert(0);
203203
}
204204

205-
vstr_free(path);
206-
207205
return module_obj;
208206
}
209207

py/misc.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,17 @@ typedef struct _vstr_t {
6868
int alloc;
6969
int len;
7070
char *buf;
71-
bool had_error;
71+
struct {
72+
bool had_error : 1;
73+
bool fixed_buf : 1;
74+
};
7275
} vstr_t;
7376

77+
// convenience macro to declare a vstr with a fixed size buffer on the stack
78+
#define VSTR_FIXED(vstr, alloc) vstr_t vstr; char vstr##_buf[(alloc)]; vstr_init_fixed_buf(&vstr, (alloc), vstr##_buf);
79+
7480
void vstr_init(vstr_t *vstr, int alloc);
81+
void vstr_init_fixed_buf(vstr_t *vstr, int alloc, char *buf);
7582
void vstr_clear(vstr_t *vstr);
7683
vstr_t *vstr_new(void);
7784
vstr_t *vstr_new_size(int alloc);
@@ -81,7 +88,7 @@ bool vstr_had_error(vstr_t *vstr);
8188
char *vstr_str(vstr_t *vstr);
8289
int vstr_len(vstr_t *vstr);
8390
void vstr_hint_size(vstr_t *vstr, int size);
84-
char *vstr_extend(vstr_t *vstr, int size);
91+
char *vstr_extend(vstr_t *vstr, int size);
8592
bool vstr_set_size(vstr_t *vstr, int size);
8693
bool vstr_shrink(vstr_t *vstr);
8794
char *vstr_add_len(vstr_t *vstr, int len);

py/mpconfig.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ typedef long long mp_longint_impl_t;
101101
#define MICROPY_CPYTHON_COMPAT (1)
102102
#endif
103103

104+
// Maximum length of a path in the filesystem
105+
// So we can allocate a buffer on the stack for path manipulation in import
106+
#ifndef MICROPY_PATH_MAX
107+
#define MICROPY_PATH_MAX (512)
108+
#endif
109+
104110
/*****************************************************************************/
105111
/* Miscellaneous settings */
106112

py/vstr.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <stdio.h>
22
#include <stdarg.h>
33
#include <string.h>
4+
#include <assert.h>
45
#include "misc.h"
56

67
// returned value is always at least 1 greater than argument
@@ -16,10 +17,23 @@ void vstr_init(vstr_t *vstr, int alloc) {
1617
}
1718
vstr->buf[0] = 0;
1819
vstr->had_error = false;
20+
vstr->fixed_buf = false;
21+
}
22+
23+
void vstr_init_fixed_buf(vstr_t *vstr, int alloc, char *buf) {
24+
assert(alloc > 0); // need at least room for the null byte
25+
vstr->alloc = alloc;
26+
vstr->len = 0;
27+
vstr->buf = buf;
28+
vstr->buf[0] = 0;
29+
vstr->had_error = false;
30+
vstr->fixed_buf = true;
1931
}
2032

2133
void vstr_clear(vstr_t *vstr) {
22-
m_del(char, vstr->buf, vstr->alloc);
34+
if (!vstr->fixed_buf) {
35+
m_del(char, vstr->buf, vstr->alloc);
36+
}
2337
vstr->buf = NULL;
2438
}
2539

@@ -43,7 +57,9 @@ vstr_t *vstr_new_size(int alloc) {
4357

4458
void vstr_free(vstr_t *vstr) {
4559
if (vstr != NULL) {
46-
m_del(char, vstr->buf, vstr->alloc);
60+
if (!vstr->fixed_buf) {
61+
m_del(char, vstr->buf, vstr->alloc);
62+
}
4763
m_del_obj(vstr_t, vstr);
4864
}
4965
}
@@ -73,7 +89,10 @@ int vstr_len(vstr_t *vstr) {
7389
}
7490

7591
// Extend vstr strictly to by requested size, return pointer to newly added chunk
76-
char *vstr_extend(vstr_t *vstr, int size) {
92+
char *vstr_extend(vstr_t *vstr, int size) {
93+
if (vstr->fixed_buf) {
94+
return NULL;
95+
}
7796
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size);
7897
if (new_buf == NULL) {
7998
vstr->had_error = true;
@@ -87,6 +106,9 @@ char *vstr_extend(vstr_t *vstr, int size) {
87106

88107
// Shrink vstr to be given size
89108
bool vstr_set_size(vstr_t *vstr, int size) {
109+
if (vstr->fixed_buf) {
110+
return false;
111+
}
90112
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, size);
91113
if (new_buf == NULL) {
92114
vstr->had_error = true;
@@ -102,8 +124,11 @@ bool vstr_shrink(vstr_t *vstr) {
102124
return vstr_set_size(vstr, vstr->len);
103125
}
104126

105-
bool vstr_ensure_extra(vstr_t *vstr, int size) {
127+
static bool vstr_ensure_extra(vstr_t *vstr, int size) {
106128
if (vstr->len + size + 1 > vstr->alloc) {
129+
if (vstr->fixed_buf) {
130+
return false;
131+
}
107132
int new_alloc = ROUND_ALLOC((vstr->len + size + 1) * 2);
108133
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc);
109134
if (new_buf == NULL) {
@@ -156,8 +181,15 @@ void vstr_add_str(vstr_t *vstr, const char *str) {
156181

157182
void vstr_add_strn(vstr_t *vstr, const char *str, int len) {
158183
if (vstr->had_error || !vstr_ensure_extra(vstr, len)) {
184+
// if buf is fixed, we got here because there isn't enough room left
185+
// so just try to copy as much as we can, with room for null byte
186+
if (vstr->fixed_buf && vstr->len + 1 < vstr->alloc) {
187+
len = vstr->alloc - vstr->len - 1;
188+
goto copy;
189+
}
159190
return;
160191
}
192+
copy:
161193
memmove(vstr->buf + vstr->len, str, len);
162194
vstr->len += len;
163195
vstr->buf[vstr->len] = 0;

stm/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define MICROPY_ENABLE_GC (1)
88
#define MICROPY_ENABLE_REPL_HELPERS (1)
99
#define MICROPY_ENABLE_FLOAT (1)
10+
#define MICROPY_PATH_MAX (128)
1011

1112
// type definitions for the specific machine
1213

unix/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define MICROPY_ENABLE_SOURCE_LINE (1)
1616
#define MICROPY_ENABLE_FLOAT (1)
1717
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG)
18+
#define MICROPY_PATH_MAX (PATH_MAX)
1819

1920
// type definitions for the specific machine
2021

0 commit comments

Comments
 (0)