rizin/librz/search/collection.c
Rot127 42dc673fa5 String/Hex-Search 6/9: Add core implementation of new search (by deroad).
Adds the core implementation of the new search.

The rough architecture is the following:

A search for a certain type of information (strings, bytes, keys etc.)
creates a collections of items to search for (byte patterns, regular expressions etc.).

Then specifies some settings how the search (number of threads, maxum hits...)
and the finding is performed (string length, inverse match etc.).

It also defines a search space, which is currently only the IO buffer.
But can be anything in the future, like a graphs or the knowledge base.

The search splits up the search space into windows (for IO: address ranges)
and dispatches each search window into a 'find()' thread.

The 'find()' handler (provided by a specific search implementation)
checks the given window and produces search hits matching the elements in the search collection.

The main search handler collects the hits of the dispatched workers
and returns them to the user.

Note: The byte and string search implementations are added in the next two commits.

Part 6/9. Likely won't build in between parts.

Co-authored-by: wargio <deroad@kumo.xn--q9jyb4c>
2025-02-22 04:12:49 +08:00

91 lines
3.3 KiB
C

// SPDX-FileCopyrightText: 2024 RizinOrg <info@rizin.re>
// SPDX-FileCopyrightText: 2024 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_search.h>
#include "search_internal.h"
static RZ_OWN RzSearchCollection *rz_search_collection_new(RzSearchSpace space, RZ_NONNULL void *find, RZ_NONNULL RzSearchIsEmptyCallback is_empty, RZ_NULLABLE RzSearchFreeCallback free, RZ_NULLABLE void *user) {
rz_return_val_if_fail(find && is_empty, NULL);
RzSearchCollection *sc = RZ_NEW0(RzSearchCollection);
if (!sc) {
RZ_LOG_ERROR("search: failed to allocate RzSearchCollection\n");
return NULL;
}
sc->space = space;
sc->find = find;
sc->is_empty = is_empty;
sc->free = free;
sc->user = user;
return sc;
}
/**
* \brief Initialize a new RzSearchCollection over a graph.
*
* \param[in] find The find callback to set
* \param[in] is_empty The callback to use to check if collection is empty
* \param[in] free The callback to use to free the context
* \param user The additional context needed.
*
* \return On success returns a valid pointer, otherwise NULL.
*/
RZ_IPI RZ_OWN RzSearchCollection *rz_search_collection_new_graph_space(RZ_NONNULL RzSearchFindGraphCallback find, RZ_NONNULL RzSearchIsEmptyCallback is_empty, RZ_NULLABLE RzSearchFreeCallback free, RZ_NULLABLE void *user) {
rz_return_val_if_fail(find && is_empty, NULL);
return rz_search_collection_new(RZ_SEARCH_SPACE_GRAPH, find, is_empty, free, user);
}
/**
* \brief Initialize a new RzSearchCollection over bytes.
*
* \param[in] find The find callback to set
* \param[in] is_empty The callback to use to check if collection is empty
* \param[in] free The callback to use to free the context
* \param user The additional context needed.
*
* \return On success returns a valid pointer, otherwise NULL.
*/
RZ_IPI RZ_OWN RzSearchCollection *rz_search_collection_new_bytes_space(RZ_NONNULL RzSearchFindBytesCallback find, RZ_NONNULL RzSearchIsEmptyCallback is_empty, RZ_NULLABLE RzSearchFreeCallback free, RZ_NULLABLE void *user) {
rz_return_val_if_fail(find && is_empty, NULL);
return rz_search_collection_new(RZ_SEARCH_SPACE_BYTES, find, is_empty, free, user);
}
/**
* \brief Frees a RzSearchCollection structure
*
* \param[in] sc The RzSearchCollection pointer to free
*/
RZ_API void rz_search_collection_free(RZ_NULLABLE RzSearchCollection *sc) {
if (!sc) {
return;
}
if (sc->free) {
sc->free(sc->user);
}
free(sc);
}
/**
* \brief Checks if a given RzSearchCollection has an expected find callback
*
* \param col The RzSearchCollection to test
* \param[in] expected The expected find callback
*
* \return Returns true when the RzSearchCollection callback matches the expected one.
*/
RZ_IPI bool rz_search_collection_has_find_callback(RZ_NONNULL RzSearchCollection *col, RZ_NONNULL void *expected) {
rz_return_val_if_fail(col && expected, false);
return col->find == expected;
}
/**
* \brief Checks if a given RzSearchCollection is empty
*
* \param col The RzSearchCollection to test
*
* \return Returns true when the RzSearchCollection is empty.
*/
RZ_IPI bool rz_search_collection_is_empty(RZ_NONNULL RzSearchCollection *col) {
rz_return_val_if_fail(col && col->is_empty, false);
return col->is_empty(col->user);
}