static int peer_hash_cb(const void *obj, const int flags)
{
const struct iax2_peer *peer = obj;
+ const char *name = obj;
- return ast_str_hash(peer->name);
+ return ast_str_hash(flags & OBJ_KEY ? name : peer->name);
}
/*!
static int peer_cmp_cb(void *obj, void *arg, int flags)
{
struct iax2_peer *peer = obj, *peer2 = arg;
+ const char *name = arg;
- return !strcmp(peer->name, peer2->name) ? CMP_MATCH | CMP_STOP : 0;
+ return !strcmp(peer->name, flags & OBJ_KEY ? name : peer2->name) ?
+ CMP_MATCH | CMP_STOP : 0;
}
/*!
static int user_hash_cb(const void *obj, const int flags)
{
const struct iax2_user *user = obj;
+ const char *name = obj;
- return ast_str_hash(user->name);
+ return ast_str_hash(flags & OBJ_KEY ? name : user->name);
}
/*!
static int user_cmp_cb(void *obj, void *arg, int flags)
{
struct iax2_user *user = obj, *user2 = arg;
+ const char *name = arg;
- return !strcmp(user->name, user2->name) ? CMP_MATCH | CMP_STOP : 0;
+ return !strcmp(user->name, flags & OBJ_KEY ? name : user2->name) ?
+ CMP_MATCH | CMP_STOP : 0;
}
/*!
static struct iax2_peer *find_peer(const char *name, int realtime)
{
struct iax2_peer *peer = NULL;
- struct iax2_peer tmp_peer = {
- .name = name,
- };
- peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
+ peer = ao2_find(peers, name, OBJ_KEY);
/* Now go for realtime if applicable */
if(!peer && realtime)
static struct iax2_user *find_user(const char *name)
{
- struct iax2_user tmp_user = {
- .name = name,
- };
-
- return ao2_find(users, &tmp_user, OBJ_POINTER);
+ return ao2_find(users, name, OBJ_KEY);
}
static inline struct iax2_user *user_ref(struct iax2_user *user)
{
/* Decrement AUTHREQ count if needed */
if (ast_test_flag64(pvt, IAX_MAXAUTHREQ)) {
struct iax2_user *user;
- struct iax2_user tmp_user = {
- .name = pvt->username,
- };
- user = ao2_find(users, &tmp_user, OBJ_POINTER);
+ user = ao2_find(users, pvt->username, OBJ_KEY);
if (user) {
ast_atomic_fetchadd_int(&user->curauthreq, -1);
user_unref(user);
p = find_peer(a->argv[2], 1);
if (p) {
if (p->expire > 0) {
- struct iax2_peer tmp_peer = {
- .name = a->argv[2],
- };
struct iax2_peer *peer;
- peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
+ peer = ao2_find(peers, a->argv[2], OBJ_KEY);
if (peer) {
expire_registry(peer_ref(peer)); /* will release its own reference when done */
peer_unref(peer); /* ref from ao2_find() */
/* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
if (ast_test_flag64(p, IAX_MAXAUTHREQ)) {
- struct iax2_user *user, tmp_user = {
- .name = p->username,
- };
+ struct iax2_user *user;
- user = ao2_find(users, &tmp_user, OBJ_POINTER);
+ user = ao2_find(users, p->username, OBJ_KEY);
if (user) {
if (user->curauthreq == user->maxauthreq)
authreq_restrict = 1;
char rsasecret[256] = "";
int res = -1;
int x;
- struct iax2_user *user, tmp_user = {
- .name = p->username,
- };
+ struct iax2_user *user;
if (p->authrej) {
return res;
}
- user = ao2_find(users, &tmp_user, OBJ_POINTER);
+ user = ao2_find(users, p->username, OBJ_KEY);
if (user) {
if (ast_test_flag64(p, IAX_MAXAUTHREQ)) {
ast_atomic_fetchadd_int(&user->curauthreq, -1);
int maskfound = 0;
int found = 0;
int firstpass = 1;
- struct iax2_peer tmp_peer = {
- .name = name,
- };
if (!temponly) {
- peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
+ peer = ao2_find(peers, name, OBJ_KEY);
if (peer && !ast_test_flag64(peer, IAX_DELME))
firstpass = 0;
}
int oldcurauthreq = 0;
char *varname = NULL, *varval = NULL;
struct ast_variable *tmpvar = NULL;
- struct iax2_user tmp_user = {
- .name = name,
- };
if (!temponly) {
- user = ao2_find(users, &tmp_user, OBJ_POINTER);
+ user = ao2_find(users, name, OBJ_KEY);
if (user && !ast_test_flag64(user, IAX_DELME))
firstpass = 0;
}
* by another mechanism other that the internal ao2_lock.
*/
OBJ_NOLOCK = (1 << 5),
+ /*!
+ * \brief The data is hashable, but is not an object.
+ *
+ * This can be used when you want to be able to pass custom data
+ * to a hash function that is not a full object, but perhaps just
+ * a string.
+ *
+ * \note OBJ_KEY and OBJ_POINTER are mutually exclusive options.
+ */
+ OBJ_KEY = (1 << 6),
};
/*!
#endif
-void *__ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag,
+void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags, char *tag,
char *file, int line, const char *funcname);
-void *__ao2_find(struct ao2_container *c, void *arg, enum search_flags flags);
+void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags);
/*! \brief
*
* run the hash function. Otherwise, scan the whole container
* (this only for the time being. We need to optimize this.)
*/
- if ((flags & OBJ_POINTER)) /* we know hash can handle this case */
- start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
+ if ((flags & (OBJ_POINTER | OBJ_KEY))) /* we know hash can handle this case */
+ start = i = c->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)) % c->n_buckets;
else /* don't know, let's scan all buckets */
start = i = -1; /* XXX this must be fixed later. */
/*!
* the find function just invokes the default callback with some reasonable flags.
*/
-void *__ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname)
+void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname)
{
- return __ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
+ return __ao2_callback_debug(c, flags, c->cmp_fn, (void *) arg, tag, file, line, funcname);
}
-void *__ao2_find(struct ao2_container *c, void *arg, enum search_flags flags)
+void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags)
{
- return __ao2_callback(c, flags, c->cmp_fn, arg);
+ return __ao2_callback(c, flags, c->cmp_fn, (void *) arg);
}
/*!
#include "asterisk/astobj2.h"
struct test_obj {
- char c[20];
int i;
int *destructor_count;
};
static int test_cmp_cb(void *obj, void *arg, int flags)
{
struct test_obj *cmp_obj = (struct test_obj *) obj;
- struct test_obj *test_obj = (struct test_obj *) arg;
+
if (!arg) {
return 0;
}
- return (cmp_obj->i == test_obj->i) ? CMP_MATCH | CMP_STOP : 0;
+
+ if (flags & OBJ_KEY) {
+ int *i = (int *) arg;
+ return (cmp_obj->i == *i) ? CMP_MATCH | CMP_STOP : 0;
+ } else {
+ struct test_obj *test_obj = (struct test_obj *) arg;
+ return (cmp_obj->i == test_obj->i) ? CMP_MATCH | CMP_STOP : 0;
+ }
}
static int test_hash_cb(const void *obj, const int flags)
{
- struct test_obj *test_obj = (struct test_obj *) obj;
- if (!test_obj || ast_strlen_zero(test_obj->c)) {
+ if (!obj) {
return 0;
}
- return ast_str_hash(test_obj->c);
+
+ if (flags & OBJ_KEY) {
+ const int *i = obj;
+
+ return *i;
+ } else {
+ const struct test_obj *test_obj = obj;
+
+ return test_obj->i;
+ }
}
static int astobj2_test_helper(int use_hash, int use_cmp, unsigned int lim, struct ast_test *test)
res = AST_TEST_FAIL;
goto cleanup;
}
- snprintf(obj->c, sizeof(obj->c), "zombie #%d", num);
obj->destructor_count = &destructor_count;
obj->i = num;
ao2_link(c1, obj);
num = 75;
for (; num; num--) {
int i = (ast_random() % ((lim / 2)) + 1); /* find a random object */
- snprintf(tmp_obj.c, sizeof(tmp_obj.c), "zombie #%d", i);
tmp_obj.i = i;
if (!(obj = ao2_find(c1, &tmp_obj, OBJ_POINTER))) {
res = AST_TEST_FAIL;
}
}
+ /* Testing ao2_find with OBJ_KEY */
+ num = 75;
+ for (; num; num--) {
+ int i = (ast_random() % ((lim / 2)) + 1); /* find a random object */
+ if (!(obj = ao2_find(c1, &i, OBJ_KEY))) {
+ res = AST_TEST_FAIL;
+ ast_test_status_update(test, "COULD NOT FIND:%d, ao2_find() with OBJ_KEY flag failed.\n", i);
+ } else {
+ /* a correct match will only take place when the custom cmp function is used */
+ if (use_cmp && obj->i != i) {
+ ast_test_status_update(test, "object %d does not match object %d\n", obj->i, tmp_obj.i);
+ res = AST_TEST_FAIL;
+ }
+ ao2_t_ref(obj, -1, "test");
+ }
+ }
+
/* Testing ao2_find with OBJ_POINTER | OBJ_UNLINK | OBJ_CONTINUE.
* In this test items are unlinked from c1 and placed in c2. Then
* unlinked from c2 and placed back into c1.
int num;
static const int NUM_OBJS = 5;
int destructor_count = NUM_OBJS;
- struct test_obj tmp_obj = { "", };
+ struct test_obj tmp_obj = { 0, };
switch (cmd) {
case TEST_INIT: