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_str(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) && FS_IS_BNODE(a.rid)) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } if (a.lex) { return fs_value_plain(a.lex); } fs_value v = fs_value_plain(NULL); a = fs_value_fill_lexical(q, a); v.lex = a.lex; return v; }
fs_value fn_cast(fs_query *q, fs_value v, fs_value d) { #if 0 printf("CAST "); fs_value_print(v); printf(" -> "); fs_value_print(d); printf("\n"); #endif if (FS_IS_URI(d.rid) && FS_IS_LITERAL(v.rid)) { return fn_cast_intl(q, v, d.rid); } if (d.rid == fs_c.xsd_string && FS_IS_URI(v.rid)) { fs_value v2 = fn_cast_intl(q, v, d.rid); v2.rid = fs_hash_literal(v.lex, d.rid); return v2; } return fs_value_error(FS_ERROR_INVALID_TYPE, "cast on URI/bNode"); }
fs_value fn_less_than(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; } #if 0 fs_value_print(a); printf(" < "); fs_value_print(b); printf("\n"); #endif if (a.attr == fs_c.xsd_datetime && b.attr == fs_c.xsd_datetime) return fn_datetime_less_than(q, a, b); if (fs_is_numeric(&a)) return fn_numeric_less_than(q, a, b); if (a.lex && b.lex) return 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_compare(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; } #if 0 fs_value_print(a); printf(" <=> "); fs_value_print(b); printf("\n"); #endif if ((FS_IS_LITERAL(a.attr) && FS_IS_LITERAL(b.attr)) || (a.attr == fs_c.empty && b.attr == fs_c.empty)) { if (a.lex && b.lex) { int diff = strcmp(a.lex, b.lex); if (diff > 0) { return fs_value_integer(1); } else if (diff < 0) { return fs_value_integer(-1); } return fs_value_integer(0); } } else if (a.attr == fs_c.xsd_string && b.attr == fs_c.xsd_string) { if (a.lex && b.lex) { int diff = strcmp(a.lex, b.lex); if (diff > 0) { return fs_value_integer(1); } else if (diff < 0) { return fs_value_integer(-1); } return fs_value_integer(0); } } return fs_value_error(FS_ERROR_INVALID_TYPE, "bad arguments to fn:compare"); }
fs_value fn_numeric_add(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 0 fs_value_print(a); printf(" P+ "); fs_value_print(b); printf("\n"); #endif if (a.attr == b.attr && a.attr != FS_RID_NULL && a.attr != fs_c.empty) { fs_value v = fs_value_blank(); v.attr = a.attr; if (a.attr == fs_c.xsd_double || a.attr == fs_c.xsd_float) { v.fp = a.fp + b.fp; v.valid = fs_valid_bit(FS_V_FP); return v; } else if (a.attr == fs_c.xsd_decimal) { fs_decimal_add(&a.de, &b.de, &v.de); v.valid = fs_valid_bit(FS_V_DE); return v; } else if (a.attr == fs_c.xsd_integer) { v.in = a.in + b.in; v.valid = fs_valid_bit(FS_V_IN); return v; } } return fs_value_error(FS_ERROR_INVALID_TYPE, "non-numeric arguments to fn:add"); }
fs_value fs_value_fill_lexical(fs_query *q, fs_value a) { if (a.lex) { return a; } if (a.valid & fs_valid_bit(FS_V_FP)) { a.lex = g_strdup_printf("%f", a.fp); fs_query_add_freeable(q, a.lex); return a; } if (a.valid & fs_valid_bit(FS_V_DE)) { a.lex = fs_decimal_to_lex(&a.de); fs_query_add_freeable(q, a.lex); return a; } if (a.valid & fs_valid_bit(FS_V_IN)) { if (a.attr == fs_c.xsd_integer) { a.lex = g_strdup_printf("%lld", (long long)a.in); fs_query_add_freeable(q, a.lex); return a; } if (a.attr == fs_c.xsd_datetime) { struct tm t; time_t clock = a.in; gmtime_r(&clock, &t); a.lex = g_strdup_printf("%04d-%02d-%02dT%02d:%02d:%02d", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); fs_query_add_freeable(q, a.lex); return a; } } return fs_value_error(FS_ERROR_INVALID_TYPE, "bad lexical cast"); }
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_timezone(fs_query *q, fs_value v) { return fs_value_error(FS_ERROR_INVALID_TYPE, "TIMEZONE() function not suported"); }
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); }