fs_value fn_greater_than_equal(fs_query *q, fs_value a, fs_value b) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (b.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return b; } /* URIs and bNodes don't compare */ if (FS_IS_URI_BN(a.rid) || FS_IS_URI_BN(b.rid)) { return fs_value_boolean(0); } /* If it's simply the same term it must be <= itsself */ fs_value term_eq = fn_rdfterm_equal(q, a, b); if (term_eq.in == 1) { return term_eq; } if (a.attr == fs_c.xsd_datetime && b.attr == fs_c.xsd_datetime) return fn_not(q, fn_datetime_less_than(q, a, b)); if (fs_is_numeric(&a) && fs_is_numeric(&b)) return fn_logical_or(q, fn_numeric_greater_than(q, a, b), fn_numeric_equal(q, a, b)); if (FS_IS_URI_BN(a.rid) || FS_IS_URI_BN(b.rid)) return fs_value_boolean(0); if (a.lex && b.lex) return fn_not(q, fn_numeric_equal(q,fn_compare(q, a, b), fs_value_integer(-1))); return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); }
fs_value fn_numeric_equal(fs_query *q, fs_value a, fs_value b) { #if 0 fs_value_print(a); printf(" "); fs_value_print(b); printf("\n"); #endif a = fs_value_promote(q, a, b); b = fs_value_promote(q, b, a); if (a.attr == b.attr && a.attr != FS_RID_NULL && a.attr != fs_c.empty) { if (a.attr == fs_c.xsd_double || a.attr == fs_c.xsd_float) { return fs_value_boolean(a.fp == b.fp); } if (a.attr == fs_c.xsd_decimal) { return fs_value_boolean(fs_decimal_equal(&a.de, &b.de)); } if (a.attr == fs_c.xsd_integer) { return fs_value_boolean(a.in == b.in); } if (a.attr == fs_c.xsd_boolean) { return fs_value_boolean((a.in ? 1 : 0) == (b.in ? 1 : 0)); } } return fs_value_error(FS_ERROR_INVALID_TYPE, "non-numeric arguments to fn:numeric-equal"); }
fs_value fs_value_resource(fs_query *q, fs_resource *r) { fs_value v = fs_value_blank(); v.lex = r->lex; if (r->rid == FS_RID_NULL) { return fs_value_rid(FS_RID_NULL); } if (r->attr == fs_c.xsd_integer) { v = fn_cast_intl(q, v, fs_c.xsd_integer); } else if (r->attr == fs_c.xsd_float || r->attr == fs_c.xsd_double) { v = fn_cast_intl(q, v, fs_c.xsd_double); } else if (r->attr == fs_c.xsd_decimal) { v = fn_cast_intl(q, v, fs_c.xsd_decimal); } else if (r->attr == fs_c.xsd_boolean) { if (!strcmp(r->lex, "true") || !strcmp(r->lex, "1")) { v = fs_value_boolean(1); } else { v = fs_value_boolean(0); } } else if (r->attr == fs_c.xsd_datetime) { v = fs_value_datetime_from_string(r->lex); } if (fs_is_error(v)) { v = fs_value_blank(); v.lex = r->lex; } v.rid = r->rid; v.attr = r->attr; v.valid |= fs_valid_bit(FS_V_RID) | fs_valid_bit(FS_V_ATTR); return v; }
fs_value fn_lang_matches(fs_query *q, fs_value l, fs_value p) { if (fs_is_error(l)) { return l; } if (fs_is_error(p)) { return p; } if (l.valid & fs_valid_bit(FS_V_RID) && l.rid == FS_RID_NULL) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } if (l.lex && l.lex[0] == '\0') { return fs_value_boolean(0); } if (p.lex && p.lex[0] == '*' && p.lex[1] == '\0') { return fs_value_boolean(1); } if (l.lex && p.lex) { /* TODO implement RFC3066 */ return fs_value_boolean(!strncasecmp(l.lex, p.lex, strlen(p.lex))); } return fs_value_boolean(0); }
fs_value fn_equal(fs_query *q, fs_value a, fs_value b) { #if 0 fs_value_print(a); printf(" = "); fs_value_print(b); printf("\n"); #endif if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (b.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return b; } fs_value term_equal = fn_rdfterm_equal(q, a, b); if (term_equal.in == 1) { return term_equal; } if (a.attr == fs_c.xsd_datetime) return fn_datetime_equal(q, a, b); if (fs_is_numeric(&a) && fs_is_numeric(&b)) return fn_numeric_equal(q, a, b); if (FS_IS_LITERAL(a.rid) && FS_IS_LITERAL(b.rid) && (a.attr == fs_c.empty || a.attr == fs_c.xsd_string) && (b.attr == fs_c.empty || b.attr == fs_c.xsd_string)) { return fs_value_boolean(!strcmp(a.lex, b.lex)); } return fs_value_boolean(0); }
fs_value fn_numeric_less_than(fs_query *q, fs_value a, fs_value b) { a = fs_value_promote(q, a, b); b = fs_value_promote(q, b, a); #if 0 fs_value_print(a); printf(" < "); fs_value_print(b); printf("\n"); #endif if (a.attr == b.attr && a.attr != FS_RID_NULL && a.attr != fs_c.empty) { if (a.attr == fs_c.xsd_double || a.attr == fs_c.xsd_float) { return fs_value_boolean(a.fp < b.fp); } if (a.attr == fs_c.xsd_decimal) { return fs_value_boolean(fs_decimal_less_than(&a.de, &b.de)); } if (a.attr == fs_c.xsd_integer) { return fs_value_boolean(a.in < b.in); } } return fs_value_error(FS_ERROR_INVALID_TYPE, "non-numeric arguments to fn:numeric-less-than"); }
fs_value fn_is_literal(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID)) { return fs_value_boolean(FS_IS_LITERAL(a.rid)); } return fs_value_boolean(a.attr != FS_RID_NULL); }
fs_value fn_bound(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID)) { return fs_value_boolean(a.rid != FS_RID_NULL); } return fs_value_boolean(1); }
fs_value fn_datetime_greater_than(fs_query *q, fs_value a, fs_value b) { if (a.attr == fs_c.xsd_datetime && b.attr == fs_c.xsd_datetime && (a.in != -1 || b.in != -1)) return fs_value_boolean(a.in > b.in); if (a.lex && b.lex) { return fs_value_boolean(iso8601_compare(a.lex, b.lex) == 1); } return fs_value_error(FS_ERROR_INVALID_TYPE, "bad arguments to fn:datetime-greater-than"); }
fs_value fn_is_blank(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID)) { if (a.rid == FS_RID_NULL) return fs_value_boolean(0); return fs_value_boolean(FS_IS_BNODE(a.rid)); } return fs_value_boolean(0); }
fs_value fn_is_iri(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID)) { return fs_value_boolean(FS_IS_URI(a.rid)); } if (a.attr == FS_RID_NULL) { return fs_value_boolean(1); } return fs_value_boolean(0); }
fs_value fn_datetime_equal(fs_query *q, fs_value a, fs_value b) { if (a.attr == fs_c.xsd_datetime && b.attr == fs_c.xsd_datetime) return fs_value_boolean(a.in == b.in); return fs_value_error(FS_ERROR_INVALID_TYPE, "bad arguments to fn:datetime-equal"); }
fs_value fn_datetime_greater_than(fs_query *q, fs_value a, fs_value b) { if (a.attr == fs_c.xsd_datetime && b.attr == fs_c.xsd_datetime) return fs_value_boolean(a.in > b.in); return fs_value_error(FS_ERROR_INVALID_TYPE, "bad arguments to fn:datetime-greater-than"); }
fs_value fn_not_equal(fs_query *q, fs_value a, fs_value b) { #if 0 fs_value_print(a); printf(" != "); fs_value_print(b); printf("\n"); #endif if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (b.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return b; } if (a.attr == fs_c.xsd_datetime) return fn_not(q, fn_datetime_equal(q, a, b)); if (fs_is_numeric(&a) && fs_is_numeric(&b)) return fn_not(q, fn_numeric_equal(q, a, b)); if ((a.attr == fs_c.empty || a.attr == fs_c.xsd_string) && (b.attr == fs_c.empty || b.attr == fs_c.xsd_string)) { return fs_value_boolean(strcmp(a.lex, b.lex)); } if ((FS_IS_URI_BN(a.rid) && FS_IS_LITERAL(b.rid)) || (FS_IS_LITERAL(a.rid) && FS_IS_URI_BN(b.rid))) { /* ones a URI/bNode and ones a literal, definatly different */ return fs_value_boolean(1); } if ((!FS_IS_URI(a.rid) && a.attr != fs_c.empty && FS_IS_LITERAL(a.attr) && !FS_IS_LITERAL(b.attr)) || (!FS_IS_URI(a.rid) && !FS_IS_LITERAL(a.attr) && b.attr != fs_c.empty && FS_IS_LITERAL(b.attr))) { /* one has a lang tag and one doesn't, definatly different */ return fs_value_boolean(1); } if (FS_IS_URI(a.attr) || FS_IS_URI(b.attr)) { /* at least one argument has an unknown datatype */ return fs_value_boolean(0); } return fn_not(q, fn_rdfterm_equal(q, a, b)); }
fs_value fn_strends(fs_query *q, fs_value arg1, fs_value arg2) { if (!fs_is_plain_or_string(arg1) || !fs_is_plain_or_string(arg2)) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } arg1 = fs_value_fill_lexical(q, arg1); arg2 = fs_value_fill_lexical(q, arg2); const int a1l = strlen(arg1.lex); const int a2l = strlen(arg2.lex); if (a2l > a1l) { return fs_value_boolean(0); } return fs_value_boolean(strncmp(arg1.lex + a1l - a2l, arg2.lex, a2l) == 0); }
fs_value fn_datetime_less_than(fs_query *q, fs_value a, fs_value b) { #if 0 fs_value_print(a); printf(" < "); fs_value_print(b); printf(" [dT]\n"); #endif if (a.attr == fs_c.xsd_datetime && b.attr == fs_c.xsd_datetime && (a.in != -1 || b.in != -1)) return fs_value_boolean(a.in < b.in); if (a.lex && b.lex) { return fs_value_boolean(iso8601_compare(a.lex, b.lex) == -1); } return fs_value_error(FS_ERROR_INVALID_TYPE, "bad arguments to fn:datetime-less-than"); }
fs_value fn_contains(fs_query *q, fs_value arg1, fs_value arg2) { if (!fs_is_plain_or_string(arg1) || !fs_is_plain_or_string(arg2)) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } arg1 = fs_value_fill_lexical(q, arg1); arg2 = fs_value_fill_lexical(q, arg2); return fs_value_boolean(strstr(arg1.lex, arg2.lex) != NULL); }
fs_value fn_numeric_greater_than(fs_query *q, fs_value a, fs_value b) { a = fs_value_promote(q, a, b); b = fs_value_promote(q, b, a); if (a.attr == b.attr && a.attr != FS_RID_NULL && a.attr != fs_c.empty) { if (a.attr == fs_c.xsd_double || a.attr == fs_c.xsd_float) { return fs_value_boolean(a.fp > b.fp); } if (a.attr == fs_c.xsd_decimal) { return fs_value_boolean(fs_decimal_greater_than(&a.de, &b.de)); } if (a.attr == fs_c.xsd_integer) { return fs_value_boolean(a.in > b.in); } } return fs_value_error(FS_ERROR_INVALID_TYPE, "non-numeric arguments to fn:numeric-greater-than"); }
fs_value fn_rdfterm_equal(fs_query *q, fs_value a, fs_value b) { if (fs_is_error(a)) { return a; } if (fs_is_error(b)) { return b; } return fs_value_boolean(fs_value_equal(a, b)); }
fs_value fn_datetime_less_than(fs_query *q, fs_value a, fs_value b) { #if 0 fs_value_print(a); printf(" < "); fs_value_print(b); printf(" [dT]\n"); #endif if (a.attr == fs_c.xsd_datetime && b.attr == fs_c.xsd_datetime) return fs_value_boolean(a.in < b.in); return fs_value_error(FS_ERROR_INVALID_TYPE, "bad arguments to fn:datetime-less-than"); }
fs_value fn_ebv(fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.rid == FS_RID_NULL) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } if (a.attr == fs_c.xsd_boolean || a.attr == fs_c.xsd_integer) { return fs_value_boolean(a.in); } if (a.attr == fs_c.xsd_double || a.attr == fs_c.xsd_float) { return fs_value_boolean(fabs(a.fp) != 0.0); } if (a.attr == fs_c.xsd_decimal) { return fs_value_boolean(!fs_decimal_equal(&a.de, fs_decimal_zero)); } if (a.lex && (a.attr == fs_c.xsd_string || a.attr == fs_c.empty)) { return fs_value_boolean(a.lex && a.lex[0]); } return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); }
fs_value fn_logical_or(fs_query *q, fs_value a, fs_value b) { fs_value ea = fn_ebv(a), eb = fn_ebv(b); if (!ea.in && fs_is_error(b)) { return b; } else if (!eb.in && fs_is_error(a)) { return a; } else if (fs_is_error(a) && fs_is_error(b)) { return a; } return fs_value_boolean(ea.in || eb.in); }
fs_value fn_not(fs_query *q, fs_value a) { #if 0 printf("! "); fs_value_print(a); printf("\n"); #endif if (fs_is_error(a)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID) && a.rid == FS_RID_NULL) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } fs_value ebv = fn_ebv(a); if (fs_is_error(ebv)) { return ebv; } return fs_value_boolean(!ebv.in); }
fs_value fn_matches(fs_query *q, fs_value str, fs_value pat, fs_value flags) { if (str.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return str; } if (pat.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return pat; } if (flags.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return flags; } if (!str.lex || !pat.lex) { return fs_value_error(FS_ERROR_INVALID_TYPE, "argument to fn:matches has no lexical value"); } if (str.valid & fs_valid_bit(FS_V_RID) && FS_IS_URI(str.rid)) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } #if 0 printf("REGEX "); fs_value_print(str); printf(", "); fs_value_print(pat); printf(", "); fs_value_print(flags); printf("\n"); #endif int reflags = PCRE_UTF8; if (flags.lex) { for (char *c = flags.lex; *c; c++) { switch (*c) { case 's': reflags |= PCRE_DOTALL; break; case 'm': reflags |= PCRE_MULTILINE; break; case 'i': reflags |= PCRE_CASELESS; break; case 'x': reflags |= PCRE_EXTENDED; break; default: fs_error(LOG_ERR, "unknown regex flag '%c'", *c); return fs_value_error(FS_ERROR_INVALID_TYPE, "unrecognised flag in fn:matches"); } } } const char *error; int erroroffset; pcre *re = pcre_compile(pat.lex, reflags, &error, &erroroffset, NULL); if (!re) { return fs_value_error(FS_ERROR_INVALID_TYPE, error); } int rc = pcre_exec(re, NULL, str.lex, strlen(str.lex), 0, 0, NULL, 0); if (rc == PCRE_ERROR_NOMATCH) { return fs_value_boolean(0); } if (rc < 0) { fs_error(LOG_ERR, "internal error %d in pcre_exec", rc); return fs_value_error(FS_ERROR_INVALID_TYPE, "internal error in fn:matches"); } return fs_value_boolean(1); }