1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/pkg/lua/contrib/binsearch.h
Karl Fessel 05f114d0af doc: fix unbalaced grouping
- most were trivial
    - missing group close or open
    - extra space
    - no doxygen comment
- name commad might open an implicit group
    this hould also be implicit cosed but does not happen somtimes
- crazy: internal declared groups have to be closed internal
2022-09-14 15:05:25 +02:00

139 lines
4.5 KiB
C

/*
* Copyright (C) 2018 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @internal
* @file
* @ingroup pkg_lua
* @brief Generic binary search for tables containing strings.
* @author Juan Carrano <j.carrano@fu-berlin.de>
*
* It is often the case that one has an array of structs, where one of the
* members of the struct is a string pointer containing a key that must be
* searched. If the array is sorted by this key and of known length, a binary
* search can be performed.
*
* To make the code generic we must reinterpret the structure array
* as an array of pointers to string with a stride (separation in bytes between
* elements) and offset (position of the first element relative to the start of
* the array) given by the struct definition.
*
* For example, given the following struct and array definitions and assuming
* a 32 bit platform with strict alignment:
* struct s1 {
* int a; // Takes up 4 bytes
* char *name; // Takes up 4 bytes
* char m; // Takes up 1 byte
* };
* struct s1 my_table[] = {......};
*
* Then each element of my_table will be aligned to 12 bytes. The address of the
* "name" field of the first elements will be 4 bytes more than the address of
* "my_table". With this two numbers we can compute the address of the i-th
* "name" field as:
* [address of my_table] + offset + i*stride
* Where stride=12 bytes and offset = 4 bytes.
* @{
*/
#ifndef BINSEARCH_H
#define BINSEARCH_H
#include <stdint.h>
#include <errno.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Produce a compiler error if x is not an lvalue.
*/
#define _ENSURE_LVALUE(x) ((void)sizeof(&(x)))
/**
* UNSAFE MACRO: Difference in bytes between the addresses of two consecutive
* array elements.
*/
#define _ARRAY_STRIDE(arr) ((size_t)((const uint8_t *)((arr) + 1) - (const uint8_t *)(arr)))
/**
* UNSAFE MACRO: Offset in bytes from the start of the array to member "member"
* of the first element.
*/
#define _ARRAY_MEMBER_OFFS(arr, member) \
((size_t)((const uint8_t *)(&((arr)->member)) - (const uint8_t *)(arr)))
/**
* Find the index of the array element that contains "str" in
* member "member".
*
* A compile-time error will be raised if arr is not an lvalue. This ensures the
* macro is safe.
*
* @return Index of the array element containing the string.
* @return (-ENOENT) if it is not found.
*/
#define BINSEARCH_STR(arr, nmemb, member, str, n) \
(_ENSURE_LVALUE(arr), \
(binsearch_str((arr), _ARRAY_MEMBER_OFFS(arr, member), _ARRAY_STRIDE(arr), \
(nmemb), (str), (n))) \
)
/**
* Find a pointer of the array element that contains "str" in
* member "member".
*
* @return Address of the element containing the string (as a void pointer).
* @return Null if it is not found.
*/
#define BINSEARCH_STR_P(arr, nmemb, member, str, n) \
(_ENSURE_LVALUE(arr), \
(binsearch_str_p((arr), _ARRAY_MEMBER_OFFS(arr, member), _ARRAY_STRIDE(arr), \
(nmemb), (str), (n))) \
)
/**
* Search for an array element containing a string.
*
* This does NOT check for NULL pointers, though start can be NULL of the size
* (nmemb) is zero.
*
* @param start Pointer to start of array. The array must be ordered
* according to the search string.
* @param offset Offset of member containing string within structure. This
* can be determined using offsetof.
* @param stride Difference in bytes between the addresses of two consecutive
* array elements.
* @param nmemb Number of elements in the array.
* @param str String that will be compared against.
* @param n Compare up to n characters (see strncmp())
*
* @return Index of the array element containing the string.
* @return (-ENOENT) if it is not found.
*/
int binsearch_str(const void *start, size_t offset, size_t stride, size_t nmemb,
const char *str, size_t n);
/**
* Like binsearch_str but returns the pointer to the element.
*
* @return Address of the element containing the string.
* @return Null if it is not found.
*/
const void *binsearch_str_p(const void *start, size_t offset, size_t stride,
size_t nmemb, const char *str, size_t n);
#ifdef __cplusplus
}
#endif
#endif /* BINSEARCH_H */
/** @internal
* @} */