Skip to content

Commit a565811

Browse files
dlechdpgeorge
authored andcommitted
extmod/modbtree: Use buffer protocol for keys/values.
This changes the btree implementation to use the buffer protocol for reading key/values in all methods. `str` and `bytes` objects are not the only bytes-like objects that could be used. Documentation and tests are also updated. Addresses issue micropython#8748. Signed-off-by: David Lechner <[email protected]>
1 parent c118b5d commit a565811

File tree

3 files changed

+26
-15
lines changed

3 files changed

+26
-15
lines changed

docs/library/btree.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ value, a database also supports efficient ordered range scans (retrieval
1111
of values with the keys in a given range). On the application interface
1212
side, BTree database work as close a possible to a way standard `dict`
1313
type works, one notable difference is that both keys and values must
14-
be `bytes` objects (so, if you want to store objects of other types, you
15-
need to serialize them to `bytes` first).
14+
be `bytes`-like objects (so, if you want to store objects of other types, you
15+
need to first serialize them to `str` or `bytes` or another type that supports
16+
the buffer protocol).
1617

1718
The module is based on the well-known BerkelyDB library, version 1.xx.
1819

extmod/modbtree.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ STATIC mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
7676
return o;
7777
}
7878

79+
STATIC void buf_to_dbt(mp_obj_t obj, DBT *dbt) {
80+
mp_buffer_info_t bufinfo;
81+
mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ);
82+
dbt->data = bufinfo.buf;
83+
dbt->size = bufinfo.len;
84+
}
85+
7986
STATIC void btree_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
8087
(void)kind;
8188
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
@@ -98,16 +105,16 @@ STATIC mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) {
98105
(void)n_args;
99106
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
100107
DBT key, val;
101-
key.data = (void *)mp_obj_str_get_data(args[1], &key.size);
102-
val.data = (void *)mp_obj_str_get_data(args[2], &val.size);
108+
buf_to_dbt(args[1], &key);
109+
buf_to_dbt(args[2], &val);
103110
return MP_OBJ_NEW_SMALL_INT(__bt_put(self->db, &key, &val, 0));
104111
}
105112
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
106113

107114
STATIC mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) {
108115
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
109116
DBT key, val;
110-
key.data = (void *)mp_obj_str_get_data(args[1], &key.size);
117+
buf_to_dbt(args[1], &key);
111118
int res = __bt_get(self->db, &key, &val, 0);
112119
if (res == RET_SPECIAL) {
113120
if (n_args > 2) {
@@ -126,7 +133,7 @@ STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
126133
int flags = MP_OBJ_SMALL_INT_VALUE(args[1]);
127134
DBT key, val;
128135
if (n_args > 2) {
129-
key.data = (void *)mp_obj_str_get_data(args[2], &key.size);
136+
buf_to_dbt(args[2], &key);
130137
}
131138

132139
int res = __bt_seq(self->db, &key, &val, flags);
@@ -201,7 +208,7 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
201208
if (self->start_key != MP_OBJ_NULL) {
202209
int flags = R_FIRST;
203210
if (self->start_key != mp_const_none) {
204-
key.data = (void *)mp_obj_str_get_data(self->start_key, &key.size);
211+
buf_to_dbt(self->start_key, &key);
205212
flags = R_CURSOR;
206213
} else if (desc) {
207214
flags = R_LAST;
@@ -219,7 +226,7 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
219226

220227
if (self->end_key != mp_const_none) {
221228
DBT end_key;
222-
end_key.data = (void *)mp_obj_str_get_data(self->end_key, &end_key.size);
229+
buf_to_dbt(self->end_key, &end_key);
223230
BTREE *t = self->db->internal;
224231
int cmp = t->bt_cmp(&key, &end_key);
225232
if (desc) {
@@ -254,7 +261,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
254261
if (value == MP_OBJ_NULL) {
255262
// delete
256263
DBT key;
257-
key.data = (void *)mp_obj_str_get_data(index, &key.size);
264+
buf_to_dbt(index, &key);
258265
int res = __bt_delete(self->db, &key, 0);
259266
if (res == RET_SPECIAL) {
260267
mp_raise_type(&mp_type_KeyError);
@@ -264,7 +271,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
264271
} else if (value == MP_OBJ_SENTINEL) {
265272
// load
266273
DBT key, val;
267-
key.data = (void *)mp_obj_str_get_data(index, &key.size);
274+
buf_to_dbt(index, &key);
268275
int res = __bt_get(self->db, &key, &val, 0);
269276
if (res == RET_SPECIAL) {
270277
mp_raise_type(&mp_type_KeyError);
@@ -274,8 +281,8 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
274281
} else {
275282
// store
276283
DBT key, val;
277-
key.data = (void *)mp_obj_str_get_data(index, &key.size);
278-
val.data = (void *)mp_obj_str_get_data(value, &val.size);
284+
buf_to_dbt(index, &key);
285+
buf_to_dbt(value, &val);
279286
int res = __bt_put(self->db, &key, &val, 0);
280287
CHECK_ERROR(res);
281288
return mp_const_none;
@@ -287,7 +294,7 @@ STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs
287294
switch (op) {
288295
case MP_BINARY_OP_CONTAINS: {
289296
DBT key, val;
290-
key.data = (void *)mp_obj_str_get_data(rhs_in, &key.size);
297+
buf_to_dbt(rhs_in, &key);
291298
int res = __bt_get(self->db, &key, &val, 0);
292299
CHECK_ERROR(res);
293300
return mp_obj_new_bool(res != RET_SPECIAL);

tests/extmod/btree1.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
f = uio.BytesIO()
1111
db = btree.open(f, pagesize=512)
1212

13+
mv = memoryview(b"bar1foo1")
14+
1315
db[b"foo3"] = b"bar3"
1416
db[b"foo1"] = b"bar1"
15-
db[b"foo2"] = b"bar2"
16-
db[b"bar1"] = b"foo1"
17+
# any type that implements buffer protocol works for key and value
18+
db["foo2"] = "bar2"
19+
db[mv[:4]] = mv[4:]
1720

1821
dbstr = str(db)
1922
print(dbstr[:7], dbstr[-1:])

0 commit comments

Comments
 (0)