[gcalctool] Don't truncate answers
- From: Robin Sonefors <rsonefors src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcalctool] Don't truncate answers
- Date: Wed, 13 Oct 2010 07:51:45 +0000 (UTC)
commit aa0350eaa91b2975809dc88a13b70a49ece8180d
Author: Robin Sonefors <ozamosi flukkost nu>
Date: Wed Oct 13 01:39:40 2010 +0200
Don't truncate answers
Originally implemented to get rid of garbage when string was truncated.
This also means that if a number is too big it will get rounded, but it
won't be off by orders of magnitudes.
src/gcalccmd.c | 5 +++--
src/gcalctool.c | 5 +++--
src/math-buttons.c | 13 ++++++++-----
src/math-equation.c | 20 ++++++++++++--------
src/math-variables.c | 5 +++--
src/mp-binary.c | 15 ++++++++++-----
src/mp-serializer.c | 38 +++++++++++++++++++++-----------------
src/mp-serializer.h | 4 ++--
src/mp.c | 9 +++++++++
src/unittest.c | 5 +++--
10 files changed, 74 insertions(+), 45 deletions(-)
---
diff --git a/src/gcalccmd.c b/src/gcalccmd.c
index e7a6509..eedd3b2 100644
--- a/src/gcalccmd.c
+++ b/src/gcalccmd.c
@@ -36,7 +36,7 @@ solve(const char *equation)
int ret;
MPEquationOptions options;
MPNumber z;
- char result_str[MAXLINE];
+ char *result_str;
memset(&options, 0, sizeof(options));
options.base = 10;
@@ -50,9 +50,10 @@ solve(const char *equation)
else if (ret)
fprintf(stderr, "Error %d\n", ret);
else {
- mp_serializer_to_specific_string(&z, 10, 9, true, true, result_str, MAXLINE);
+ mp_serializer_to_specific_string(&z, 10, 9, true, true, &result_str);
printf("%s\n", result_str);
}
+ g_free(result_str);
}
diff --git a/src/gcalctool.c b/src/gcalctool.c
index 1bb4f87..fa0e413 100644
--- a/src/gcalctool.c
+++ b/src/gcalctool.c
@@ -45,7 +45,7 @@ solve(const char *equation)
MPEquationOptions options;
MPErrorCode error;
MPNumber result;
- char result_str[1024];
+ char *result_str;
memset(&options, 0, sizeof(options));
options.base = 10;
@@ -62,8 +62,9 @@ solve(const char *equation)
exit(1);
}
else {
- mp_serializer_to_specific_string(&result, options.base, 9, true, true, result_str, 1024);
+ mp_serializer_to_specific_string(&result, options.base, 9, true, true, &result_str);
printf("%s\n", result_str);
+ g_free(result_str);
exit(0);
}
}
diff --git a/src/math-buttons.c b/src/math-buttons.c
index de82728..b0cd926 100644
--- a/src/math-buttons.c
+++ b/src/math-buttons.c
@@ -589,12 +589,12 @@ update_currency_label(MathButtons *buttons)
math_equation_get_source_currency(buttons->priv->equation),
math_equation_get_target_currency(buttons->priv->equation),
&value)) {
- char input_text[1024], output_text[1024];
+ char *input_text, *output_text;
const char *source_symbol, *target_symbol;
int i;
- mp_serializer_to_specific_string(&x, 10, 2, false, true, input_text, 1024);
- mp_serializer_to_specific_string(&value, 10, 2, false, true, output_text, 1024);
+ mp_serializer_to_specific_string(&x, 10, 2, false, true, &input_text);
+ mp_serializer_to_specific_string(&value, 10, 2, false, true, &output_text);
for (i = 0; strcmp(math_equation_get_source_currency(buttons->priv->equation), currency_names[i].short_name) != 0; i++);
source_symbol = currency_names[i].symbol;
@@ -605,6 +605,8 @@ update_currency_label(MathButtons *buttons)
label = g_strdup_printf(_("%s%s = %s%s"),
source_symbol, input_text,
target_symbol, output_text);
+ g_free(input_text);
+ g_free(output_text);
}
else
label = g_strdup("");
@@ -1279,13 +1281,14 @@ delete_variable_cb(GtkWidget *widget, MathButtons *buttons)
static GtkWidget *
make_register_menu_item(MathButtons *buttons, const gchar *name, const MPNumber *value, gboolean can_modify, GCallback callback)
{
- gchar text[1024] = "", *mstr;
+ gchar *text, *mstr;
GtkWidget *item, *label;
if (value) {
MpSerializer *serializer = math_equation_get_serializer(buttons->priv->equation);
- mp_serializer_to_standard_string(serializer, value, text, 1024);
+ mp_serializer_to_standard_string(serializer, value, &text);
mstr = g_strdup_printf("<span weight=\"bold\">%s</span> = %s", name, text);
+ g_free(text);
}
else
mstr = g_strdup_printf("<span weight=\"bold\">%s</span>", name);
diff --git a/src/math-equation.c b/src/math-equation.c
index 66ec07b..d2a0808 100644
--- a/src/math-equation.c
+++ b/src/math-equation.c
@@ -147,13 +147,13 @@ reformat_ans(MathEquation *equation)
return;
gchar *orig_ans_text;
- gchar ans_text[MAX_DIGITS];
+ gchar *ans_text;
GtkTextIter ans_start, ans_end;
gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &ans_start, equation->priv->ans_start);
gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &ans_end, equation->priv->ans_end);
orig_ans_text = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation), &ans_start, &ans_end, FALSE);
- mp_serializer_to_standard_string(equation->priv->serializer, &equation->priv->state.ans, ans_text, MAX_DIGITS);
+ mp_serializer_to_standard_string(equation->priv->serializer, &equation->priv->state.ans, &ans_text);
if (strcmp(orig_ans_text, ans_text) != 0) {
gint start;
@@ -175,6 +175,7 @@ reformat_ans(MathEquation *equation)
gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &ans_start, equation->priv->ans_start);
gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &ans_end, equation->priv->ans_end);
g_free(orig_ans_text);
+ g_free(ans_text);
}
static void
@@ -714,11 +715,11 @@ math_equation_set(MathEquation *equation, const gchar *text)
void
math_equation_set_number(MathEquation *equation, const MPNumber *x)
{
- char text[MAX_DIGITS];
+ char *text;
GtkTextIter start, end;
/* Show the number in the user chosen format */
- mp_serializer_to_standard_string(equation->priv->serializer, x, text, MAX_DIGITS);
+ mp_serializer_to_standard_string(equation->priv->serializer, x, &text);
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), text, -1);
mp_set_from_mp(x, &equation->priv->state.ans);
@@ -728,6 +729,7 @@ math_equation_set_number(MathEquation *equation, const MPNumber *x)
equation->priv->ans_start = gtk_text_buffer_create_mark(GTK_TEXT_BUFFER(equation), NULL, &start, FALSE);
equation->priv->ans_end = gtk_text_buffer_create_mark(GTK_TEXT_BUFFER(equation), NULL, &end, TRUE);
gtk_text_buffer_apply_tag(GTK_TEXT_BUFFER(equation), equation->priv->ans_tag, &start, &end);
+ g_free(text);
}
@@ -787,9 +789,10 @@ math_equation_insert_numeric_point(MathEquation *equation)
void
math_equation_insert_number(MathEquation *equation, const MPNumber *x)
{
- char text[MAX_DIGITS];
- mp_serializer_to_standard_string(equation->priv->serializer, x, text, MAX_DIGITS);
+ char *text;
+ mp_serializer_to_standard_string(equation->priv->serializer, x, &text);
math_equation_insert(equation, text);
+ g_free(text);
}
@@ -1053,15 +1056,16 @@ math_equation_factorize(MathEquation *equation)
text = g_string_new("");
for (factor = factors; factor; factor = factor->next) {
- gchar temp[MAX_DIGITS];
+ gchar *temp;
MPNumber *n;
n = factor->data;
- mp_serializer_to_standard_string(equation->priv->serializer, n, temp, MAX_DIGITS);
+ mp_serializer_to_standard_string(equation->priv->serializer, n, &temp);
g_string_append(text, temp);
if (factor->next)
g_string_append(text, "Ã?");
g_slice_free(MPNumber, n);
+ g_free(temp);
}
g_list_free(factors);
diff --git a/src/math-variables.c b/src/math-variables.c
index 58a9815..77207b6 100644
--- a/src/math-variables.c
+++ b/src/math-variables.c
@@ -96,10 +96,11 @@ registers_save(MathVariables *variables)
{
gchar *name = key;
MPNumber *value = val;
- char number[1024];
+ char *number;
- mp_serializer_to_specific_string(value, 10, 50, true, false, number, 1024);
+ mp_serializer_to_specific_string(value, 10, 50, true, false, &number);
fprintf(f, "%s=%s\n", name, number);
+ g_free(number);
}
fclose(f);
}
diff --git a/src/mp-binary.c b/src/mp-binary.c
index 6c8811c..f16470b 100644
--- a/src/mp-binary.c
+++ b/src/mp-binary.c
@@ -43,11 +43,11 @@ static int hex_to_int(char digit)
static void
mp_bitwise(const MPNumber *x, const MPNumber *y, int (*bitwise_operator)(int, int), MPNumber *z, int wordlen)
{
- char text1[MAX_DIGITS], text2[MAX_DIGITS], text_out[MAX_DIGITS], text_out2[MAX_DIGITS];
+ char *text1, *text2, text_out[MAX_DIGITS], text_out2[MAX_DIGITS];
int offset1, offset2, offset_out;
- mp_serializer_to_specific_string(x, 16, 0, false, false, text1, MAX_DIGITS);
- mp_serializer_to_specific_string(y, 16, 0, false, false, text2, MAX_DIGITS);
+ mp_serializer_to_specific_string(x, 16, 0, false, false, &text1);
+ mp_serializer_to_specific_string(y, 16, 0, false, false, &text2);
offset1 = strlen(text1) - 1;
offset2 = strlen(text2) - 1;
offset_out = wordlen / 4 - 1;
@@ -56,6 +56,8 @@ mp_bitwise(const MPNumber *x, const MPNumber *y, int (*bitwise_operator)(int, in
}
if (offset_out > 0 && (offset_out < offset1 || offset_out < offset2)) {
mperr("Overflow. Try a bigger word size");
+ g_free(text1);
+ g_free(text2);
return;
}
@@ -76,6 +78,8 @@ mp_bitwise(const MPNumber *x, const MPNumber *y, int (*bitwise_operator)(int, in
snprintf(text_out2, MAX_DIGITS, "%s", text_out);
mp_set_from_string(text_out2, 16, z);
+ g_free(text1);
+ g_free(text2);
}
@@ -153,15 +157,16 @@ mp_not(const MPNumber *x, int wordlen, MPNumber *z)
void
mp_mask(const MPNumber *x, int wordlen, MPNumber *z)
{
- char text[MAX_DIGITS];
+ char *text;
size_t len, offset;
/* Convert to a hexadecimal string and use last characters */
- mp_serializer_to_specific_string(x, 16, 0, false, false, text, MAX_DIGITS);
+ mp_serializer_to_specific_string(x, 16, 0, false, false, &text);
len = strlen(text);
offset = wordlen / 4;
offset = len > offset ? len - offset: 0;
mp_set_from_string(text + offset, 16, z);
+ g_free(text);
}
diff --git a/src/mp-serializer.c b/src/mp-serializer.c
index b397a57..1b9db1e 100644
--- a/src/mp-serializer.c
+++ b/src/mp-serializer.c
@@ -76,7 +76,11 @@ mp_cast_to_string_real(MpSerializer *serializer, const MPNumber *x, int base, bo
mp_xpowy_integer(&temp, -(serializer->priv->accuracy+1), &temp);
mp_multiply_integer(&temp, base, &temp);
mp_divide_integer(&temp, 2, &temp);
- mp_add(&number, &temp, &number);
+ mp_add(&number, &temp, &temp);
+
+ /* If trying to add rounding factor causes overflow, don't add it */
+ if (!mp_get_error())
+ mp_set_from_mp(&temp, &number);
/* Split into integer and fractional component */
mp_floor(&number, &integer_component);
@@ -158,12 +162,12 @@ mp_cast_to_string_real(MpSerializer *serializer, const MPNumber *x, int base, bo
static void
-mp_cast_to_string(MpSerializer *serializer, const MPNumber *x, char *buffer, int buffer_length)
+mp_cast_to_string(MpSerializer *serializer, const MPNumber *x, char **buffer)
{
GString *string;
MPNumber x_real;
- string = g_string_sized_new(buffer_length);
+ string = g_string_sized_new(1024);
mp_real_component(x, &x_real);
mp_cast_to_string_real(serializer, &x_real, serializer->priv->base, false, string);
@@ -179,7 +183,7 @@ mp_cast_to_string(MpSerializer *serializer, const MPNumber *x, char *buffer, int
force_sign = false;
}
- s = g_string_sized_new(buffer_length);
+ s = g_string_sized_new(1024);
mp_cast_to_string_real(serializer, &x_im, 10, force_sign, s);
if (strcmp(s->str, "0") == 0 || strcmp(s->str, "+0") == 0 || strcmp(s->str, "â??0") == 0) {
/* Ignore */
@@ -204,22 +208,21 @@ mp_cast_to_string(MpSerializer *serializer, const MPNumber *x, char *buffer, int
g_string_free(s, TRUE);
}
- // FIXME: Check for truncation
- strncpy(buffer, string->str, buffer_length);
+ *buffer = g_strndup(string->str, string->len + 1);
g_string_free(string, TRUE);
}
static void
-mp_cast_to_exponential_string(MpSerializer *serializer, const MPNumber *x, bool eng_format, char *buffer, int buffer_length)
+mp_cast_to_exponential_string(MpSerializer *serializer, const MPNumber *x, bool eng_format, char **buffer)
{
- char fixed[1024], *c;
+ char *fixed, *c;
MPNumber t, z, base, base3, base10, base10inv, mantissa;
int exponent = 0;
GString *string;
const char *super_digits[] = {"�", "¹", "²", "³", "�", "�", "�", "�", "�", "�"};
- string = g_string_sized_new(buffer_length);
+ string = g_string_sized_new(1024);
mp_abs(x, &z);
if (mp_is_negative(x))
@@ -256,8 +259,9 @@ mp_cast_to_exponential_string(MpSerializer *serializer, const MPNumber *x, bool
}
}
- mp_cast_to_string(serializer, &mantissa, fixed, 1024);
+ mp_cast_to_string(serializer, &mantissa, &fixed);
g_string_append(string, fixed);
+ g_free(fixed);
if (exponent != 0) {
g_string_append_printf(string, "Ã?10"); // FIXME: Use the current base
if (exponent < 0) {
@@ -269,29 +273,29 @@ mp_cast_to_exponential_string(MpSerializer *serializer, const MPNumber *x, bool
g_string_append(string, super_digits[*c - '0']);
}
- strncpy(buffer, string->str, buffer_length);
+ *buffer = g_strndup(string->str, string->len + 1);
g_string_free(string, TRUE);
}
void
-mp_serializer_to_standard_string(MpSerializer *serializer, const MPNumber *x, char *target, int target_len)
+mp_serializer_to_standard_string(MpSerializer *serializer, const MPNumber *x, char **target)
{
switch(serializer->priv->format) {
case FIX:
- mp_cast_to_string(serializer, x, target, target_len);
+ mp_cast_to_string(serializer, x, target);
break;
case SCI:
- mp_cast_to_exponential_string(serializer, x, false, target, target_len);
+ mp_cast_to_exponential_string(serializer, x, false, target);
break;
case ENG:
- mp_cast_to_exponential_string(serializer, x, true, target, target_len);
+ mp_cast_to_exponential_string(serializer, x, true, target);
break;
}
}
void
-mp_serializer_to_specific_string(const MPNumber *x, int base, int accuracy, bool trim_zeroes, bool localize, char *target, int target_len)
+mp_serializer_to_specific_string(const MPNumber *x, int base, int accuracy, bool trim_zeroes, bool localize, char **target)
{
MpSerializer *serializer = mp_serializer_new ();
if (!localize) {
@@ -302,7 +306,7 @@ mp_serializer_to_specific_string(const MPNumber *x, int base, int accuracy, bool
serializer->priv->base = base;
serializer->priv->accuracy = accuracy;
serializer->priv->show_zeroes = !trim_zeroes;
- mp_serializer_to_standard_string(serializer, x, target, target_len);
+ mp_serializer_to_standard_string(serializer, x, target);
g_object_unref(serializer);
}
diff --git a/src/mp-serializer.h b/src/mp-serializer.h
index f815fa2..718ee1e 100644
--- a/src/mp-serializer.h
+++ b/src/mp-serializer.h
@@ -50,8 +50,8 @@ typedef enum {
GType mp_serializer_get_type(void);
MpSerializer *mp_serializer_new(void);
-void mp_serializer_to_standard_string(MpSerializer *serializer, const MPNumber *z, char *target, int target_len);
-void mp_serializer_to_specific_string(const MPNumber *z, int base, int accuracy, bool trim_zeroes, bool localize, char *target, int target_len);
+void mp_serializer_to_standard_string(MpSerializer *serializer, const MPNumber *z, char **target);
+void mp_serializer_to_specific_string(const MPNumber *z, int base, int accuracy, bool trim_zeroes, bool localize, char **target);
bool mp_serializer_from_string(MpSerializer *serializer, const char *str, MPNumber *z);
const gchar* mp_serializer_get_thousands_separator_text(MpSerializer *serializer);
diff --git a/src/mp.c b/src/mp.c
index 0e46b35..798b1b0 100644
--- a/src/mp.c
+++ b/src/mp.c
@@ -293,6 +293,15 @@ mp_add_real(const MPNumber *x, int y_sign, const MPNumber *y, MPNumber *z)
z->fraction[MP_T + i] = 0;
if (sign_prod >= 0) {
+ /* This is probably insufficient overflow detection, but it makes us
+ * not crash at least.
+ */
+ if (MP_T + 3 < med) {
+ mperr(_("Overflow: the result couldn't be calculated"));
+ mp_set_from_integer(0, z);
+ return;
+ }
+
/* HERE DO ADDITION, EXPONENT(Y) >= EXPONENT(X) */
for (i = MP_T + 3; i >= MP_T; i--)
z->fraction[i] = small_fraction[i - med];
diff --git a/src/unittest.c b/src/unittest.c
index 30de463..8701218 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -79,18 +79,19 @@ test(char *expression, char *expected, int expected_error)
{
MPErrorCode error;
MPNumber result;
- char result_str[1024] = "";
error = mp_equation_parse(expression, &options, &result, NULL);
if(error == 0) {
- mp_serializer_to_specific_string(&result, options.base, 9, true, false, result_str, 1024);
+ char *result_str;
+ mp_serializer_to_specific_string(&result, options.base, 9, true, false, &result_str);
if(expected_error != 0)
fail("'%s' -> %s, expected error %s", expression, result_str, error_code_to_string(expected_error));
else if(strcmp(result_str, expected) != 0)
fail("'%s' -> '%s', expected '%s'", expression, result_str, expected);
else
pass("'%s' -> '%s'", expression, result_str);
+ g_free(result_str);
}
else {
if(error == expected_error)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]