/* * This file is part of the Poliqarp suite. * * Copyright (C) 2004-2009 by Instytut Podstaw Informatyki Polskiej * Akademii Nauk (IPI PAN; Institute of Computer Science, Polish * Academy of Sciences; cf. www.ipipan.waw.pl). All rights reserved. * * This file may be distributed and/or modified under the terms of the * GNU General Public License version 2 as published by the Free Software * Foundation and appearing in the file gpl.txt included in the packaging * of this file. (See http://www.gnu.org/licenses/translations.html for * unofficial translations.) * * A commercial license is available from IPI PAN (contact * Michal.Ciesiolka@ipipan.waw.pl or ipi@ipipan.waw.pl for more * information). Licensees holding a valid commercial license from IPI * PAN may use this file in accordance with that license. * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. */ #include <errno.h> #include <sakura/meta-value.h> static size_t meta_key_lookup(const struct poliqarp_corpus *corpus, const char *key) { const struct poliqarp_backend_meta *backend_meta = poliqarp_get_const_backend(corpus, meta); size_t num_keys = poliqarp_backend_meta_num_keys(backend_meta); size_t i; for (i = 0; i < num_keys; ++i) if (strcmp(key, poliqarp_backend_meta_key_fetch(backend_meta, i)) == 0) break; if (i == num_keys) { errno = ENOENT; return (size_t)-1; } return i; } struct poliqarp_meta_value *poliqarp_meta_value_create_date( const struct poliqarp_corpus *corpus, const char *key_text, struct poliqarp_meta_date date, enum poliqarp_meta_match_strategy strategy) { struct poliqarp_meta_value *this; size_t key; key = meta_key_lookup(corpus, key_text); if (key == (size_t)-1) return NULL; this = malloc(sizeof *this); this->domain = POLIQARP_DOMAIN_DATE; this->strategy = strategy; this->key = key; this->value_as.date = date; return this; } struct poliqarp_meta_value *poliqarp_meta_value_create_undefined( const struct poliqarp_corpus *corpus, const char *key_text) { struct poliqarp_meta_value *this; size_t key; key = meta_key_lookup(corpus, key_text); if (key == (size_t)-1) return NULL; this = malloc(sizeof *this); this->domain = POLIQARP_DOMAIN_UNDEFINED; this->strategy = POLIQARP_STRATEGY_EQUAL; this->key = key; return this; } struct poliqarp_meta_value *poliqarp_meta_value_create_text( const struct poliqarp_corpus *corpus, const char *key_text, const struct poliqarp_regexp *pattern) { struct poliqarp_meta_value *this; size_t key; key = meta_key_lookup(corpus, key_text); if (key == (size_t)-1) return NULL; this = malloc(sizeof *this); this->domain = POLIQARP_DOMAIN_TEXT; this->strategy = POLIQARP_STRATEGY_EQUAL; this->key = key; this->value_as.value_pattern = *pattern; return this; } void poliqarp_meta_value_destroy(struct poliqarp_meta_value *this) { switch (this->domain) { case POLIQARP_DOMAIN_DATE: break; case POLIQARP_DOMAIN_TEXT: poliqarp_regexp_destroy(&this->value_as.value_pattern); break; case POLIQARP_DOMAIN_UNDEFINED: break; } free(this); } bool poliqarp_meta_value_can_be_optimized(const struct poliqarp_meta_value *this, const struct poliqarp_meta_value *that, enum poliqarp_logic_operator oper) { /* TODO */ return false; } struct poliqarp_value *poliqarp_meta_value_optimize( const struct poliqarp_meta_value *this, const struct poliqarp_meta_value *that, enum poliqarp_logic_operator oper) { abort(); /* See the TODO above. */ } int poliqarp_meta_value_compare(const struct poliqarp_meta_value *this, const struct poliqarp_meta_value *that) { return this == that ? 0 : 1; } static int compare_date(struct poliqarp_meta_date d1, struct poliqarp_meta_date d2) { return d1.year != d2.year ? d1.year - d2.year : d1.month != d2.month ? d1.month - d2.month : d1.day - d2.day; } bool poliqarp_meta_value_eval(const struct poliqarp_meta_value *this, const struct poliqarp_corpus *corpus, const struct poliqarp_document *document) { const struct poliqarp_backend_meta *backend_meta = poliqarp_get_const_backend(corpus, meta); struct poliqarp_binary_metadata meta; int i; switch (this->domain) { case POLIQARP_DOMAIN_DATE: for (i = document->meta_high - document->meta_low; i > 0; --i) { meta = poliqarp_backend_meta_fetch(backend_meta, document->meta_high - i); if (meta.type == POLIQARP_METADATA_DATE && meta.key == this->key) switch (this->strategy) { case POLIQARP_STRATEGY_EQUAL: return compare_date(meta.value_as.date, this->value_as.date) == 0; case POLIQARP_STRATEGY_GREATER: return compare_date(meta.value_as.date, this->value_as.date) > 0; case POLIQARP_STRATEGY_GREATER_EQUAL: return compare_date(meta.value_as.date, this->value_as.date) >= 0; case POLIQARP_STRATEGY_SMALLER: return compare_date(meta.value_as.date, this->value_as.date) < 0; case POLIQARP_STRATEGY_SMALLER_EQUAL: return compare_date(meta.value_as.date, this->value_as.date) <= 0; default: abort(); /* Should not happen. */ } } return false; case POLIQARP_DOMAIN_TEXT: for (i = document->meta_high - document->meta_low; i > 0; --i) { meta = poliqarp_backend_meta_fetch(backend_meta, document->meta_high - i); if ((meta.type == POLIQARP_METADATA_SINGLE || meta.type == POLIQARP_METADATA_MULTI) && meta.key == this->key) { if (poliqarp_regexp_match(&this->value_as.value_pattern, poliqarp_backend_meta_value_fetch(backend_meta, meta.value_as.text))) { return true; } } } return false; case POLIQARP_DOMAIN_UNDEFINED: for (i = document->meta_high - document->meta_low; i > 0; --i) { meta = poliqarp_backend_meta_fetch(backend_meta, document->meta_high - i); if (meta.type == POLIQARP_METADATA_UNDEFINED && meta.key == this->key) return true; } return false; default: abort(); /* Should not happen. */ } /* switch(this->domain) */ } void poliqarp_meta_value_modify(struct poliqarp_meta_value *this, enum poliqarp_meta_match_strategy strategy) { this->strategy = strategy; } /** * Parses the text of the form 'yearSEPmonthSEPday' to produce a * metadata date value. SEP can be any non-digit character. * If day or month and day are omitted, the result has 0 on the respective * field. * * Returns 0 if the expression was successfully formed, -1 if a parse error * occurred. */ int poliqarp_meta_date_parse(const char *text, struct poliqarp_meta_date *date) { char *ptr; unsigned long val; date->year = date->month = date->day = 0; if (text[0] == '\0') return -1; val = strtoul(text, &ptr, 10); date->year = val; if (date->year != val || val == 0) return -1; /* integer overflow or 0 */ if (ptr[0] == '\0') return 0; if (ptr[1] == '\0') return -1; /* no digits after separator */ val = strtoul(ptr + 1, &ptr, 10); date->month = val; if (date->month != val || val == 0 || val > 12) return -1; /* integer overflow or invalid month */ if (ptr[0] == '\0') return 0; if (ptr[1] == '\0') return -1; /* no digits after separator */ val = strtoul(ptr + 1, &ptr, 10); date->day = val; if (date->day != val || val == 0 || val > 31) return -1; /* integer overflow or invalid day */ if (ptr[0] == '\0') return 0; else return -1; /* trailing garbage */ }