1 /* $Id: zebramap.c,v 1.70 2007-11-08 13:35:36 adam Exp $
2 Copyright (C) 1995-2007
5 This file is part of the Zebra server.
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra. If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
29 #include <yaz/yaz-util.h>
36 #define ZEBRA_MAP_TYPE_SORT 1
37 #define ZEBRA_MAP_TYPE_INDEX 2
38 #define ZEBRA_MAP_TYPE_STATICRANK 3
40 #define ZEBRA_REPLACE_ANY 300
56 const char *maptab_name;
57 zebra_maps_t zebra_maps;
62 struct icu_chain *icu_chain;
66 struct zebra_map *next;
74 const char *temp_map_ptr[2];
81 void zebra_maps_close(zebra_maps_t zms)
83 struct zebra_map *zm = zms->map_list;
87 chrmaptab_destroy(zm->maptab);
90 icu_chain_destroy(zm->icu_chain);
95 wrbuf_destroy(zm->simple_buf);
98 wrbuf_destroy(zms->wrbuf_1);
99 nmem_destroy(zms->nmem);
103 zebra_map_t zebra_add_map(zebra_maps_t zms, const char *index_type,
106 zebra_map_t zm = (zebra_map_t) nmem_malloc(zms->nmem, sizeof(*zm));
108 zm->zebra_maps = zms;
109 zm->id = nmem_strdup(zms->nmem, index_type);
114 zm->completeness = 0;
116 zm->alwaysmatches = 0;
117 zm->first_in_field = 0;
120 zms->last_map->next = zm;
131 zm->simple_buf = wrbuf_alloc();
135 static int parse_command(zebra_maps_t zms, int argc, char **argv,
136 const char *fname, int lineno)
138 zebra_map_t zm = zms->last_map;
141 yaz_log(YLOG_WARN, "%s:%d: Missing arguments for '%s'",
142 fname, lineno, argv[0]);
147 yaz_log(YLOG_WARN, "%s:%d: Too many arguments for '%s'",
148 fname, lineno, argv[0]);
151 if (!yaz_matchstr(argv[0], "index"))
153 zm = zebra_add_map(zms, argv[1], ZEBRA_MAP_TYPE_INDEX);
156 else if (!yaz_matchstr(argv[0], "sort"))
158 zm = zebra_add_map(zms, argv[1], ZEBRA_MAP_TYPE_SORT);
159 zm->u.sort.entry_size = 80;
161 else if (!yaz_matchstr(argv[0], "staticrank"))
163 zm = zebra_add_map(zms, argv[1], ZEBRA_MAP_TYPE_STATICRANK);
164 zm->completeness = 1;
168 yaz_log(YLOG_WARN, "%s:%d: Missing sort/index before '%s'",
169 fname, lineno, argv[0]);
172 else if (!yaz_matchstr(argv[0], "charmap") && argc == 2)
174 if (zm->type != ZEBRA_MAP_TYPE_STATICRANK)
175 zm->maptab_name = nmem_strdup(zms->nmem, argv[1]);
178 yaz_log(YLOG_WARN|YLOG_FATAL, "%s:%d: charmap for "
179 "staticrank is invalid", fname, lineno);
180 yaz_log(YLOG_LOG, "Type is %d", zm->type);
184 else if (!yaz_matchstr(argv[0], "completeness") && argc == 2)
186 zm->completeness = atoi(argv[1]);
188 else if (!yaz_matchstr(argv[0], "position") && argc == 2)
190 zm->positioned = atoi(argv[1]);
192 else if (!yaz_matchstr(argv[0], "alwaysmatches") && argc == 2)
194 if (zm->type != ZEBRA_MAP_TYPE_STATICRANK)
195 zm->alwaysmatches = atoi(argv[1]);
198 yaz_log(YLOG_WARN|YLOG_FATAL, "%s:%d: alwaysmatches for "
199 "staticrank is invalid", fname, lineno);
203 else if (!yaz_matchstr(argv[0], "firstinfield") && argc == 2)
205 zm->first_in_field = atoi(argv[1]);
207 else if (!yaz_matchstr(argv[0], "entrysize") && argc == 2)
209 if (zm->type == ZEBRA_MAP_TYPE_SORT)
210 zm->u.sort.entry_size = atoi(argv[1]);
214 "%s:%d: entrysize only valid in sort section",
219 else if (!yaz_matchstr(argv[0], "simplechain"))
226 else if (!yaz_matchstr(argv[0], "icuchain"))
229 zm->doc = xmlParseFile(argv[1]);
232 yaz_log(YLOG_WARN, "%s:%d: Could not load icuchain config '%s'",
233 fname, lineno, argv[1]);
240 xmlNode *xml_node = xmlDocGetRootElement(zm->doc);
242 icu_chain_xml_config(xml_node,
243 /* not sure about sort for this function yet.. */
247 zm->type == ZEBRA_MAP_TYPE_SORT,
252 yaz_log(YLOG_WARN, "%s:%d: Failed to load ICU chain %s",
253 fname, lineno, argv[1]);
257 yaz_log(YLOG_WARN, "%s:%d: ICU support unavailable",
263 yaz_log(YLOG_WARN, "%s:%d: XML support unavailable",
270 yaz_log(YLOG_WARN, "%s:%d: Unrecognized directive '%s'",
271 fname, lineno, argv[0]);
277 ZEBRA_RES zebra_maps_read_file(zebra_maps_t zms, const char *fname)
286 if (!(f = yaz_fopen(zms->tabpath, fname, "r", zms->tabroot)))
288 yaz_log(YLOG_ERRNO|YLOG_FATAL, "%s", fname);
291 while ((argc = readconf_line(f, &lineno, line, 512, argv, 10)))
293 int r = parse_command(zms, argc, argv, fname, lineno);
302 (zms->no_files_read)++;
306 zebra_maps_t zebra_maps_open(Res res, const char *base_path,
307 const char *profile_path)
309 zebra_maps_t zms = (zebra_maps_t) xmalloc(sizeof(*zms));
311 zms->nmem = nmem_create();
312 zms->tabpath = profile_path ? nmem_strdup(zms->nmem, profile_path) : 0;
315 zms->tabroot = nmem_strdup(zms->nmem, base_path);
319 zms->temp_map_str[0] = '\0';
320 zms->temp_map_str[1] = '\0';
322 zms->temp_map_ptr[0] = zms->temp_map_str;
323 zms->temp_map_ptr[1] = NULL;
325 zms->wrbuf_1 = wrbuf_alloc();
327 zms->no_files_read = 0;
331 zebra_map_t zebra_map_get(zebra_maps_t zms, const char *id)
334 for (zm = zms->map_list; zm; zm = zm->next)
335 if (!strcmp(zm->id, id))
340 zebra_map_t zebra_map_get_or_add(zebra_maps_t zms, const char *id)
342 struct zebra_map *zm = zebra_map_get(zms, id);
345 zm = zebra_add_map(zms, id, ZEBRA_MAP_TYPE_INDEX);
347 /* no reason to warn if no maps are read from file */
348 if (zms->no_files_read)
349 yaz_log(YLOG_WARN, "Unknown register type: %s", id);
351 zm->maptab_name = nmem_strdup(zms->nmem, "@");
352 zm->completeness = 0;
358 chrmaptab zebra_charmap_get(zebra_map_t zm)
362 if (!zm->maptab_name || !yaz_matchstr(zm->maptab_name, "@"))
364 if (!(zm->maptab = chrmaptab_create(zm->zebra_maps->tabpath,
366 zm->zebra_maps->tabroot)))
367 yaz_log(YLOG_WARN, "Failed to read character table %s",
370 yaz_log(YLOG_DEBUG, "Read character table %s", zm->maptab_name);
375 const char **zebra_maps_input(zebra_map_t zm,
376 const char **from, int len, int first)
378 chrmaptab maptab = zebra_charmap_get(zm);
380 return chr_map_input(maptab, from, len, first);
382 zm->zebra_maps->temp_map_str[0] = **from;
385 return zm->zebra_maps->temp_map_ptr;
388 const char **zebra_maps_search(zebra_map_t zm,
389 const char **from, int len, int *q_map_match)
394 maptab = zebra_charmap_get(zm);
398 map = chr_map_q_input(maptab, from, len, 0);
404 map = chr_map_input(maptab, from, len, 0);
408 zm->zebra_maps->temp_map_str[0] = **from;
411 return zm->zebra_maps->temp_map_ptr;
414 const char *zebra_maps_output(zebra_map_t zm,
417 chrmaptab maptab = zebra_charmap_get(zm);
420 return chr_map_output(maptab, from, 1);
424 /* ------------------------------------ */
426 int zebra_maps_is_complete(zebra_map_t zm)
429 return zm->completeness;
433 int zebra_maps_is_positioned(zebra_map_t zm)
436 return zm->positioned;
440 int zebra_maps_is_index(zebra_map_t zm)
443 return zm->type == ZEBRA_MAP_TYPE_INDEX;
447 int zebra_maps_is_staticrank(zebra_map_t zm)
450 return zm->type == ZEBRA_MAP_TYPE_STATICRANK;
454 int zebra_maps_is_sort(zebra_map_t zm)
457 return zm->type == ZEBRA_MAP_TYPE_SORT;
461 int zebra_maps_is_alwaysmatches(zebra_map_t zm)
464 return zm->alwaysmatches;
468 int zebra_maps_is_first_in_field(zebra_map_t zm)
471 return zm->first_in_field;
475 int zebra_maps_sort(zebra_maps_t zms, Z_SortAttributes *sortAttributes,
481 attr_init_AttrList(&use, sortAttributes->list, 1);
482 attr_init_AttrList(&structure, sortAttributes->list, 4);
485 structure_value = attr_find(&structure, 0);
486 if (structure_value == 109)
488 return attr_find(&use, NULL);
491 int zebra_maps_attr(zebra_maps_t zms, Z_AttributesPlusTerm *zapt,
492 const char **index_type, char **search_type, char *rank_type,
493 int *complete_flag, int *sort_flag)
495 AttrType completeness;
498 AttrType sort_relation;
501 int completeness_value;
503 const char *structure_str = 0;
505 int sort_relation_value;
509 attr_init_APT(&structure, zapt, 4);
510 attr_init_APT(&completeness, zapt, 6);
511 attr_init_APT(&relation, zapt, 2);
512 attr_init_APT(&sort_relation, zapt, 7);
513 attr_init_APT(&weight, zapt, 9);
514 attr_init_APT(&use, zapt, 1);
516 completeness_value = attr_find(&completeness, NULL);
517 structure_value = attr_find_ex(&structure, NULL, &structure_str);
518 relation_value = attr_find(&relation, NULL);
519 sort_relation_value = attr_find(&sort_relation, NULL);
520 weight_value = attr_find(&weight, NULL);
521 use_value = attr_find(&use, NULL);
523 if (completeness_value == 2 || completeness_value == 3)
529 *sort_flag =(sort_relation_value > 0) ? 1 : 0;
530 *search_type = "phrase";
531 strcpy(rank_type, "void");
532 if (relation_value == 102)
534 if (weight_value == -1)
536 sprintf(rank_type, "rank,w=%d,u=%d", weight_value, use_value);
542 switch (structure_value)
544 case 6: /* word list */
545 *search_type = "and-list";
547 case 105: /* free-form-text */
548 *search_type = "or-list";
550 case 106: /* document-text */
551 *search_type = "or-list";
556 case 108: /* string */
557 *search_type = "phrase";
559 case 107: /* local-number */
560 *search_type = "local";
563 case 109: /* numeric string */
565 *search_type = "numeric";
569 *search_type = "phrase";
573 *search_type = "phrase";
577 *search_type = "phrase";
581 *search_type = "phrase";
584 if (structure_str && *structure_str)
585 *index_type = structure_str;
595 WRBUF zebra_replace(zebra_map_t zm, const char *ex_list,
596 const char *input_str, int input_len)
598 wrbuf_rewind(zm->zebra_maps->wrbuf_1);
599 wrbuf_write(zm->zebra_maps->wrbuf_1, input_str, input_len);
600 return zm->zebra_maps->wrbuf_1;
603 #define SE_CHARS ";,.()-/?<> \r\n\t"
605 static int tokenize_simple(zebra_map_t zm,
606 const char **result_buf, size_t *result_len)
608 char *buf = wrbuf_buf(zm->simple_buf);
609 size_t len = wrbuf_len(zm->simple_buf);
610 size_t i = zm->simple_off;
613 while (i < len && strchr(SE_CHARS, buf[i]))
616 while (i < len && !strchr(SE_CHARS, buf[i]))
618 if (buf[i] > 32 && buf[i] < 127)
619 buf[i] = tolower(buf[i]);
626 *result_buf = buf + start;
627 *result_len = i - start;
633 int zebra_map_tokenize(zebra_map_t zm,
634 const char *buf, size_t len,
635 const char **result_buf, size_t *result_len)
637 assert(zm->use_chain);
641 wrbuf_rewind(zm->simple_buf);
642 wrbuf_write(zm->simple_buf, buf, len);
648 return tokenize_simple(zm, result_buf, result_len);
654 yaz_log(YLOG_LOG, "assicn_cstr %s", wrbuf_cstr(zm->simple_buf));
655 icu_chain_assign_cstr(zm->icu_chain,
656 wrbuf_cstr(zm->simple_buf),
658 assert(U_SUCCESS(status));
660 while (icu_chain_next_token(zm->icu_chain, &status))
662 assert(U_SUCCESS(status));
663 *result_buf = icu_chain_token_norm(zm->icu_chain);
665 yaz_log(YLOG_LOG, "got result %s", *result_buf);
666 *result_len = strlen(*result_buf);
667 if (**result_buf != '\0')
670 assert(U_SUCCESS(status));
674 return tokenize_simple(zm, result_buf, result_len);
678 int zebra_maps_is_icu(zebra_map_t zm)
681 return zm->use_chain;
691 * indent-tabs-mode: nil
693 * vim: shiftwidth=4 tabstop=8 expandtab