gnumeric r16490 - in branches/gnumeric-1-8: . plugins/fn-lookup src



Author: mortenw
Date: Sun Apr  6 19:00:54 2008
New Revision: 16490
URL: http://svn.gnome.org/viewvc/gnumeric?rev=16490&view=rev

Log:
2008-04-06  Morten Welinder  <terra gnome org>

	* src/collect.c (collect_strings): Change return type to GPtrArray
	so we can actually tell if there was an error.  All callers
	changed.  Fixes CONCATENATE.
	(string_range_function): Make the subject function take a
	GPtrArray for simplicity.  All callers changed.



Modified:
   branches/gnumeric-1-8/ChangeLog
   branches/gnumeric-1-8/NEWS
   branches/gnumeric-1-8/plugins/fn-lookup/functions.c
   branches/gnumeric-1-8/src/collect.c
   branches/gnumeric-1-8/src/collect.h
   branches/gnumeric-1-8/src/rangefunc-strings.c
   branches/gnumeric-1-8/src/rangefunc-strings.h

Modified: branches/gnumeric-1-8/NEWS
==============================================================================
--- branches/gnumeric-1-8/NEWS	(original)
+++ branches/gnumeric-1-8/NEWS	Sun Apr  6 19:00:54 2008
@@ -14,6 +14,7 @@
 	* Allow opening multiple files in open dialog.  [#524479]
 	* Fix check for bogus xls files.  [#524926]
 	* Fix inc/dec buttons for General.  [#510252]
+	* Fix CONCATENATE's empty case.
 
 --------------------------------------------------------------------------
 Gnumeric 1.8.2

Modified: branches/gnumeric-1-8/plugins/fn-lookup/functions.c
==============================================================================
--- branches/gnumeric-1-8/plugins/fn-lookup/functions.c	(original)
+++ branches/gnumeric-1-8/plugins/fn-lookup/functions.c	Sun Apr  6 19:00:54 2008
@@ -135,26 +135,37 @@
 }
 
 static int
+calc_length (GnmValue const *data, GnmEvalPos const *ep, gboolean vertical)
+{
+	if (vertical)
+		return value_area_get_height (data, ep);
+	else
+		return value_area_get_width (data, ep);
+}
+
+static const GnmValue *
+get_elem (GnmValue const *data, guint ui,
+	  GnmEvalPos const *ep, gboolean vertical)
+{
+	if (vertical)
+		return value_area_fetch_x_y (data, 0, ui, ep);
+	else
+		return value_area_fetch_x_y (data, ui, 0, ep);
+}
+
+static int
 find_index_linear (GnmFuncEvalInfo *ei,
 		   GnmValue const *find, GnmValue const *data,
-		   gint type, gboolean height)
+		   gint type, gboolean vertical)
 {
 	GnmValue const *index_val = NULL;
 	GnmValDiff comp;
 	int length, lp, index = -1;
 
-	if (height)
-		length = value_area_get_height (data, ei->pos);
-	else
-		length = value_area_get_width (data, ei->pos);
+	length = calc_length (data, ei->pos, vertical);
 
 	for (lp = 0; lp < length; lp++){
-		GnmValue const *v;
-
-		if (height)
-			v = value_area_fetch_x_y (data, 0, lp, ei->pos);
-		else
-			v = value_area_fetch_x_y (data, lp, 0, ei->pos);
+		GnmValue const *v = get_elem (data, lp, ei->pos, vertical);
 
 		g_return_val_if_fail (v != NULL, -1);
 
@@ -198,16 +209,12 @@
 static int
 find_index_bisection (GnmFuncEvalInfo *ei,
 		      GnmValue const *find, GnmValue const *data,
-		      gint type, gboolean height)
+		      gint type, gboolean vertical)
 {
 	GnmValDiff comp = TYPE_MISMATCH;
 	int high, low = 0, prev = -1, mid = -1;
 
-	if (height)
-		high = value_area_get_height (data, ei->pos);
-	else
-		high = value_area_get_width (data, ei->pos);
-	high--;
+	high = calc_length (data, ei->pos, vertical) - 1;
 
 	if (high < low) {
 		return -1;
@@ -236,10 +243,7 @@
 		while (!find_compare_type_valid (find, v) && mid != -1) {
 			gboolean rev = FALSE;
 
-			if (height)
-				v = value_area_get_x_y (data, 0, mid, ei->pos);
-			else
-				v = value_area_get_x_y (data, mid, 0, ei->pos);
+			v = get_elem (data, mid, ei->pos, vertical);
 
 			if (find_compare_type_valid (find, v))
 				break;
@@ -292,10 +296,7 @@
 					adj = mid - 1;
 				}
 
-				if (height)
-					v = value_area_fetch_x_y (data, 0, adj, ei->pos);
-				else
-					v = value_area_fetch_x_y (data, adj, 0, ei->pos);
+				v = get_elem (data, adj, ei->pos, vertical);
 
 				g_return_val_if_fail (v != NULL, -1);
 

Modified: branches/gnumeric-1-8/src/collect.c
==============================================================================
--- branches/gnumeric-1-8/src/collect.c	(original)
+++ branches/gnumeric-1-8/src/collect.c	Sun Apr  6 19:00:54 2008
@@ -23,11 +23,11 @@
 /* ------------------------------------------------------------------------- */
 
 typedef struct {
-	guint           alloc_count;
-	gnm_float   *data;
-	guint         count;
-	CollectFlags  flags;
-	GSList       *info;
+	guint alloc_count;
+	gnm_float *data;
+	guint count;
+	CollectFlags flags;
+	GSList *info;
 	GODateConventions const *date_conv;
 } collect_floats_t;
 
@@ -35,23 +35,19 @@
 callback_function_collect (GnmEvalPos const *ep, GnmValue const *value,
 			   void *closure)
 {
-	gnm_float x;
-	collect_floats_t *cl = (collect_floats_t *)closure;
+	gnm_float x = 0;
+	collect_floats_t *cl = closure;
+	gboolean ignore = FALSE;
 
-	if (value == NULL) {
-		if (cl->flags & COLLECT_IGNORE_BLANKS)
-			goto callback_function_collect_store_info;
-		x = 0.;
-	} else switch (value->type) {
+	switch (value ? value->type : VALUE_EMPTY) {
 	case VALUE_EMPTY:
 		if (cl->flags & COLLECT_IGNORE_BLANKS)
-			goto callback_function_collect_store_info;
-		x = 0.;
+			ignore = TRUE;
 		break;
 
 	case VALUE_BOOLEAN:
 		if (cl->flags & COLLECT_IGNORE_BOOLS)
-			goto callback_function_collect_store_info;
+			ignore = TRUE;
 		else if (cl->flags & COLLECT_ZEROONE_BOOLS)
 			x = (value->v_bool.val) ? 1. : 0.;
 		else
@@ -64,9 +60,7 @@
 
 	case VALUE_ERROR:
 		if (cl->flags & COLLECT_IGNORE_ERRORS)
-			goto callback_function_collect_store_info;
-		else if (cl->flags & COLLECT_ZERO_ERRORS)
-			x = 0.;
+			ignore = TRUE;
 		else
 			return value_new_error_VALUE (ep);
 		break;
@@ -90,7 +84,7 @@
 			if (bad)
 				return value_new_error_VALUE (ep);
 		} else if (cl->flags & COLLECT_IGNORE_STRINGS)
-			goto callback_function_collect_store_info;
+			ignore = TRUE;
 		else if (cl->flags & COLLECT_ZERO_STRINGS)
 			x = 0;
 		else
@@ -100,29 +94,23 @@
 	default:
 		g_warning ("Trouble in callback_function_collect. (%d)",
 			   value->type);
-		goto callback_function_collect_store_info;
+		ignore = TRUE;
 	}
 
-	if (cl->count == cl->alloc_count) {
-		cl->alloc_count *= 2;
-		cl->data = g_realloc (cl->data, cl->alloc_count * sizeof (gnm_float));
+	if (ignore) {
+		if (cl->flags & COLLECT_INFO)
+			cl->info = g_slist_prepend (cl->info, GUINT_TO_POINTER (cl->count));
+		else {
+			return NULL;
+		}
 	}
 
-	cl->data[cl->count++] = x;
-	return NULL;
-
- callback_function_collect_store_info:
-
-	if (!(cl->flags & COLLECT_INFO))
-		return NULL;
-
 	if (cl->count == cl->alloc_count) {
-		cl->alloc_count *= 2;
-		cl->data = g_realloc (cl->data, cl->alloc_count * sizeof (gnm_float));
+		cl->alloc_count = cl->alloc_count * 2 + 20;
+		cl->data = g_renew (gnm_float, cl->data, cl->alloc_count);
 	}
 
-	cl->info = g_slist_prepend (cl->info, GUINT_TO_POINTER (cl->count));
-	cl->data[cl->count++] = 0;
+	cl->data[cl->count++] = x;
 	return NULL;
 }
 
@@ -156,7 +144,6 @@
 		GnmEvalPos const *ep, CollectFlags flags,
 		int *n, GnmValue **error, GSList **info)
 {
-	GnmValue * err;
 	collect_floats_t cl;
 	CellIterFlags iter_flags = CELL_ITER_ALL;
 
@@ -172,26 +159,29 @@
 	if (flags & COLLECT_IGNORE_SUBTOTAL)
 		iter_flags |= CELL_ITER_IGNORE_SUBTOTAL;
 
-	cl.alloc_count = 20;
-	cl.data = g_new (gnm_float, cl.alloc_count);
+	cl.alloc_count = 0;
+	cl.data = NULL;
 	cl.count = 0;
 	cl.flags = flags;
 	cl.info = NULL;
 	cl.date_conv = workbook_date_conv (ep->sheet->workbook);
 
-	err = function_iterate_argument_values
+	*error = function_iterate_argument_values
 		(ep, &callback_function_collect, &cl,
 		 argc, argv,
 		 TRUE, iter_flags);
-
-	if (err) {
-		g_assert (VALUE_IS_ERROR (err));
+	if (*error) {
+		g_assert (VALUE_IS_ERROR (*error));
 		g_free (cl.data);
 		g_slist_free (cl.info);
-		*error = err;
 		return NULL;
 	}
 
+	if (cl.data == NULL) {
+		cl.alloc_count = 1;
+		cl.data = g_new (gnm_float, cl.alloc_count);
+	}
+
 	if (info)
 		*info = cl.info;
 	*n = cl.count;
@@ -250,7 +240,7 @@
 
 	vals = collect_floats (argc, argv, ei->pos, flags, &n, &error, NULL);
 	if (!vals)
-		return (error != VALUE_TERMINATE) ? error : NULL;
+		return error;
 
 	err = func (vals, n, &res);
 	g_free (vals);
@@ -439,49 +429,38 @@
 /* ------------------------------------------------------------------------- */
 
 typedef struct {
-	GSList       *data;
-	CollectFlags  flags;
+	GPtrArray *data;
+	CollectFlags flags;
 } collect_strings_t;
 
 static GnmValue *
 callback_function_collect_strings (GnmEvalPos const *ep, GnmValue const *value,
 				   void *closure)
 {
-	char *text = NULL;
+	char *text;
 	collect_strings_t *cl = closure;
 
-	if (value == NULL) {
+	if (VALUE_IS_EMPTY (value)) {
 		if (cl->flags & COLLECT_IGNORE_BLANKS)
-			return NULL;
-		text = g_strdup ("");
-	} else switch (value->type) {
-	case VALUE_EMPTY:
-	case VALUE_BOOLEAN:
-	case VALUE_FLOAT:
-	case VALUE_STRING:
-		text = value_get_as_string (value);
-		break;
-	case VALUE_CELLRANGE :
-	case VALUE_ARRAY :
-		text = value_get_as_string (value);
-		break;
-	case VALUE_ERROR:
-		if (cl->flags & COLLECT_IGNORE_ERRORS)
-			return NULL;
-		else if (cl->flags & COLLECT_ZERO_ERRORS)
-			text = g_strdup ("");
+			text = NULL;
 		else
-			return value_new_error_VALUE (ep);
-		break;
-	default:
-		g_assert_not_reached ();
-		break;
-	}
+			text = g_strdup ("");
+	} else
+		text = value_get_as_string (value);
+
+	if (text)
+		g_ptr_array_add (cl->data, text);
 
-	cl->data = g_slist_prepend (cl->data, text);
 	return NULL;
 }
 
+static void
+collect_strings_free (GPtrArray *data)
+{
+	g_ptr_array_foreach (data, (GFunc)g_free, NULL);
+	g_ptr_array_free (data, TRUE);
+}
+
 /*
  * collect_strings:
  *
@@ -493,37 +472,37 @@
  *   NULL in case of error, error will be set
  *   Non-NULL in case of success.
  *
- * Evaluate a list of expressions and return the result as an array of
- * gnm_float.
+ * Evaluate a list of expressions and return the result as a GPtrArray of
+ * strings.
  */
 
-static GSList *
+static GPtrArray *
 collect_strings (int argc, GnmExprConstPtr const *argv,
 		 GnmEvalPos const *ep, CollectFlags flags,
 		 GnmValue **error)
 {
-	GnmValue * err;
 	collect_strings_t cl;
+	CellIterFlags iter_flags = CELL_ITER_ALL;
 
-	cl.data = NULL;
+	if (flags & COLLECT_IGNORE_BLANKS)
+		iter_flags = CELL_ITER_IGNORE_BLANK;
+
+	cl.data = g_ptr_array_new ();
 	cl.flags = flags;
 
-	err = function_iterate_argument_values
+	*error = function_iterate_argument_values
 		(ep, &callback_function_collect_strings, &cl,
 		 argc, argv,
-		TRUE, (flags & COLLECT_IGNORE_BLANKS) ?  CELL_ITER_IGNORE_BLANK : CELL_ITER_ALL);
-
-	if (err) {
-		g_assert (VALUE_IS_ERROR (err));
-		go_slist_free_custom (cl.data, g_free);
-		*error = err;
+		 TRUE, iter_flags);
+	if (*error) {
+		g_assert (VALUE_IS_ERROR (*error));
+		collect_strings_free (cl.data);
 		return NULL;
 	}
 
-	return g_slist_reverse (cl.data);
+	return cl.data;
 }
 
-
 GnmValue *
 string_range_function (int argc, GnmExprConstPtr const *argv,
 		       GnmFuncEvalInfo *ei,
@@ -532,16 +511,17 @@
 		       GnmStdError func_error)
 {
 	GnmValue *error = NULL;
-	GSList *vals;
+	GPtrArray *vals;
 	char *res = NULL;
 	int err;
 
 	vals = collect_strings (argc, argv, ei->pos, flags, &error);
 	if (!vals)
-		return (error != VALUE_TERMINATE) ? error : NULL;
+		return error;
 
 	err = func (vals, &res);
-	go_slist_free_custom (vals, g_free);
+
+	collect_strings_free (vals);
 
 	if (err) {
 		g_free (res);

Modified: branches/gnumeric-1-8/src/collect.h
==============================================================================
--- branches/gnumeric-1-8/src/collect.h	(original)
+++ branches/gnumeric-1-8/src/collect.h	Sun Apr  6 19:00:54 2008
@@ -16,17 +16,17 @@
 	COLLECT_ZEROONE_BOOLS	= 0x20,
 
 	COLLECT_IGNORE_ERRORS	= 0x100,
-	COLLECT_ZERO_ERRORS	= 0x200,
 
 	COLLECT_IGNORE_BLANKS	= 0x1000,
 	COLLECT_IGNORE_SUBTOTAL	= 0x2000,
-	COLLECT_INFO		= 0x8000
-} CollectFlags;
 
+	/* Not for general usage.  */
+	COLLECT_INFO		= 0x1000000
+} CollectFlags;
 
 typedef int (*float_range_function_t) (gnm_float const *, int, gnm_float *);
 typedef int (*float_range_function2_t) (gnm_float const *, gnm_float const *, int, gnm_float *);
-typedef int (*string_range_function_t) (GSList *, char**);
+typedef int (*string_range_function_t) (GPtrArray *, char**);
 
 /*gnm_float *collect_floats (int argc, GnmExprConstPtr const *argv,
 				GnmEvalPos const *ep, CollectFlags flags,
@@ -52,6 +52,7 @@
 				 float_range_function2_t func,
 				 CollectFlags flags,
 				 GnmStdError func_error);
+
 GnmValue *string_range_function (int argc, GnmExprConstPtr const *argv,
 				 GnmFuncEvalInfo *ei,
 				 string_range_function_t func,
@@ -62,6 +63,7 @@
 
 GArray *gnm_strip_missing (GArray * data, GSList **missing);
 
+
 G_END_DECLS
 
 #endif /* _GNM_COLLECT_H_ */

Modified: branches/gnumeric-1-8/src/rangefunc-strings.c
==============================================================================
--- branches/gnumeric-1-8/src/rangefunc-strings.c	(original)
+++ branches/gnumeric-1-8/src/rangefunc-strings.c	Sun Apr  6 19:00:54 2008
@@ -11,20 +11,21 @@
 
 #include <string.h>
 
-static void
-cb_concatenate (char const *text, GString *str)
-{
-	g_string_append (str, text);
-}
-
 int
-range_concatenate (GSList *data, char **res)
+range_concatenate (GPtrArray *data, char **res)
 {
-	GString *str = g_string_new (NULL);
+	unsigned ui;
+	size_t len = 0;
+	GString *str;
 
-	g_slist_foreach (data, (GFunc) cb_concatenate, str);
+	for (ui = 0; ui < data->len; ui++)
+		len += strlen (g_ptr_array_index (data, ui));
+
+	str = g_string_sized_new (len);
+
+	for (ui = 0; ui < data->len; ui++)
+		g_string_append (str, g_ptr_array_index (data, ui));
 
 	*res = g_string_free (str, FALSE);
 	return 0;
 }
-

Modified: branches/gnumeric-1-8/src/rangefunc-strings.h
==============================================================================
--- branches/gnumeric-1-8/src/rangefunc-strings.h	(original)
+++ branches/gnumeric-1-8/src/rangefunc-strings.h	Sun Apr  6 19:00:54 2008
@@ -6,7 +6,7 @@
 
 G_BEGIN_DECLS
 
-int range_concatenate (GSList *data, char **res);
+int range_concatenate (GPtrArray *data, char **res);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]