mdbx: добавление mdbx_cursor_scan() в API.

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2023-11-18 22:52:13 +03:00
parent ed59ad22c6
commit bc562d5c06
2 changed files with 41 additions and 0 deletions

8
mdbx.h
View File

@ -4929,6 +4929,14 @@ LIBMDBX_API int mdbx_cursor_compare(const MDBX_cursor *left,
* \retval MDBX_EINVAL An invalid parameter was specified. */ * \retval MDBX_EINVAL An invalid parameter was specified. */
LIBMDBX_API int mdbx_cursor_get(MDBX_cursor *cursor, MDBX_val *key, LIBMDBX_API int mdbx_cursor_get(MDBX_cursor *cursor, MDBX_val *key,
MDBX_val *data, MDBX_cursor_op op); MDBX_val *data, MDBX_cursor_op op);
/** FIXME */
typedef int(MDBX_predicate_func)(void *context, MDBX_val *key, MDBX_val *value,
void *arg) MDBX_CXX17_NOEXCEPT;
/** FIXME */
LIBMDBX_API int mdbx_cursor_scan(MDBX_cursor *cursor,
MDBX_predicate_func *predicate, void *context,
MDBX_cursor_op start_op,
MDBX_cursor_op turn_op, void *arg);
/** \brief Retrieve multiple non-dupsort key/value pairs by cursor. /** \brief Retrieve multiple non-dupsort key/value pairs by cursor.
* \ingroup c_crud * \ingroup c_crud

View File

@ -17433,6 +17433,39 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
return cursor_get(mc, key, data, op); return cursor_get(mc, key, data, op);
} }
int mdbx_cursor_scan(MDBX_cursor *mc, MDBX_predicate_func *predicate,
void *context, MDBX_cursor_op start_op,
MDBX_cursor_op turn_op, void *arg) {
if (unlikely(!predicate))
return MDBX_EINVAL;
const unsigned valid_start_mask =
1 << MDBX_FIRST | 1 << MDBX_FIRST_DUP | 1 << MDBX_LAST |
1 << MDBX_LAST_DUP | 1 << MDBX_GET_CURRENT | 1 << MDBX_GET_MULTIPLE;
if (unlikely(start_op > 30 || ((1 << start_op) & valid_start_mask) == 0))
return MDBX_EINVAL;
const unsigned valid_turn_mask =
1 << MDBX_NEXT | 1 << MDBX_NEXT_DUP | 1 << MDBX_NEXT_NODUP |
1 << MDBX_PREV | 1 << MDBX_PREV_DUP | 1 << MDBX_PREV_NODUP |
1 << MDBX_NEXT_MULTIPLE | 1 << MDBX_PREV_MULTIPLE;
if (unlikely(turn_op > 30 || ((1 << turn_op) & valid_turn_mask) == 0))
return MDBX_EINVAL;
MDBX_val key, data;
int rc = mdbx_cursor_get(mc, &key, &data, start_op);
if (unlikely(rc != MDBX_SUCCESS))
return rc;
for (;;) {
rc = predicate(context, &key, &data, arg);
if (rc != MDBX_RESULT_FALSE)
return rc;
rc = cursor_get(mc, &key, &data, turn_op);
if (rc != MDBX_SUCCESS)
return (rc == MDBX_NOTFOUND) ? MDBX_RESULT_FALSE : rc;
}
}
static int cursor_first_batch(MDBX_cursor *mc) { static int cursor_first_batch(MDBX_cursor *mc) {
if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) { if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) {
int err = page_search(mc, NULL, MDBX_PS_FIRST); int err = page_search(mc, NULL, MDBX_PS_FIRST);