From 64931c395dcee6f0a65a6d143e92fbab9439bf00 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Tue, 17 Feb 2026 12:11:47 -0800 Subject: [PATCH] Add bsearch_index() Add a wrapper around bsearch() that returns an index into the array that the key would occupy rather than only being able to return pointers to array members that match the key. Signed-off-by: Zach Brown --- kmod/src/Makefile | 1 + kmod/src/bsearch_index.c | 59 ++++++++++++++++++++++++++++++++++++++++ kmod/src/bsearch_index.h | 7 +++++ 3 files changed, 67 insertions(+) create mode 100644 kmod/src/bsearch_index.c create mode 100644 kmod/src/bsearch_index.h diff --git a/kmod/src/Makefile b/kmod/src/Makefile index c9f6a961..ce1599f8 100644 --- a/kmod/src/Makefile +++ b/kmod/src/Makefile @@ -13,6 +13,7 @@ scoutfs-y += \ avl.o \ alloc.o \ block.o \ + bsearch_index.o \ btree.o \ client.o \ counters.o \ diff --git a/kmod/src/bsearch_index.c b/kmod/src/bsearch_index.c new file mode 100644 index 00000000..556b097d --- /dev/null +++ b/kmod/src/bsearch_index.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2026 Versity Software, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#include +#include + +#include "bsearch_index.h" + +struct bsearch_index_key { + int (*cmp)(const void *key, const void *elt); + /* the key has to be const, so we have to update the index through a pointer */ + void **index_elt; + const void *key; + size_t size; +}; + +static int cmp_index(const void *key, const void *elt) +{ + const struct bsearch_index_key *bik = key; + int cmp = bik->cmp(bik->key, elt); + + if (cmp > 0) + *(bik->index_elt) = (void *)elt + bik->size; + else + *(bik->index_elt) = (void *)elt; + + return cmp; +} + +/* + * A bsearch() wrapper that returns the index of the element of the + * array that the key would be stored in to maintain sort order. It's + * the first element where the existing element is greater than the key. + * It returns the size of the array if the key is greater than the last + * element in the array. + */ +size_t bsearch_index(const void *key, const void *base, size_t num, size_t size, + int (*cmp)(const void *key, const void *elt)) +{ + void *index_elt = (void *)base; + struct bsearch_index_key bik = { + .cmp = cmp, + .index_elt = &index_elt, + .key = key, + .size = size, + }; + + bsearch(&bik, base, num, size, cmp_index); + return ((unsigned long)index_elt - (unsigned long)base) / size; +} diff --git a/kmod/src/bsearch_index.h b/kmod/src/bsearch_index.h new file mode 100644 index 00000000..d3115a17 --- /dev/null +++ b/kmod/src/bsearch_index.h @@ -0,0 +1,7 @@ +#ifndef _SCOUTFS_BSEARCH_INDEX_H_ +#define _SCOUTFS_BSEARCH_INDEX_H_ + +size_t bsearch_index(const void *key, const void *base, size_t num, size_t size, + int (*cmp)(const void *key, const void *elt)); + +#endif