fs_value fn_less_than_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; } /* 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_greater_than(q, a, b)); if (fs_is_numeric(&a) && fs_is_numeric(&b)) return fn_logical_or(q, fn_numeric_less_than(q, a, b), fn_numeric_equal(q, a, b)); 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_seconds(fs_query *q, fs_value v) { if (v.attr != fs_c.xsd_datetime) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } v = fs_value_fill_lexical(q, v); GTimeVal tv; if (!g_time_val_from_iso8601(v.lex, &tv)) { return fs_value_error(FS_ERROR_INVALID_TYPE, "cannot get seconds from xsd:date"); } return fs_value_integer(tv.tv_sec % 60); }
fs_value fn_day(fs_query *q, fs_value v) { if (v.attr != fs_c.xsd_datetime) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } v = fs_value_fill_lexical(q, v); fs_date_fields df; if (date_from_iso8601(v.lex, &df)) { return fs_value_error(FS_ERROR_INVALID_TYPE, "cannot get day from xsd:dateTime"); } return fs_value_integer(df.day); }
fs_value fn_year(fs_query *q, fs_value v) { if (v.attr != fs_c.xsd_datetime) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } v = fs_value_fill_lexical(q, v); fs_date_fields df; if (date_from_iso8601(v.lex, &df)) { char *err = g_strdup_printf("cannot get year from xsd:dateTime %s", v.lex); fs_query_add_freeable(q, err); return fs_value_error(FS_ERROR_INVALID_TYPE, err); } return fs_value_integer(df.year); }
fs_value fn_greater_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 (a.attr == fs_c.xsd_datetime && b.attr == fs_c.xsd_datetime) return fn_datetime_greater_than(q, a, b); if (fs_is_numeric(&a)) return fn_numeric_greater_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_substring(fs_query *q, fs_value str, fs_value start, fs_value length) { if (!fs_is_plain_or_string(str)) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } if (!fs_is_numeric(&start)) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } start = cast_integer(start); /* 2 arg form */ if (length.rid == FS_RID_NULL) { length = fs_value_integer(INT_MAX); } else { if (!fs_is_numeric(&length)) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } length = cast_integer(length); } str = fs_value_fill_lexical(q, str); const int slen = g_utf8_strlen(str.lex, -1); if (start.in > slen || length.in <= 0) { fs_value ret = fs_value_plain(""); ret.attr = str.attr; return ret; } gchar *spos = g_utf8_offset_to_pointer(str.lex, start.in - 1); int retlen_utf8 = g_utf8_strlen(spos, -1); if (retlen_utf8 > length.in) { retlen_utf8 = length.in; } gchar *epos = g_utf8_offset_to_pointer(spos, retlen_utf8); int retlen_bytes = epos - spos + 1; char *retstr = g_malloc(retlen_bytes+1); retstr[retlen_bytes] = '\0'; g_utf8_strncpy(retstr, spos, retlen_utf8); fs_query_add_freeable(q, retstr); fs_value ret = fs_value_plain(retstr); ret.attr = str.attr; return ret; }
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"); }