1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
/* This file is part of GNU Dico.
Copyright (C) 2024 Sergey Poznyakoff
GNU Dico is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Dico 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.
You should have received a copy of the GNU General Public License
along with GNU Dico. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <string.h>
#include <errno.h>
#include <dico.h>
#include <dico/conv.h>
static dico_list_t /* of struct dico_conv */ conv_list;
static int
conv_name_cmp(const void *item, const void *data, void *unused)
{
dico_conv_t p = (dico_conv_t) item;
const char *name = data;
return strcmp(p->name, name);
}
static int
conv_free(void *item, void *data)
{
free(item);
return 0;
}
int
dico_conv_register(char const *name, dico_convfun_t fun, void *data)
{
dico_conv_t cp;
if (!conv_list) {
conv_list = dico_list_create();
if (!conv_list)
return -1;
dico_list_set_comparator(conv_list, conv_name_cmp, NULL);
dico_list_set_free_item(conv_list, conv_free, NULL);
}
if (dico_conv_find(name)) {
errno = EEXIST;
return -1;
}
cp = malloc(sizeof(*cp) + strlen(name) + 1);
if (!cp)
return -1;
cp->name = (char*)(cp + 1);
strcpy(cp->name, name);
cp->conv = fun;
cp->data = data;
dico_list_append(conv_list, cp);
return 0;
}
dico_conv_t
dico_conv_find(char const *name)
{
return dico_list_locate(conv_list, (void*)name);
}
int
dico_conv_apply(dico_list_t list, char const *input, char **output)
{
dico_iterator_t itr;
dico_conv_t cp;
char *tmp = NULL;
itr = dico_list_iterator(list);
if (!itr)
return -1;
for (cp = dico_iterator_first(itr); cp; cp = dico_iterator_next(itr)) {
int rc;
char *p;
rc = cp->conv(cp->data, input, &p);
free(tmp);
if (rc) {
free(p);
return rc;
}
tmp = p;
input = tmp;
}
dico_iterator_destroy(&itr);
*output = tmp;
return 0;
}
|