summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rpmio/Makefile.am4
-rw-r--r--rpmio/rpmhook.c191
-rw-r--r--rpmio/rpmhook.h28
3 files changed, 127 insertions, 96 deletions
diff --git a/rpmio/Makefile.am b/rpmio/Makefile.am
index c3f72a3ee..2cfb04f67 100644
--- a/rpmio/Makefile.am
+++ b/rpmio/Makefile.am
@@ -20,7 +20,7 @@ pkgincdir = $(pkgincludedir)
pkginc_HEADERS = \
argv.h fts.h \
rpmio.h rpmurl.h rpmmacro.h rpmlog.h rpmmessages.h rpmerr.h rpmpgp.h \
- rpmsq.h rpmsw.h ugid.h rpmlua.h
+ rpmsq.h rpmsw.h ugid.h rpmlua.h rpmhook.h
noinst_HEADERS = rpmio_internal.h
BEECRYPTLOBJS = $(shell test X"@WITH_BEECRYPT_SUBDIR@" != X && cat $(top_builddir)/@WITH_BEECTYPT_SUBDIR@/listobjs)
@@ -33,7 +33,7 @@ librpmio_la_SOURCES = \
argv.c digest.c fts.c macro.c \
rpmio.c rpmlog.c rpmmalloc.c \
rpmpgp.c rpmrpc.c rpmsq.c rpmsw.c strcasecmp.c stubs.c url.c ugid.c \
- rpmlua.c
+ rpmlua.c rpmhook.c
librpmio_la_LDFLAGS = -release 4.3 $(LDFLAGS) \
@WITH_BEECRYPT_LIB@ \
$(top_builddir)/file/src/libfmagic.la \
diff --git a/rpmio/rpmhook.c b/rpmio/rpmhook.c
index 1323117ba..74938801d 100644
--- a/rpmio/rpmhook.c
+++ b/rpmio/rpmhook.c
@@ -1,56 +1,46 @@
+#include "system.h"
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
+#include <rpmhook.h>
+
#define RPMHOOK_TABLE_INITSIZE 256
#define RPMHOOK_BUCKET_INITSIZE 5
-typedef union {
- char *s;
- int i;
- float f;
- void *p;
-} rpmhookArgv;
-
-typedef struct {
- int argc;
- const char *argt;
- rpmhookArgv argv[1];
-} rpmhookArgs;
-
-typedef int (*rpmhookFunc)(rpmhookArgs *args, void *data);
-
-typedef struct _rpmhookItem {
+typedef struct rpmhookItem_s {
rpmhookFunc func;
void *data;
- struct _rpmhookItem *next;
-} rpmhookItem;
+ struct rpmhookItem_s *next;
+} * rpmhookItem;
-typedef struct {
+typedef struct rpmhookBucket_s {
unsigned long hash;
char *name;
- rpmhookItem *item;
-} rpmhookBucket;
+ rpmhookItem item;
+} * rpmhookBucket;
-typedef struct {
+typedef struct rpmhookTable_s {
int size;
int used;
- rpmhookBucket bucket[1];
-} rpmhookTable;
+ struct rpmhookBucket_s bucket[1];
+} * rpmhookTable;
-rpmhookTable *rpmhookTableNew(int size)
+static rpmhookTable rpmhookTableNew(int size)
{
- rpmhookTable *table = (rpmhookTable *)calloc(1, sizeof(rpmhookTable)+
- sizeof(rpmhookBucket)*
- (size-1));
+ rpmhookTable table =
+ (rpmhookTable)xcalloc(1, sizeof(struct rpmhookTable_s)+
+ sizeof(struct rpmhookBucket_s)*(size-1));
table->size = size;
return table;
}
-rpmhookTable *rpmhookTableFree(rpmhookTable *table)
+#if 0
+static rpmhookTable rpmhookTableFree(rpmhookTable table)
{
- rpmhookItem *item, *nextItem;
+ rpmhookItem item, nextItem;
int i;
for (i = 0; i != table->size; i++) {
if (table->bucket[i].name) {
@@ -64,18 +54,20 @@ rpmhookTable *rpmhookTableFree(rpmhookTable *table)
}
}
free(table);
+ return NULL;
}
+#endif
-void rpmhookTableRehash(rpmhookTable **table);
+static void rpmhookTableRehash(rpmhookTable *table);
-int rpmhookTableFindBucket(rpmhookTable **table, const char *name)
+static int rpmhookTableFindBucket(rpmhookTable *table, const char *name)
{
/* Hash based on http://www.isthe.com/chongo/tech/comp/fnv/ */
unsigned long perturb;
unsigned long hash = 0;
unsigned char *bp = (unsigned char *)name;
unsigned char *be = bp + strlen(name);
- rpmhookBucket *bucket;
+ rpmhookBucket bucket;
if (((*table)->used/2)*3 > (*table)->size)
rpmhookTableRehash(table);
int ret;
@@ -98,9 +90,9 @@ int rpmhookTableFindBucket(rpmhookTable **table, const char *name)
return ret;
}
-void rpmhookTableRehash(rpmhookTable **table)
+static void rpmhookTableRehash(rpmhookTable *table)
{
- rpmhookTable *newtable = rpmhookTableNew((*table)->size*2);
+ rpmhookTable newtable = rpmhookTableNew((*table)->size*2);
int n, i = 0;
for (; i != (*table)->size; i++) {
if ((*table)->bucket[i].name) {
@@ -114,55 +106,58 @@ void rpmhookTableRehash(rpmhookTable **table)
*table = newtable;
}
-void rpmhookTableAddItem(rpmhookTable **table, const char *name,
- rpmhookFunc func, void *data)
+static void rpmhookTableAddItem(rpmhookTable *table, const char *name,
+ rpmhookFunc func, void *data)
{
int n = rpmhookTableFindBucket(table, name);
- rpmhookBucket *bucket = &(*table)->bucket[n];
- rpmhookItem **item = &bucket->item;
+ rpmhookBucket bucket = &(*table)->bucket[n];
+ rpmhookItem *item = &bucket->item;
if (!bucket->name) {
bucket->name = strdup(name);
(*table)->used++;
}
while (*item) item = &(*item)->next;
- *item = calloc(1, sizeof(rpmhookItem));
+ *item = calloc(1, sizeof(struct rpmhookItem_s));
(*item)->func = func;
(*item)->data = data;
}
-void rpmhookTableDelItem(rpmhookTable **table, const char *name,
- rpmhookFunc func, void *data)
+static void rpmhookTableDelItem(rpmhookTable *table, const char *name,
+ rpmhookFunc func, void *data,
+ int matchfunc, int matchdata)
{
int n = rpmhookTableFindBucket(table, name);
- rpmhookBucket *bucket = &(*table)->bucket[n];
- rpmhookItem *item = bucket->item;
- rpmhookItem *lastItem = NULL;
- while (item && item->func != func
- && (data == NULL || item->data == data)) {
- lastItem = item;
- item = item->next;
- }
- if (item) {
- if (lastItem)
- lastItem->next = item->next;
- else
- bucket->item = item->next;
- free(item);
- if (!bucket->item) {
- free(bucket->name);
- bucket->name = NULL;
- (*table)->used--;
+ rpmhookBucket bucket = &(*table)->bucket[n];
+ rpmhookItem item = bucket->item;
+ rpmhookItem lastItem = NULL;
+ rpmhookItem nextItem;
+ while (item) {
+ nextItem = item->next;
+ if ((!matchfunc || item->func == func) &&
+ (!matchdata || item->data == data)) {
+ free(item);
+ if (lastItem)
+ lastItem->next = nextItem;
+ else
+ bucket->item = nextItem;
+ } else {
+ lastItem = item;
}
+ item = nextItem;
+ }
+ if (!bucket->item) {
+ free(bucket->name);
+ bucket->name = NULL;
+ (*table)->used--;
}
}
-rpmhookArgs *rpmhookArgsParse(const char *argt, va_list ap)
+static rpmhookArgs rpmhookArgsParse(const char *argt, va_list ap)
{
int argc = strlen(argt);
int i;
- rpmhookArgs *args =
- (rpmhookArgs *)malloc(sizeof(rpmhookArgs)+
- (argc-1)*sizeof(rpmhookArgv));
+ rpmhookArgs args = (rpmhookArgs)malloc(sizeof(struct rpmhookArgs_s)+
+ (argc-1)*sizeof(rpmhookArgv));
args->argc = argc;
args->argt = argt;
for (i = 0; i != argc; i++) {
@@ -180,58 +175,66 @@ rpmhookArgs *rpmhookArgsParse(const char *argt, va_list ap)
args->argv[i].p = va_arg(ap, void *);
break;
default:
- fprintf(stderr,
- "error: unsupported type '%c' as "
- "a hook argument\n");
+ fprintf(stderr, "error: unsupported type '%c' as "
+ "a hook argument\n", argt[i]);
break;
}
}
return args;
}
-void rpmhookTableCall(rpmhookTable **table, const char *name,
- const char *argt, ...)
+static void rpmhookTableCallV(rpmhookTable *table, const char *name,
+ const char *argt, va_list ap)
{
- rpmhookItem *item;
- rpmhookArgs *args;
+ rpmhookItem item;
+ rpmhookArgs args;
int n;
- va_list ap;
- va_start(ap, argt);
args = rpmhookArgsParse(argt, ap);
- va_end(ap);
n = rpmhookTableFindBucket(table, name);
item = (*table)->bucket[n].item;
while (item) {
- item->func(args, item->data);
+ if (item->func(args, item->data) != 0)
+ break;
item = item->next;
}
free(args);
}
-int myhook(rpmhookArgs *args, void *data)
+static rpmhookTable globalTable = NULL;
+
+void rpmhookRegister(const char *name, rpmhookFunc func, void *data)
{
- printf("%s: %d\n", args->argv[0].s, data);
+ if (!globalTable)
+ globalTable = rpmhookTableNew(RPMHOOK_TABLE_INITSIZE);
+ rpmhookTableAddItem(&globalTable, name, func, data);
}
-int main()
+void rpmhookUnregister(const char *name, rpmhookFunc func, void *data)
{
- rpmhookTable *table = rpmhookTableNew(RPMHOOK_TABLE_INITSIZE);
- int i;
- char buf[BUFSIZ];
- for (i = 0; i != 100000; i++) {
- sprintf(buf, "%d", i);
- rpmhookTableAddItem(&table, buf, myhook, (void *)i);
- }
- for (i = 0; i != 100000; i++) {
- sprintf(buf, "%d", i);
- rpmhookTableCall(&table, buf, "s", "Hello world!");
- }
- for (i = 0; i != 100000; i++) {
- sprintf(buf, "%d", i);
- rpmhookTableDelItem(&table, buf, myhook, (void *)i);
+ if (globalTable)
+ rpmhookTableDelItem(&globalTable, name, func, data, 1, 1);
+}
+
+void rpmhookUnregisterAny(const char *name, rpmhookFunc func)
+{
+ if (globalTable)
+ rpmhookTableDelItem(&globalTable, name, func, NULL, 1, 0);
+}
+
+void rpmhookUnregisterAll(const char *name)
+{
+ if (globalTable)
+ rpmhookTableDelItem(&globalTable, name, NULL, NULL, 0, 0);
+}
+
+void rpmhookCall(const char *name, const char *argt, ...)
+{
+ if (globalTable) {
+ va_list ap;
+ va_start(ap, argt);
+ rpmhookTableCallV(&globalTable, name, argt, ap);
+ va_end(ap);
}
- rpmhookTableFree(table);
- return 0;
}
/* vim:ts=4:sw=4:et
diff --git a/rpmio/rpmhook.h b/rpmio/rpmhook.h
new file mode 100644
index 000000000..b80f496e0
--- /dev/null
+++ b/rpmio/rpmhook.h
@@ -0,0 +1,28 @@
+#ifndef RPMHOOK_H
+#define RPMHOOK_H
+
+typedef union {
+ char *s;
+ int i;
+ float f;
+ void *p;
+} rpmhookArgv;
+
+typedef struct rpmhookArgs_s {
+ int argc;
+ const char *argt;
+ rpmhookArgv argv[1];
+} * rpmhookArgs;
+
+typedef int (*rpmhookFunc)(rpmhookArgs args, void *data);
+
+void rpmhookRegister(const char *name, rpmhookFunc func, void *data);
+void rpmhookUnregister(const char *name, rpmhookFunc func, void *data);
+void rpmhookUnregisterAny(const char *name, rpmhookFunc func);
+void rpmhookUnregisterAll(const char *name);
+void rpmhookCall(const char *name, const char *argt, ...);
+
+#endif
+
+/* vim:ts=4:sw=4:et
+ */