[gnumeric] Criteria: implement pattern matching.
- From: Morten Welinder <mortenw src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnumeric] Criteria: implement pattern matching.
- Date: Sat, 20 Jun 2009 15:36:40 -0400 (EDT)
commit cfb430df770b90a2765ebfc3c036a5e092952d75
Author: Morten Welinder <terra gnome org>
Date: Sat Jun 20 15:36:00 2009 -0400
Criteria: implement pattern matching.
ChangeLog | 11 ++++++
NEWS | 28 +++++++++------
plugins/fn-database/functions.c | 4 +-
plugins/fn-math/functions.c | 4 +-
src/value.c | 72 ++++++++++++++++++++------------------
src/value.h | 15 +++++---
6 files changed, 78 insertions(+), 56 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a6985d2..81407a3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2009-06-20 Morten Welinder <terra gnome org>
+
+ * src/value.c (criteria_test_match): New function.
+ (free_criteria): Free regexp if needed.
+ (criteria_inspect_values, criteria_test_equal,
+ criteria_test_unequal, criteria_test_less, criteria_test_greater,
+ criteria_test_less_or_equal, criteria_test_greater_or_equal): Take
+ GnmCriteria instead of y and date_conv. All callers changed.
+ (parse_criteria): The no-operator case is criteria_test_match, not
+ criteria_test_equal.
+
2009-06-20 Morten Welinder <terra gnome org>
* configure.in: Post-release bump.
diff --git a/NEWS b/NEWS
index 04de424..21f91ac 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,9 @@
Gnumeric 1.9.10
+Morten:
+ * Make SUMIF/COUNTIF and the D* functions understand pattern.
+ [#586215]
+
--------------------------------------------------------------------------
Gnumeric 1.9.9
@@ -12,18 +16,18 @@ Andreas:
* Remove distinction between label and filled rectangle.
* Add superscipt and subscript buttons. [#583327]
* Improve ODF import.
- * Improve 2 factor ANOVA tool
- * Improve Rank & Percentiles tool
- * Improve Fourier transform tool
- * New FOURIER function
- * Added Tests for Independence and Homogeneity
- * Make imported manual page breaks work
- * Improve print area handling and export to ODF
- * Some minor menu rearrangement
- * Let the sort dialog guess whether there is a header
- * Fix xls import of sheet labels [#586066]
- * Fix html export [#586028]
- * Avoid analysis tool crashes if required plugins are not loaded
+ * Improve 2 factor ANOVA tool.
+ * Improve Rank & Percentiles tool.
+ * Improve Fourier transform tool.
+ * New FOURIER function.
+ * Added Tests for Independence and Homogeneity.
+ * Make imported manual page breaks work.
+ * Improve print area handling and export to ODF.
+ * Some minor menu rearrangement.
+ * Let the sort dialog guess whether there is a header.
+ * Fix xls import of sheet labels. [#586066]
+ * Fix html export. [#586028]
+ * Avoid analysis tool crashes if required plugins are not loaded.
Jody:
* GOString start of richtext and phonetic support.
diff --git a/plugins/fn-database/functions.c b/plugins/fn-database/functions.c
index 96c628c..369e9da 100644
--- a/plugins/fn-database/functions.c
+++ b/plugins/fn-database/functions.c
@@ -81,13 +81,13 @@ find_cells_that_match (Sheet *sheet, GnmValue const *database,
condition = current_criteria->conditions;
for (;condition != NULL ; condition = condition->next) {
- GnmCriteria const *cond = condition->data;
+ GnmCriteria *cond = condition->data;
GnmCell *tmp = sheet_cell_get (sheet,
cond->column, row);
if (tmp != NULL)
gnm_cell_eval (tmp);
if (gnm_cell_is_empty (tmp) ||
- !cond->fun (tmp->value, cond->x, date_conv)) {
+ !cond->fun (tmp->value, cond)) {
add_flag = FALSE;
break;
}
diff --git a/plugins/fn-math/functions.c b/plugins/fn-math/functions.c
index ab8ba5f..a406e8a 100644
--- a/plugins/fn-math/functions.c
+++ b/plugins/fn-math/functions.c
@@ -601,7 +601,7 @@ cb_countif (GnmCellIter const *iter, CountIfClosure *res)
if (!VALUE_IS_NUMBER (v) && !VALUE_IS_STRING (v))
return NULL;
- if (!res->crit->fun (v, res->crit->x, res->crit->date_conv))
+ if (!res->crit->fun (v, res->crit))
return NULL;
res->count++;
@@ -693,7 +693,7 @@ cb_sumif (GnmCellIter const *iter, SumIfClosure *res)
if (!VALUE_IS_NUMBER (v) && !VALUE_IS_STRING (v))
return NULL;
- if (!res->crit->fun (v, res->crit->x, res->crit->date_conv))
+ if (!res->crit->fun (v, res->crit))
return NULL;
if (NULL != res->target_sheet) {
diff --git a/src/value.c b/src/value.c
index 49c3108..fda9e94 100644
--- a/src/value.c
+++ b/src/value.c
@@ -1337,11 +1337,11 @@ value_set_fmt (GnmValue *v, GOFormat const *fmt)
typedef enum { CRIT_NULL, CRIT_FLOAT, CRIT_BADFLOAT, CRIT_STRING } CritType;
static CritType
-criteria_inspect_values (GnmValue const *x, GnmValue const *y,
- gnm_float *xr, gnm_float *yr,
- GODateConventions const *date_conv)
+criteria_inspect_values (GnmValue const *x, gnm_float *xr, gnm_float *yr,
+ GnmCriteria *crit)
{
GnmValue *vx;
+ GnmValue const *y = crit->x;
if (x == NULL || y == NULL)
return CRIT_NULL;
@@ -1355,7 +1355,7 @@ criteria_inspect_values (GnmValue const *x, GnmValue const *y,
return CRIT_FLOAT;
}
- vx = format_match (value_peek_string (x), NULL, date_conv);
+ vx = format_match (value_peek_string (x), NULL, crit->date_conv);
if (!vx)
return CRIT_BADFLOAT;
@@ -1366,12 +1366,12 @@ criteria_inspect_values (GnmValue const *x, GnmValue const *y,
static gboolean
-criteria_test_equal (GnmValue const *x, GnmValue const *y,
- GODateConventions const *date_conv)
+criteria_test_equal (GnmValue const *x, GnmCriteria *crit)
{
gnm_float xf, yf;
+ GnmValue const *y = crit->x;
- switch (criteria_inspect_values (x, y, &xf, &yf, date_conv)) {
+ switch (criteria_inspect_values (x, &xf, &yf, crit)) {
default:
g_assert_not_reached ();
case CRIT_NULL:
@@ -1387,12 +1387,11 @@ criteria_test_equal (GnmValue const *x, GnmValue const *y,
}
static gboolean
-criteria_test_unequal (GnmValue const *x, GnmValue const *y,
- GODateConventions const *date_conv)
+criteria_test_unequal (GnmValue const *x, GnmCriteria *crit)
{
gnm_float xf, yf;
- switch (criteria_inspect_values (x, y, &xf, &yf, date_conv)) {
+ switch (criteria_inspect_values (x, &xf, &yf, crit)) {
default:
g_assert_not_reached ();
case CRIT_NULL:
@@ -1403,17 +1402,16 @@ criteria_test_unequal (GnmValue const *x, GnmValue const *y,
case CRIT_STRING:
/* FIXME: _ascii_??? */
return g_ascii_strcasecmp (value_peek_string (x),
- value_peek_string (y)) != 0;
+ value_peek_string (crit->x)) != 0;
}
}
static gboolean
-criteria_test_less (GnmValue const *x, GnmValue const *y,
- GODateConventions const *date_conv)
+criteria_test_less (GnmValue const *x, GnmCriteria *crit)
{
gnm_float xf, yf;
- switch (criteria_inspect_values (x, y, &xf, &yf, date_conv)) {
+ switch (criteria_inspect_values (x, &xf, &yf, crit)) {
default:
g_assert_not_reached ();
case CRIT_NULL:
@@ -1426,12 +1424,11 @@ criteria_test_less (GnmValue const *x, GnmValue const *y,
}
static gboolean
-criteria_test_greater (GnmValue const *x, GnmValue const *y,
- GODateConventions const *date_conv)
+criteria_test_greater (GnmValue const *x, GnmCriteria *crit)
{
gnm_float xf, yf;
- switch (criteria_inspect_values (x, y, &xf, &yf, date_conv)) {
+ switch (criteria_inspect_values (x, &xf, &yf, crit)) {
default:
g_assert_not_reached ();
case CRIT_NULL:
@@ -1444,12 +1441,11 @@ criteria_test_greater (GnmValue const *x, GnmValue const *y,
}
static gboolean
-criteria_test_less_or_equal (GnmValue const *x, GnmValue const *y,
- GODateConventions const *date_conv)
+criteria_test_less_or_equal (GnmValue const *x, GnmCriteria *crit)
{
gnm_float xf, yf;
- switch (criteria_inspect_values (x, y, &xf, &yf, date_conv)) {
+ switch (criteria_inspect_values (x, &xf, &yf, crit)) {
default:
g_assert_not_reached ();
case CRIT_NULL:
@@ -1462,12 +1458,11 @@ criteria_test_less_or_equal (GnmValue const *x, GnmValue const *y,
}
static gboolean
-criteria_test_greater_or_equal (GnmValue const *x, GnmValue const *y,
- GODateConventions const *date_conv)
+criteria_test_greater_or_equal (GnmValue const *x, GnmCriteria *crit)
{
gnm_float xf, yf;
- switch (criteria_inspect_values (x, y, &xf, &yf, date_conv)) {
+ switch (criteria_inspect_values (x, &xf, &yf, crit)) {
default:
g_assert_not_reached ();
case CRIT_NULL:
@@ -1479,6 +1474,15 @@ criteria_test_greater_or_equal (GnmValue const *x, GnmValue const *y,
}
}
+static gboolean
+criteria_test_match (GnmValue const *x, GnmCriteria *crit)
+{
+ if (!crit->has_rx)
+ return FALSE;
+
+ return go_regexec (&crit->rx, value_peek_string (x), 0, NULL, 0) == REG_OK;
+}
+
/*
* Finds a column index of a field.
*/
@@ -1536,6 +1540,8 @@ void
free_criteria (GnmCriteria *criteria)
{
value_release (criteria->x);
+ if (criteria->has_rx)
+ go_regfree (&criteria->rx);
g_free (criteria);
}
@@ -1596,20 +1602,21 @@ parse_criteria (GnmValue const *crit_val, GODateConventions const *date_conv)
res->fun = criteria_test_greater_or_equal;
len = 2;
} else if (strncmp (criteria, "<>", 2) == 0) {
- res->fun = (GnmCriteriaFunc) criteria_test_unequal;
+ res->fun = criteria_test_unequal;
len = 2;
res->iter_flags = CELL_ITER_ALL;
} else if (*criteria == '<') {
- res->fun = (GnmCriteriaFunc) criteria_test_less;
+ res->fun = criteria_test_less;
len = 1;
} else if (*criteria == '=') {
- res->fun = (GnmCriteriaFunc) criteria_test_equal;
+ res->fun = criteria_test_equal;
len = 1;
} else if (*criteria == '>') {
- res->fun = (GnmCriteriaFunc) criteria_test_greater;
+ res->fun = criteria_test_greater;
len = 1;
} else {
- res->fun = (GnmCriteriaFunc) criteria_test_equal;
+ res->fun = criteria_test_match;
+ res->has_rx = (gnm_regcomp_XL (&res->rx, criteria, 0, TRUE) == REG_OK);
len = 0;
}
@@ -1714,22 +1721,19 @@ find_rows_that_match (Sheet *sheet, int first_col, int first_row,
gboolean add_flag;
char const *t1, *t2;
GnmCell *test_cell;
- GnmCriteria const *cond;
- GODateConventions const *date_conv =
- workbook_date_conv (sheet->workbook);
for (row = first_row; row <= last_row; row++) {
add_flag = TRUE;
- for (crit_ptr = criterias; crit_ptr != NULL; crit_ptr = crit_ptr->next) {
+ for (crit_ptr = criterias; crit_ptr; crit_ptr = crit_ptr->next) {
add_flag = TRUE;
for (cond_ptr = ((GnmDBCriteria const *)crit_ptr->data)->conditions;
cond_ptr != NULL ; cond_ptr = cond_ptr->next) {
- cond = cond_ptr->data;
+ GnmCriteria *cond = cond_ptr->data;
test_cell = sheet_cell_get (sheet, cond->column, row);
if (test_cell != NULL) {
gnm_cell_eval (test_cell);
if (!gnm_cell_is_empty (test_cell) &&
- !cond->fun (test_cell->value, cond->x, date_conv)) {
+ !cond->fun (test_cell->value, cond)) {
add_flag = FALSE;
break;
}
diff --git a/src/value.h b/src/value.h
index b570800..66bf54f 100644
--- a/src/value.h
+++ b/src/value.h
@@ -185,16 +185,19 @@ extern GnmValueErr const value_terminate_err;
void value_array_set (GnmValue *array, int col, int row, GnmValue *v);
+typedef struct _GnmCriteria GnmCriteria;
+
/* FIXME: this stuff below ought to go elsewhere. */
-typedef gboolean (*GnmCriteriaFunc) (GnmValue const *x, GnmValue const *y,
- GODateConventions const *date_conv);
-typedef struct {
+typedef gboolean (*GnmCriteriaFunc) (GnmValue const *x, GnmCriteria *crit);
+struct _GnmCriteria {
GnmCriteriaFunc fun;
- GnmValue *x;
- int column; /* absolute */
+ GnmValue *x;
+ int column; /* absolute */
CellIterFlags iter_flags;
GODateConventions const *date_conv;
-} GnmCriteria;
+ GORegexp rx;
+ gboolean has_rx;
+};
typedef struct {
int row; /* absolute */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]