[grisbi-cvs] grisbi/src gsb_real.c, 1.43, 1.44 gsb_real.h, 1.17, 1.18 gsb_real_cunit.c, 1.9, 1.10
Mickaƫl Remars
mykeul at users.sourceforge.net
Thu May 21 11:04:51 CEST 2009
Update of /cvsroot/grisbi/grisbi/src
In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv21543/src
Modified Files:
gsb_real.c gsb_real.h gsb_real_cunit.c
Log Message:
Added new function gsb_real_raw_get_from_string() and its unit-tests
Index: gsb_real.c
===================================================================
RCS file: /cvsroot/grisbi/grisbi/src/gsb_real.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- gsb_real.c 20 May 2009 21:15:06 -0000 1.43
+++ gsb_real.c 21 May 2009 09:04:48 -0000 1.44
@@ -307,6 +307,99 @@
}
+/**
+ * get a gsb_real number from a string
+ * the string can be formatted :
+ * - spaces and the given utf8-encoded thousands separators are ignored
+ * - handle ",", "." and the given utf8-encoded decimal separator
+ * - another character makes a error_real return
+ *
+ * \param string
+ * \param mon_thousands_sep, can be NULL or empty, but only one utf8 sequence
+ * \param mon_decimal_point, can be NULL or empty, but only one utf8 sequence
+ *
+ * \return the number in the string transformed to gsb_real
+ */
+gsb_real gsb_real_raw_get_from_string ( const gchar *string,
+ const gchar *mon_thousands_sep,
+ const gchar *mon_decimal_point )
+{
+ assert ( !mon_thousands_sep || ( g_utf8_strlen ( mon_thousands_sep, -1 ) <= 1 ) );
+ assert ( !mon_decimal_point || ( g_utf8_strlen ( mon_decimal_point, -1 ) <= 1 ) );
+
+ if ( !string)
+ return error_real;
+
+ unsigned mts_len = mon_thousands_sep
+ ? strlen ( mon_thousands_sep )
+ : 0;
+ unsigned mdp_len = mon_decimal_point ? strlen ( mon_decimal_point ) : 0;
+
+ static const gchar *space_chars = " ";
+ static const gchar *decimal_chars = ".,";
+ static const gchar *positive_chars = "+";
+ static const gchar *negative_chars = "-";
+
+ unsigned nb_digits = 0;
+ gint64 mantissa = 0;
+ gint8 sign = 0;
+ gint8 dot_position = -1;
+ const gchar *p = string;
+ for ( ; ; )
+ {
+ if ( g_ascii_isdigit ( *p ) )
+ {
+ mantissa *= 10;
+ mantissa += ( *p - '0' );
+ if ( mantissa > G_MAXLONG )
+ return error_real;
+ if ( sign == 0 ) sign = 1; // no sign found yet ==> positive
+ ++nb_digits;
+ ++p;
+ }
+ else if ( *p == 0 ) // terminal zero
+ {
+ gint exponent = ( dot_position >= 0 )
+ ? nb_digits - dot_position
+ : 0;
+ gsb_real result = { sign * mantissa, exponent };
+ return result;
+ }
+ else if ( strchr ( space_chars, *p )
+ || ( mts_len && ( strncmp ( p, mon_thousands_sep, mts_len ) == 0 ) ) )
+ {
+ // just skip spaces and thousands separators
+ p = g_utf8_find_next_char ( p, NULL );
+ }
+ else if ( strchr ( decimal_chars, *p )
+ || ( mdp_len && ( strncmp ( p, mon_decimal_point, mdp_len ) == 0 ) ) )
+ {
+ if ( dot_position >= 0 ) // already found a decimal separator
+ return error_real;
+ dot_position = nb_digits;
+ p = g_utf8_find_next_char ( p, NULL );
+ }
+ else if ( strchr ( negative_chars, *p ) )
+ {
+ if ( sign != 0 ) // sign already set
+ return error_real;
+ sign = -1;
+ ++p;
+ }
+ else if ( strchr ( positive_chars, *p ) )
+ {
+ if ( sign != 0 ) // sign already set
+ return error_real;
+ sign = 1;
+ ++p;
+ }
+ else // unknown char ==> error
+ {
+ return error_real;
+ }
+ }
+}
+
/**
* get a real number from a string
Index: gsb_real_cunit.c
===================================================================
RCS file: /cvsroot/grisbi/grisbi/src/gsb_real_cunit.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- gsb_real_cunit.c 20 May 2009 21:15:06 -0000 1.9
+++ gsb_real_cunit.c 21 May 2009 09:04:48 -0000 1.10
@@ -73,6 +73,237 @@
CU_ASSERT_EQUAL(0, val.exponent);
}
+void gsb_real_cunit__gsb_real_raw_get_from_string()
+{
+ gsb_real val;
+ // NULL ==> error
+ val = gsb_real_raw_get_from_string ( NULL, NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ val = gsb_real_raw_get_from_string ( "", NULL, NULL );
+ // empty ==> 0
+ CU_ASSERT_EQUAL ( 0, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ val = gsb_real_raw_get_from_string ( "0", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ val = gsb_real_raw_get_from_string ( "1", NULL, NULL );
+ CU_ASSERT_EQUAL ( 1, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ val = gsb_real_raw_get_from_string ( "12", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // ignore left spaces
+ val = gsb_real_raw_get_from_string ( " 12", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // ignore right spaces
+ val = gsb_real_raw_get_from_string ( "12 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // ignore left-middle-right spaces
+ val = gsb_real_raw_get_from_string ( " 1 2 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // significant zeros
+ val = gsb_real_raw_get_from_string ( "12000", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // useless zeros
+ val = gsb_real_raw_get_from_string ( "00012", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // comma decimal separator
+ val = gsb_real_raw_get_from_string ( "123,45", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12345, val.mantissa );
+ CU_ASSERT_EQUAL ( 2, val.exponent );
+
+ // dot decimal separator
+ val = gsb_real_raw_get_from_string ( "123.45", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12345, val.mantissa );
+ CU_ASSERT_EQUAL ( 2, val.exponent );
+
+ // decimal separator with spaces
+ val = gsb_real_raw_get_from_string ( " 123 . 45 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12345, val.mantissa );
+ CU_ASSERT_EQUAL ( 2, val.exponent );
+
+ // decimal separator with space, and zeroes
+ val = gsb_real_raw_get_from_string ( "0 0123.4500", NULL, NULL );
+ CU_ASSERT_EQUAL ( 1234500, val.mantissa );
+ CU_ASSERT_EQUAL ( 4, val.exponent );
+
+ // decimal separator with space, zero, and value less than 1
+ val = gsb_real_raw_get_from_string ( " 0.123 45 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12345, val.mantissa );
+ CU_ASSERT_EQUAL ( 5, val.exponent );
+
+ // decimal separator with space, no zero, and value less than 1
+ val = gsb_real_raw_get_from_string ( " .123 45 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12345, val.mantissa );
+ CU_ASSERT_EQUAL ( 5, val.exponent );
+
+ // multiple decimal separators ==> error
+ val = gsb_real_raw_get_from_string ( " 123 . 45 . ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // large number
+ val = gsb_real_raw_get_from_string ( "21000000", NULL, NULL );
+ CU_ASSERT_EQUAL ( 21000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // large number with thousands separators
+ val = gsb_real_raw_get_from_string ( "21 000 000", NULL, NULL );
+ CU_ASSERT_EQUAL ( 21000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // large number (largest-1) with thousands separators
+ val = gsb_real_raw_get_from_string ( " 2 147 483 646 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 2147483646, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // largest positive number with thousands separators
+ val = gsb_real_raw_get_from_string ( " 2 147 483 647 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 2147483647, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // too large positive number ==> error
+ val = gsb_real_raw_get_from_string ( " 2 147 483 648 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // too large positive number ==> error
+ val = gsb_real_raw_get_from_string ( " 2 147 483 649 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // very large positive number ==> error
+ val = gsb_real_raw_get_from_string ( " 112 147 483 649 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // 0 with positive sign
+ val = gsb_real_raw_get_from_string ( "+0", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // 0 with negative sign
+ val = gsb_real_raw_get_from_string ( "-0", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // negative number
+ val = gsb_real_raw_get_from_string ( "-1", NULL, NULL );
+ CU_ASSERT_EQUAL ( -1, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // positive number
+ val = gsb_real_raw_get_from_string ( "+1", NULL, NULL );
+ CU_ASSERT_EQUAL ( 1, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // negative two digits
+ val = gsb_real_raw_get_from_string ( "-12", NULL, NULL );
+ CU_ASSERT_EQUAL ( -12, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // positive two digits
+ val = gsb_real_raw_get_from_string ( "+12", NULL, NULL );
+ CU_ASSERT_EQUAL ( 12, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // negative sign at unexpected position ==> error
+ val = gsb_real_raw_get_from_string ( "1-2", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // positive sign at unexpected position ==> error
+ val = gsb_real_raw_get_from_string ( "1+2", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // two signs ==> error
+ val = gsb_real_raw_get_from_string ( "-1+2", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // two signs ==> error
+ val = gsb_real_raw_get_from_string ( "+1-2", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // two signs ==> error
+ val = gsb_real_raw_get_from_string ( "--1", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // decimal separator, no zero, and value less than 1
+ val = gsb_real_raw_get_from_string ( "-.12345", NULL, NULL );
+ CU_ASSERT_EQUAL ( -12345, val.mantissa );
+ CU_ASSERT_EQUAL ( 5, val.exponent );
+
+ // large negative number (largest+1) with thousands separators
+ val = gsb_real_raw_get_from_string ( " -2 147 483 646 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( -2147483646, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // largest negative number with thousands separators
+ val = gsb_real_raw_get_from_string ( " -2 147 483 647 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( -2147483647, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // too large negative number ==> error
+ val = gsb_real_raw_get_from_string ( " -2 147 483 648 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // too large negative number ==> error
+ val = gsb_real_raw_get_from_string ( " -2 147 483 649 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // too large negative number ==> error
+ val = gsb_real_raw_get_from_string ( " -112 147 483 649 ", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+
+ // error number as string ==> error
+ val = gsb_real_raw_get_from_string ( "###ERR###", NULL, NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+}
+
+void gsb_real_cunit__gsb_real_raw_get_from_string__locale()
+{
+ gsb_real val;
+ // locale's thousands separator override comma
+ val = gsb_real_raw_get_from_string ( "1,000.00", ",", "." );
+ CU_ASSERT_EQUAL ( 100000, val.mantissa );
+ CU_ASSERT_EQUAL ( 2, val.exponent );
+
+ // utf8 thousands separator (non-break space)
+ gchar tmp[] = { '1', 0xC2, 0xA0, '0', '0', '0', '.', '0', '0', 0x0 };
+ val = gsb_real_raw_get_from_string ( tmp, "\xC2\xA0", NULL );
+ CU_ASSERT_EQUAL ( 100000, val.mantissa );
+ CU_ASSERT_EQUAL ( 2, val.exponent );
+
+ // non-break space used as separator, but locale says somthing else
+ val = gsb_real_raw_get_from_string ( tmp, "\xC2\xA1", NULL );
+ CU_ASSERT_EQUAL ( 0x80000000, val.mantissa );
+ CU_ASSERT_EQUAL ( 0, val.exponent );
+}
+
void gsb_real_cunit__gsb_real_raw_format_string ( void )
{
gchar *s;
@@ -397,12 +628,14 @@
if(NULL == pSuite)
return NULL;
- if((NULL == CU_add_test(pSuite, "of gsb_real_get_from_string()", gsb_real_cunit__gsb_real_get_from_string))
- || (NULL == CU_add_test(pSuite, "of gsb_real_raw_format_string()", gsb_real_cunit__gsb_real_raw_format_string))
- || (NULL == CU_add_test(pSuite, "of gsb_real_gsb_real_normalize()", gsb_real_cunit__gsb_real_normalize))
- || (NULL == CU_add_test(pSuite, "of gsb_real_add()", gsb_real_cunit__gsb_real_add))
- || (NULL == CU_add_test(pSuite, "of gsb_real_sub()", gsb_real_cunit__gsb_real_sub))
- || (NULL == CU_add_test(pSuite, "of gsb_real_mul()", gsb_real_cunit__gsb_real_mul))
+ if ( ( NULL == CU_add_test( pSuite, "of gsb_real_get_from_string()", gsb_real_cunit__gsb_real_get_from_string ) )
+ || ( NULL == CU_add_test( pSuite, "of gsb_real_raw_get_from_string()", gsb_real_cunit__gsb_real_raw_get_from_string ) )
+ || ( NULL == CU_add_test( pSuite, "of gsb_real_raw_get_from_string() with locale", gsb_real_cunit__gsb_real_raw_get_from_string__locale ) )
+ || ( NULL == CU_add_test( pSuite, "of gsb_real_raw_format_string()", gsb_real_cunit__gsb_real_raw_format_string ) )
+ || ( NULL == CU_add_test( pSuite, "of gsb_real_gsb_real_normalize()", gsb_real_cunit__gsb_real_normalize ) )
+ || ( NULL == CU_add_test( pSuite, "of gsb_real_add()", gsb_real_cunit__gsb_real_add ) )
+ || ( NULL == CU_add_test( pSuite, "of gsb_real_sub()", gsb_real_cunit__gsb_real_sub ) )
+ || ( NULL == CU_add_test( pSuite, "of gsb_real_mul()", gsb_real_cunit__gsb_real_mul ) )
)
return NULL;
Index: gsb_real.h
===================================================================
RCS file: /cvsroot/grisbi/grisbi/src/gsb_real.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- gsb_real.h 20 May 2009 19:49:29 -0000 1.17
+++ gsb_real.h 21 May 2009 09:04:48 -0000 1.18
@@ -28,6 +28,9 @@
gsb_real gsb_real_div ( gsb_real number_1,
gsb_real number_2 );
gsb_real gsb_real_double_to_real ( gdouble number );
+gsb_real gsb_real_raw_get_from_string ( const gchar *string,
+ const gchar *mon_thousands_sep,
+ const gchar *mon_decimal_point );
gsb_real gsb_real_get_from_string ( const gchar *string );
gchar *gsb_real_get_string ( gsb_real number );
gchar *gsb_real_get_string_with_currency ( gsb_real number,
More information about the cvs
mailing list